Joy DOM

Getting started

Add the JoyDom Swift package to an app and render your first Joy DOM document in SwiftUI.

This guide walks through rendering a Joy DOM document in a SwiftUI app, from an empty project to a live view that reacts to events.

Requirements

  • macOS with Xcode 15+ (Swift 5.9 toolchain).
  • A deployment target of iOS 16 / macOS 13 or newer — the platforms the binary ships for. The alpha XCFrameworks are iOS + macOS only; the source package also builds for tvOS and watchOS.
  • No source checkout — JoyDom is distributed as a precompiled Swift package you add via SPM.

Alpha

JoyDom ships as precompiled XCFrameworks (source not included) from j0yhq/joydom-swift. Use the latest release — the API may still change during alpha, so pin the exact version you pick.

Creating your project

Open Xcode and choose File ▸ New ▸ Project.
Pick the App template under iOS (or macOS), then Next.

Set a product name, choose SwiftUI for the interface and Swift for the language, then Next and create.

Already have an app? Skip ahead to Adding JoyDom to your project.

Adding JoyDom to your project

JoyDom is distributed over Swift Package Manager from j0yhq/joydom-swift as precompiled XCFrameworks.

In Xcode, choose File ▸ Add Package Dependencies…

Paste the package URL into the search field:

https://github.com/j0yhq/joydom-swift
Set Dependency Rule to Exact Version and pick the latest published release, then Add Package.
Add the JoyDOM library product to your app target.

The JoyDOM product bundles the flexbox engine that powers JoyDom's layout (how it works), so there's nothing else to add.

Rendering a document

Add a document to your project. Drop a Joy DOM JSON file — say card.json — into your app target so it's bundled as a resource.

card.json
{
  "version": 1,
  "style": {
    ".card": { "display": "flex", "padding": { "value": 16, "unit": "px" } },
    "p": { "display": "flex" }
  },
  "breakpoints": [],
  "layout": {
    "type": "div",
    "props": { "className": ["card"] },
    "children": [{ "type": "p", "children": ["Hello Joy DOM"] }]
  }
}

Download card.json

Import the package.

import SwiftUI
import JoyDOM

Render it. Seed a ComponentRegistry with the built-in primitives — ComponentRegistry.shared is empty by design, so without withDefaultPrimitives() every built-in node renders as a placeholder. (Decoding the bundled JSON into a Spec is covered in Loading documents.)

struct CardScreen: View {
    let spec: Spec
    private let registry = ComponentRegistry().withDefaultPrimitives()

    var body: some View {
        JoyDom(spec: spec, components: registry)
    }
}

Build and run. JoyDom resolves the style cascade and lays the tree out through FlexLayout — that's everything required to render. To resolve @media breakpoints, observe diagnostics, or override a node inline, see Extras.

Where next

  • Events — the binding/emit/onEvent contract in depth.
  • Custom components — render the document's kebab-case node types with your own views.
  • How it works — the decode → cascade → flexbox → SwiftUI pipeline.

On this page