Get a better understanding of Fluid and Fusion for your Neos CMS project
View Slide
@dfeyer on twitter/slackDominique Feyer
@dimaip on twitter/slackDmitri Pisarev
a round trip throughyour presentation layerin Neos
Logicless Templates, Smart Fusion Objects
Conditions
Secret stuff!
secrectStuff = 'Secret stuff!'[email protected] = ${node.context.inBackend}
{secrectStuff}
Loops
{blogPost.title}{blogPost.teaser}
prototype(Your.Site:BlogPostsList) <prototype(Neos.Fusion:Collection) {collection = ${blogPosts}itemName = 'node'itemRenderer = Your.Site:BlogTeaser}
Partials
Website content
prototype(Your.Site:Page) {header = Your.Site:Header}
{header -> f:format.raw()}Website content
Layouts
The content
prototype(Your.Site:MainPage) < prototype(Page) {@process.layout = Your.Site:Components.Layout}
prototype(Your.Site:Components.Layout) <prototype(Neos.Fusion:Template) {templatePath = .../Layout.htmlvalue = ${value}}
structure is everything
collocatecomponent's resources
Fusion/Components/Menu/Menu.fusionMenu.htmlMenu.jsMenu.css
project directory structure
Blog/Blog.fusionBlog.htmlBlog.Document.fusionBlog.Comments.fusionBlog.cssComponents/Menu/Menu.fusionMenu.htmlMenu.jsMenu.cssOverride.fusionShame.fusionRoot.fusionResources/Private/Fusion
Override.fusion
prototype(Neos.Fusion:Collection) {itemName = ‘node’}
Shame.fusion
prototype(Neos.Neos:Page) {googleAnalyticsTrackingCode =Neos.GoogleAnalytics:TrackingCode}
select rendering based on thenode type
root {default {renderPath = ‘page’}}root.blog {@position = ‘before default’condition = ${q(node).is(‘[instanceof Your.Site:Blog]’)}type = ‘Your.Site:Blog.Document’}
root {default {type = ${q(node).property(‘_nodeType') + ‘.Document’}renderPath >}}
prototype(Your.Site:Blog.Document) < prototype(Page) {head.stylesheets.main = …body = Your.Site:Blog}prototype(Your.Site:Blog) < prototype(Neos.Fusion:Template) {templatePath = ‘…’main = Neos.Neos:ContentCollection {nodePath = 'main'}}
fusion prototype generator
'Neos.Neos:Node':options:fusion:prototypeGenerator: ~
'Neos.Neos:Node':options:fusion:prototypeGenerator: Your\Site\Generators\Generator
opinionated template object
prototype(Your.Site:Components.Footer) <prototype(Neos.Fusion:Template) {templatePath = ‘resource://Your.Site/Private/Fusion/Components/Footer/Footer.html’}
prototype(Your.Site:SimpleTemplate) {@class = ‘Your\\Site\\FusionObjects\\TemplateImplementation’}https://gist.github.com/dfeyer/f13c5e35004493956c9fef0bbc5efb0f
prototype(Your.Site:Components.Footer) <prototype(Your.Site:SimpleTemplate)Will automatically look for template inresource://Your.Site/Private/Fusion/Components/Footer/Footer.html
more to come
fusion is justanother language
Your.Site:Bookis notYour.Site:Book
Your.Site:BookNodeTypes.Book.yaml
‘Your.Site:Book':superTypes:'Neos.Neos:Document': true‘Your.Site:SeoMixins': true‘Your.Site:JsonLd.Document’: true
Your.Site:BookBook.fusion
prototype(Your.Site:Book) < prototype(Neos.Fusion:Template)
prototype(Your.Site:Book) {title = ${q(node).property(‘title’)}}
one node typemultiple fusionprototypes
Your.Site:BookYour.Site:Book.DocumentYour.Site:Book.TitleYour.Site:Book.QrCodeYour.Site:Book.SearchResult
one fusion prototypemultiple nodetypes
Your.Site:Defaut.SearchResultYour.Site:Defaut.DocumentYour.Site:Defaut.JsonLd.Document
composition orinheritance… again
prototype(Your.Site:Library) {ownerName = …ownerEmail = …contactName = …contactEmail = …}
prototype(Your.Site:Library) {owner = Your.Site:Personcontact = Your.Site:Personaddress = Your.Site:Address}
‘Your.Site:Library':childNodes:'owner':type: ‘Your.Site:Person''contact':type: 'Your.Site:Person''address':type: 'Your.Site:Address'
naming… again
schema.org
small objectsare beautiful
Neos.Fusion:Valueprototype(Your.Site:Anything) < prototype(Neos.Fusion:Value)
Query
prototype(Your.Site:AllBooks.Query) {value = ${q(site).find(...).get()}}
prototype(Your.Site:LatestBooks.Query) {value = Your.Site:AllBooks.Query {@process.latest = ${Array.slice(value,0,3}}}
Decorator
prototype(Your.Site:Components.Article) {tagName = ‘article’content = ${value}}prototype(Your.Site:Components.Article) < prototype(Neos.Fusion:Tag)
prototype(Your.Site:Book.Teaser) {…@process.wrap = Your.Site:Components.Article}
Neos.Fusion:RawArrayprototype(Your.Site:Anything) < prototype(Neos.Fusion:RawArray)
prototype(Your.Site:Book.Json) {title = ${q(bookNode).property(‘title’)}price = ${Price.get(bookNode)}@process.stringify = ${Json.stringify(value)}}prototype(Your.Site:Book.Json) < prototype(Neos.Fusion:RawArray)
Neos.Fusion:RawCollectionNeos.Fusion:Tag
take care of yourdomain logic
${q(node).property('discount') > 0 ? q(node).property('price') -(q(node).property('price') * q(node).property('discount') / 100) :q(node).property(‘price’)}
‘Your.Site:Book’:class: Your\Site\Domain\Model\Book
${book.price}
start from scratch
fusion inflow application
workshop anyone ?
hijack us
demo site reboot
in the makinghttps://github.com/Flowpack/fusion-bp