WHAT?

A server-driven UI stack for fully native prototypes

Not a cross-platform framework, and not a web page in a native shell. The server authors a typed tree; web, iOS and Android each render it with their own native components. Below is every part of the stack — there are eight, and you can read all of them.

Cross-platform prototyping that scales

Built for experimentation ▍Ready for scaling to production

See SDUX as protoyping tool that lets you play with Web, iOS and Android at the same time. You focus on the content and each client renders it's fully native ui. This way you get the best look whilst keeping the focus on your product.

The eight parts

01 ▍The SDUX Page

One tree, three renderers

A page is a typed tree — nav, header, main, footer — authored once on the server. Web renders it in Heex, iOS in SwiftUI, Android in Jetpack Compose. No web view and no shared UI code: each platform reads the same tree and answers in its own idiom.

02 ▍The design components

Atoms, molecules, organisms

Every node in that tree comes from one library. Atoms are the smallest named things — a heading, a link, an image. Molecules compose atoms into a unit; organisms own a screen's width. A component exists once all three platforms can render it, which is what stops one library quietly becoming three.

The component map →

03 ▍The OpenAPI spec

A single source of truth

The contract is not documentation written after the fact. One Elixir module generates it, and everything downstream is generated from that. A shape that isn't in the spec is a shape no platform can name.

Read the spec ⏺

04 ▍Typed HTTP clients

Apple's generator and Fabrikt

Swift OpenAPI Generator and Fabrikt turn that same spec into Swift and Kotlin models. Rename a field on the server and the clients stop compiling — a broken contract becomes a build error on a laptop instead of a crash in someone's hand.

05 ▍Scalability

Phoenix and Elixir on the BEAM

Every request renders in its own lightweight process. A page that fails takes itself down and nothing with it, latency stays flat as traffic climbs, and the same PubSub that serves these pages relays live audio to the phones.

06 ▍Deployment

Docker and mise

One task runner for a three-headed repo: regenerate the spec, regenerate the clients, run the suites, build the container, ship it. The commands a contributor types are the commands CI runs, which is why neither surprises the other.

07 ▍Declarative content

json.ex files

A page is a plain Elixir module that returns structs. No CMS and no template language — content is data, checked by the compiler, versioned in git, and reviewable as a diff. This page is one such file, and so is every page you have read here.

08 ▍Every endpoint

HTML and JSON

The same route serves a rendered page to a browser and the raw tree to an app. There is no second API drifting out of step with the site, because the site is the API. The apps are reading exactly this:

This page, as JSON ⏺

The newest parts, in use

Everything below shipped this week and is doing its job rather than posing for a screenshot. A site that is itself server-driven can prove the claim instead of illustrating it.

This is an SduxBanner

Four severities, each resolved from the theme's state tokens, so it follows the palette into dark mode. Until this shipped, the library could render content and could not say “that didn't save.”

Is this a cross-platform framework?

No. There is no shared UI code and no web view in a shell. The server sends a typed tree; SwiftUI, Jetpack Compose and Heex each render it with their own components. That is why a platform can lean into what it is good at instead of compromising across three.

Do I need an App Store release to change a screen?

No. Your UI is data. Move a button, add a section, retheme a whole tenant — the clients already know how to render it. You need a release when you add a component the clients have never seen.

What does a new component cost?

A struct, a schema entry, and one renderer per platform. The three components on this page were a day's work between them — which is the honest answer to the usual worry that a server-driven contract makes you poorer at UI.

The component map →