How it works
The pipeline that turns a Joy DOM document into native SwiftUI — layout powered by the flexbox-swift engine.
JoyDom turns a Joy DOM JSON document into a live SwiftUI view tree in four stages. It owns decode, cascade, and render; the layout stage is delegated to flexbox-swift, a Swift flexbox engine, so flex behavior matches the web spec rather than being re-approximated in SwiftUI.
The four stages
- Decode —
SpecisCodable, so the JSON document decodes straight into the model: a tree ofNodes plus thestylerecord andbreakpoints. - Cascade — selectors (
div,.class,#id) and the active breakpoint resolve against theViewportinto one fully-computed style per node — exactly the CSS cascade, applied ahead of layout. - Layout — each node's box style (
display,flexDirection,gap,padding, sizing, …) is handed to FlexBox (flexbox-swift), which computes the frame for every node, the same way a browser's flexbox engine would. - Render —
JoyDomwalks the laid-out tree and emits native views: flex containers through aFlexLayoutcontainer, text through SwiftUIText,imgthroughAsyncImage, and your custom components wherever theirtypeappears.
Powered by flexbox-swift
The layout engine
Layout is delegated to j0yhq/flexbox-swift — a
standalone Swift flexbox implementation exposed as the FlexLayout product. Keeping a real
flexbox engine in the pipeline (rather than mapping CSS onto SwiftUI's stacks) is what lets the
Swift renderer match the web and Kotlin renderers pixel-for-pixel on the shared conformance
fixtures.
Because the engine owns layout, the styles you write in a document behave like CSS flexbox: flex-grow/flex-shrink/flex-basis, align-items/justify-content, wrapping, gaps, and the box model all resolve the same as they do in the React renderer.
Quick showcase
To see the whole pipeline end to end, run JoyDOMShowcase — one self-contained file, cross-platform (iOS + macOS), no images or external state. It renders an inline JSON card with the built-in primitives plus a single custom badge component, and a lone .onEvent handler increments a like count, re-decoding the document on each tap.
It ships as a runnable example in the public package, so you can clone and run it directly — swift run builds the macOS app and pulls the JoyDOM binary automatically:
git clone https://github.com/j0yhq/joydom-swift.git
cd joydom-swift/Example
swift run JoyDOMShowcaseiOS / requirements
Needs Xcode 16+ (Swift 5.9+), macOS 13+ or iOS 16+. swift run launches the macOS app; to run on
iOS instead, open Example/Package.swift in Xcode and run the JoyDOMShowcase scheme on a
simulator. To wire JoyDom into your own app from scratch, see Getting started.
JoyDOMShowcase is deliberately minimal; the joy-dom monorepo additionally has a richer Native-vs-Web-vs-Kotlin conformance demo (JoyDomDemo) for contributors.
Where next
- Custom components — slot your own SwiftUI / UIKit / WebKit views into the render stage.
- Interactive — drive the whole pipeline from external state.
- API reference (DocC) ↗ — every type the renderer exposes.