Shortcut-Components to have the same content on multiple sites

Hello, I am relatively new to NEOS so if there is an obvious solution for this I am sorry.
We want to try out NEOS as the new CMS for our website. One part of this website is a collection of programming course concepts with specific content for each course and non-specific content concerning organization and schedule of the courses.
We do not want to copy the non-specific content to each page because it would be a hassle to update the content on each site when necessary.
Is there an easy way to create shortcut components acting like a content collection but having the same content across all sites?

Our ideas:

  1. Pull the content from one or several “magic sites” via FlowQueries
  2. Write a backend plugin
  3. Change the content of all instances of a component in the database when one changes

Our thoughts on them:

  1. We are stuck on the question of how to render a node from a FlowQuery-context. Additionally, this feels a little hacky, is unintuitive for the content editors, not really scalable and a misuse of the site document type
  2. Seems to be very time-demanding, otherwise probably the best solution
  3. We don’t know if this is possible, feasible or scalable

Does any of you have an idea for this problem?

Hi @SiuhnexusAtHS,

for such use cases, Neos has so called Node references. This means, you can select another node (either by the editor in the sidebar or by the developer with a fixed path/id) and render the same content. There is also a nodetypes package for this, so you can simply look it up from there:

Also you could have a look at the tutorial for a shared footer:

https://docs.neos.io/tutorials/editing-a-shared-footer-across-all-pages

I hope this helps, otherwise feel free to ask again.

Kind regards,

Benjamin

Hi @ SiuhnexusAtHS!

I am quite new to NEOS, but as far as I understand(!) I have a very similar use case, which I just solved with advise and a lot of friendly and patient help of the community (BIG thenks again to all of you!).
I am writing a new tutorial about the topic (the shared-footer-tutorial did not work for me, I am not sure why) but it might still take some days, so for now in short:

  1. We created a NodeType for specific Content and
  2. A NodeType ContentCollection restricted to only this NodeType.
  3. We created a NodeType for a Page to hold this kind of Content Collection in its ‘main’ childNode.
    Like this the Editor has a place to only add the specific Type of Content.
  4. We created a Fusion Object to get the Content of the specific Page using Flow Queries
  5. We included this Fusion Object in my main Page Template - so the Content shows on every page.

Could well be, it can be still optimized, but this should be a working example for NEOS 8.3, maybe you can adjust it for you:


1. NodeType for Content (.yaml file)

'Vendor.Site:Content.Teaser':
  superTypes:
    'Neos.Neos:Content': true
    'Neos.NodeTypes.BaseMixins:ImageMixin': true
    [...]
  ui:
    label: 'Teaser'
    icon: picture
  properties:
  [...]

2. NodeType for ContentCollection (.yaml file)

'Vendor.Site:Collection.Content.Teaser':
  superTypes:
    'Neos.Neos:ContentCollection': true
    'Neos.Neos:Content': true    
  ui:
    label: 'Teaser List'
  constraints:
    nodeTypes:
      '*': false
      'Vendor.Site:Content.Teaser': true

3. NodeType for Page (.yaml file)

'Vendor.Site:Document.TeaserContainer':
  superTypes:
    'Neos.Neos:Document': true
  ui:
    icon: fas fa-folder
    label: 'Teaser Container'
  childNodes:
    main:
      type: 'Vendor.Site:Collection.Content.Teaser'

4. Object for fetching the content (.fusion file)

prototype(Vendor.Site:TeaserList) < prototype(Neos.Neos:ContentCollection) {

    @context.node = ${q(site).find('[instanceof Vendor.Site:Document.TeaserContainer]').children('main').get(0)}

    content {
       items = ${q(site).find('[instanceof Vendor.Site:Document.TeaserContainer]').children('main')}
    }
}

@context.node’ fetches the correct site using the Page Type.
‘content.items’ fetches the Content Collection ‘main’ on that page.

Just to show the potential: we spiced up the Flow Query to show only three randomly chosen elements on every page call…

   items = ${Array.Slice(Array.Shuffle(q(site).find('[instanceof Vendor.Site:Document.TeaserContainer]').children('main').children()), 0, 3)}

…which then also leads to switch this kind of Collection to “uncached”:

    @cache {
        mode = 'uncached'
        context {
            1 = "site"
            2 = "node"
            3 = "documentNode"
        }
    }

5. Adding to the Template (.fusion file/files)

  body = Vendor.Site:Component.Template.Default {
    [...]
    teaserlist = Vendor.Site:TeaserList
    [...]
    }

and of course

      {props.teaserlist}

at the appropriate places, depending on your way of doing it.

hope the helps…

have a great day!
oe

Thank you both for your very helpful answers! @benjamink your mentioned package is the simple solution I needed. It can be used to build up a structure like yours @dasoe to make it all work.
In my experiments with ContentCollection-like nodes copying the data via FlowQuery the copied nodes were always editable in the backend, but surely you found a way to prevent that in your solution @dasoe.

If you do not want the referenced nodes to be editable at all places they were referenced, the mentioned package already handles this. Have a look at nodetypes-contentreferences/Resources/Private/Fusion/Root.fusion at 8.4 · neos/nodetypes-contentreferences · GitHub

Yes, I noticed that, sorry for my unclear answer. That’s one of the reasons why I really like this package. Thank you again!