Fusion Best Practises in detail

Hi everyone

Before starting with new Neos projects, we are currently taking the time to discuss the use of best practises in Atomic Fusion. As we had some interesting discussions - especially about the separation of integration and presentation - I’d like to hear other people’s opinion about some topics.

Boundary between integration and presentation

I assume that in general, it is clear that a presentational component should never work with a Node object. Therefore, e.g. a URI to a node should be created in the integration part and passed as a prop (linkUri) to the presentational component. Agreed?

Apart from that, would you

  • … still use EEL helpers in a presentational component, e.g. to format a DateTime object, or should this be done in the integration part and just be passed as a string?
  • … create a srcset or something similar in the integration part and just pass the srcset or an img tag as a string to the presentation component?

Nested Fusion components

Would you still consider nesting two Fusion components a best practise:

prototype(Visol.FoobarCom:Component.Molecule.Event) < prototype(Neos.Fusion:Component) {
    title = ''
    date = null
    renderer = Neos.Fusion:Component {
        @apply.props = ${props}
        dateFormatted = ${props.date ? Date.formatCldr(props.date, 'd. MMMM yyyy') : ''}
        renderer = afx`
            <div class="event">
                <h2>{props.dateFormatted}: {props.title}</h2>
            </div>
        `
    }
}

The reasoning here was that “locally calculated” properties would not be on the same level as “passed” properties. Is there another reason for this pattern?

Thanks for sharing your thoughts!

  • Formatting DateTime via Eel is imho ok in presentation but you can also pass rendered dates as string if you want to be extra clean
  • in general I would consider every side effect free eel ok’ish … simple expressions should be preferred
  • for images we pass a Sitegeist.Kaleidoscope imageSource to the presentation that can then be used by the presentation to render the srcset
  • nested fusion components should nowadays be avoided in favor of @private

How I see the best practises:

  • Agreed, no node inside presentation
  • I prefer to only send formatted strings for dates to the presentation
  • We use EelHelpers in presentation, sometimes even i18n
  • We ONLY send ImageSource from Kaleidoscope to the presentation for images and LinkSource from CodeQ.Link for links

Instead of nested Component, you can use @private in latest Neos.

PS: Martin was faster, pretty much the same ideas :slight_smile:

1 Like

Yes you can use @private like this :wink: (Since 8.3)

https://neos.readthedocs.io/en/stable/References/NeosFusionReference.html#neos-fusion-component

prototype(Visol.FoobarCom:Component.Molecule.Event) < prototype(Neos.Fusion:Component) {
    title = ''
    date = null
    @private {
        dateFormatted = ${props.date ? Date.formatCldr(props.date, 'd. MMMM yyyy') : ''}
    }
    renderer = afx`
        <div class="event">
            <h2>{private.dateFormatted}: {props.title}</h2>
        </div>
    `
}

About the naming with Molecule Atom Organism and so on: I found it hard for me to distinguish the right type. Also at first this naming lead me to believe i should avoid to use composition of presentational components in the integration and rather create a big Organism thingy.

Instead i have seen that people like to group their components into two groups: Block and Layout.

Block being simple units like Text, Headline, Button, Icon, Link and Figure
and Layout being composites like Grid, Row, Stack and Card

Regarding naming i would suggest to implement the structure of the design and thus use the naming as specified by the designer. Atomic design structures on a non atomic design will lead to issues.

The distinction into Layout / Block Components works well in many cases for us. However i would encourage teams to find their own structure.

1 Like

Thanks for sharing your thoughts, this is very valuable to me.

As we don’t have a Neos 8 yet, I had completely forgotten about @private. As far as I can see, this will also lead to less usage of @context because the private properties are passed down to the Fusion child objects. At least it looks that way from the example in the docs.

1 Like

Since 8.2 ( Neos 8.2 “Native loading of Fusion files from the NodeTypes folder”) I also started to put the “Integration” fusion files into the NodeTypes folder along with the yaml files. Then the Fusion folder itself only contains the “presentational” Components and occasionally Helpers.

For me the Atomic structure with atoms, molecules, organisms and templates works quite well, I just added Webpage as a fifth level on top, representing an AbstractPage rendering Neos.Neos:Page. Keeping that deep hierarchy helps me thinking about reusability.

and even if it doesn’t seem popular :wink: I also accept node, date and other objects in my presentational components. e.g. I also consider :Component.Molecule.Menu a Presentation Component, and there I have the startingPoint as parameter (set to {site} as default instead of an array of links… but I guess this could also be implemented with another prototype as a kind of middleware like ImageSource or LinkSource if you work with Monocle and want to be able to render it without node context.