$30 off During Our Annual Pro Sale. View Details »

Atomic.Fusion & Sitegeist.Monocle - Neos Conference 2017

Atomic.Fusion & Sitegeist.Monocle - Neos Conference 2017

An presentation of sitegeists approach for component based fusion development that enabled the creation of living styleguide in Neos.

Sitegeist

March 31, 2017
Tweet

More Decks by Sitegeist

Other Decks in Technology

Transcript

  1. Atomic.Fusion + Sitegeist.Monocle
    Wilhelm Behncke & Martin Ficzel

    View Slide

  2. Full Stack Developer


    +sitegeist
    [email protected]
    twitter: @WilhelmBehncke

    slack: @wbehncke


    Neos Team-Member, Musician
    Wilhelm Behncke

    View Slide

  3. Backend Developer


    +sitegeist
    [email protected]
    twitter/slack: @kopfaufholz


    Neos Team-Member,
 2 Kids, Climber
    Martin Ficzel

    View Slide

  4. Fluid Partials and Logic in Templates

    View Slide

  5. Evolution of an Image Partial

    Part 1 - Frontend creates Image-Partial

    View Slide

  6. Evolution of an Image-Partial

    Part 2 - Backend alters Partial to render image.

    View Slide

  7. Evolution of an Image Partial



















    Part 3 - Backend adds optional link

    View Slide

  8. The challenges for bigger projects
    1. Partials don't scale well
    2. Proper context boundaries are missing
    3. That way Frontend to backend collaboration is a one way trip

    View Slide

  9. Collaboration

    View Slide

  10. Styleguides

    View Slide

  11. Living Styleguides

    View Slide

  12. We want a living-styleguide for Neos

    View Slide

  13. We want a living-styleguide for Neos
    What do we have to do to get it?

    View Slide

  14. Keep your filthy state off my views!

    View Slide

  15. View Slide

  16. View Slide

  17. View Slide

  18. View Slide

  19. View Slide

  20. View Slide

  21. View Slide

  22. View Slide

  23. View Slide

  24. Components are everywhere
    React, Preact, Inferno...
    Angular, Ember, Vue.js...
    Web Components

    View Slide

  25. Components
    Solely determined by their attributes, (Side-effect free)
    Single purpose
    Encapsulate everything that is needed to re-use them

    View Slide

  26. Atomic.Fusion

    View Slide

  27. Atomic.Fusion - Component
    prototype(Vendor.Site:Component.Atom.Link) < prototype(PackageFactory.AtomicFusion:Component) {
    # component api
    text = ''
    uri = ''
    # component renderer
    renderer = Neos.Fusion:Tag {
    tagName = 'a'
    content = Neos.Fusion:Array {
    text = ${props.text}
    }
    attributes.src = ${props.uri}

    }
    }

    View Slide

  28. Atomic.Fusion - Composition
    prototype(Vendor.Site:Component.Organism.Header) < prototype(PackageFactory.AtomicFusion:Component) {
    renderer = Neos.Fusion:Array {
    funcNav = Vendor.Site:Component.Molecule.FuncNav
    mainNav = Vendor.Site:Component.Molecule.MainNav
    home = Vendor.Site:Component.Atom.Link {
    src = '/'
    }
    }
    }

    View Slide

  29. Atomic.Fusion
    Not to be confused with
    Atomic.Design
    Nuclear.Fusion
    Github: https://github.com/PackageFactory/atomic-fusion
    Packagist: composer require packagefactory/atomicfusion
    Used in production

    View Slide

  30. Sitegeist.Monocle

    View Slide

  31. Sitegeist.Monocle - Meta Data
    prototype(Vendor.Site:Component.Atom.Button) {
    @styleguide {
    # Meta Data
    path = 'atoms.basic'
    title = 'Button'
    description = 'generic Buttom Atom’
    # Preview Data
    props {
    content = 'Lorem Ipsum'

    tagName = 'a'
    }
    }
    }

    View Slide

  32. Sitegeist.Monocle - Preview Data
    prototype(Vendor.Site:Component.Atom.Button) {
    @styleguide {
    # Meta Data
    path = 'atoms.basic'
    title = 'Button'
    description = 'generic Buttom Atom’
    # Preview Data
    props {
    content = 'Lorem Ipsum'

    tagName = 'a'
    }
    }
    }

    View Slide

  33. View Slide

  34. View Slide

  35. View Slide

  36. View Slide

  37. Sitegeist.Monocle
    Github: https://github.com/sitegeist/Sitegeist.Monocle
    Packagist: composer require sitegeist/monocle
    It is used in Production
    Has no effect the on the neos-fusion runtime
    It does'nt need a database

    View Slide

  38. Atomic.Fusion - Mapping

    View Slide

  39. Atomic.Fusion - Mapping Content
    prototype(Vendor.Site:Content.Teaser) < prototype(Neos.Fusion:Renderer) {
    renderer = Vendor.Site:Component.Molecule.Teaser {
    layout = ${q(node).property('layout')}
    title.content = ${q(node).property('title')}

    description {
    content = ${q(node).property(‚description')}

    @process.makeEditable = Neos.Neos:ContentEditableWrapping

    @process.makeEditable.propertyName = 'description'

    }
    }
    @process.contentElementWrapping = Neos.Neos:ContentElementWrapping
    }

    View Slide

  40. Atomic.Fusion - Mapping Content
    prototype(Vendor.Site:Content.Teaser) < prototype(Neos.Fusion:Renderer) {
    renderer = Vendor.Site:Component.Molecule.Teaser {
    layout = ${q(node).property('layout')}
    title.content = ${q(node).property('title')}

    description {
    content = ${q(node).property(‚description')}

    @process.makeEditable = Neos.Neos:ContentEditableWrapping

    @process.makeEditable.propertyName = 'description'

    }
    }
    @process.contentElementWrapping = Neos.Neos:ContentElementWrapping
    }

    View Slide

  41. Atomic.Fusion - Mapping Content
    prototype(Vendor.Site:Content.Teaser) < prototype(Neos.Fusion:Renderer) {
    renderer = Vendor.Site:Component.Molecule.Teaser {
    layout = ${q(node).property('layout')}
    title.content = ${q(node).property('title')}

    description {
    content = ${q(node).property(‚description')}

    @process.makeEditable = Neos.Neos:ContentEditableWrapping

    @process.makeEditable.propertyName = 'description'

    }
    }
    @process.contentElementWrapping = Neos.Neos:ContentElementWrapping
    }

    View Slide

  42. Atomic.Fusion - Mapping Documents
    prototype(Vendor.Site:Document.Page) < prototype(Neos.Neos:Page) {
    body = Vendor.Site:Component.Template.Page {
    navigationItems = Neos.Fusion:RawCollection {
    collection = ${q(site).children('[instanceof Neos.Neos:Document]').get()}
    itemName = 'item'
    itemRenderer = Neos.Fusion:RawArray {
    title = ${q(item).property('titleOverride') ? q(item).property('titleOverride') : q(item).property(
    uri = Neos.Neos:NodeUri {
    node = ${item}
    }
    }
    }
    content = Neos.Neos:PrimaryContent {
    nodePath = 'main'
    }
    }
    }

    View Slide

  43. Atomic.Fusion - Mapping Documents
    prototype(Vendor.Site:Document.Page) < prototype(Neos.Neos:Page) {
    body = Vendor.Site:Component.Template.Page {
    navigationItems = Neos.Fusion:RawCollection {
    collection = ${q(site).children('[instanceof Neos.Neos:Document]').get()}
    itemName = 'item'
    itemRenderer = Neos.Fusion:RawArray {
    title = ${q(item).property('titleOverride') ? q(item).property('titleOverride') : q(item).property(
    uri = Neos.Neos:NodeUri {
    node = ${item}
    }
    }
    }
    content = Neos.Neos:PrimaryContent {
    nodePath = 'main'
    }
    }
    }

    View Slide

  44. Atomic.Fusion - Mapping Documents
    prototype(Vendor.Site:Document.Page) < prototype(Neos.Neos:Page) {
    body = Vendor.Site:Component.Template.Page {
    navigationItems = Neos.Fusion:RawCollection {
    collection = ${q(site).children('[instanceof Neos.Neos:Document]').get()}
    itemName = 'item'
    itemRenderer = Neos.Fusion:RawArray {
    title = ${q(item).property('titleOverride') ? q(item).property('titleOverride') : q(item).property(
    uri = Neos.Neos:NodeUri {
    node = ${item}
    }
    }
    }
    content = Neos.Neos:PrimaryContent {
    nodePath = 'main'
    }
    }
    }

    View Slide

  45. The challenges for bigger projects
    1. Partials don't scale well
    Presentational components do!
    2. Proper context boundaries are missing
    Components have boundaries
    In Fusion you can cross boundaries if needed
    3. Frontend to backend collaboration works only in one direction
    Seperate presentational components enable independent.
    The Component API defines the interface between crafts.

    View Slide

  46. That's it

    View Slide

  47. Experimental content ahead

    View Slide

  48. Fusion Components - Today
    prototype(PackageFactory.AtomicFusion.AFX:Example) < prototype(PackageFactory.AtomicFusion:Component) {
    title = 'title text'
    subtitle = 'subtitle line'
    imageUri = 'https://dummyimage.com/600x400/000/fff'
    renderer = Neos.Fusion:Tag {
    tagName = 'div'
    content = Neos.Fusion:Array {
    headline = Neos.Fusion:Tag {
    tagName = 'h1'
    content = Neos.Fusion:Array {
    1 = ${props.title}
    }
    attributes.class = 'headline'
    }
    subheadline = Neos.Fusion:Tag {
    tagName = 'h2'
    content = Neos.Fusion:Array {
    1 = ${props.subtitle}
    }
    attributes.subheadline = 'subheadline'
    @if.hasSubtitle = ${props.subtitle ? true : false}
    }
    image = PackageFactory.AtomicFusion.AFX:Image {

    View Slide

  49. Fusion Components - AFX
    Github: https://github.com/PackageFactory/atomic-fusion-afx
    EXPERIMENTAL CODE ... WILL LIKELY CHANGE ... BUT IT WORKS
    prototype(PackageFactory.AtomicFusion.AFX:Example) < prototype(PackageFactory.AtomicFusion:Component) {
    title = 'title text'
    subtitle = 'subtitle line'
    imageUri = 'https://dummyimage.com/600x400/000/fff'
    renderer = afx`

    {props.title}
    {props.subtitle}


    `
    }

    View Slide

  50. Fusion Components - AFX
    Github: https://github.com/PackageFactory/atomic-fusion-afx
    EXPERIMENTAL CODE ... WILL LIKELY CHANGE ... BUT IT WORKS
    prototype(PackageFactory.AtomicFusion.AFX:Example) < prototype(PackageFactory.AtomicFusion:Component) {
    title = 'title text'
    subtitle = 'subtitle line'
    imageUri = 'https://dummyimage.com/600x400/000/fff'
    renderer = afx`

    {props.title}
    {props.subtitle}


    `
    }

    View Slide

  51. Fusion Components - AFX
    Github: https://github.com/PackageFactory/atomic-fusion-afx
    EXPERIMENTAL CODE ... WILL LIKELY CHANGE ... BUT IT WORKS
    prototype(PackageFactory.AtomicFusion.AFX:Example) < prototype(PackageFactory.AtomicFusion:Component) {
    title = 'title text'
    subtitle = 'subtitle line'
    imageUri = 'https://dummyimage.com/600x400/000/fff'
    renderer = afx`

    {props.title}
    {props.subtitle}


    `
    }

    View Slide

  52. What to take home
    Don't use Partials
    Components in Fusion are a thing, use them today!
    Sitegeist.Monocle helps to develop reusable Components.

    View Slide

  53. Copyright: Larry D. Moore [CC BY-SA 3.0 oder GFDL], via Wikimedia Commons

    View Slide

  54. Copyright: By Alan Chia (Lego Color Bricks) [CC BY-SA 2.0], via Wikimedia Commons

    View Slide

  55. Copyright: elPadawan [CC BY-SA 2.0], via flickr.com/photos/elpadawan/8505316460

    View Slide

  56. Thank you
    and good luck

    View Slide