SDUI for Swift: a practical definition
SDUI for Swift is a JSON envelope, an open widget registry, and a renderer. Not a new language, not a downloaded script.
SDUI for Swift is three pieces you can point at in a repo: a JSON envelope, an open widget registry, and a renderer that emits SwiftUI. It is not a new UI language. It is not a script you download at runtime. It is data plus views you already compiled.
Android and Compose posts use "SDUI" as a slogan. Swift teams search the same letters and land on gists with a closed enum and a switch. That gist is a prototype. A definition you can implement has to survive unknown types, nested widgets, and Swift 6.
A definition that fits in a paragraph#
The backend returns a page document. The Swift client decodes it into models (PageModel and friends in FlowCore). Each widget has a type string and a data object. WidgetRegistry maps that string to a WidgetView. FlowPageView walks sections and asks the registry for a view. Taps become ActionData values a dispatcher handles.
If your stack does not have those seams, you have a one-off JSON screen, not SDUI for Swift.
Not a new language#
The payload is JSON. The views are SwiftUI. Designers do not learn a DSL unique to your company unless you build that on top. Flow-UI's contract is pages, sections, widgets, layout, and atoms (TextData, ColorData, ImageData, FontData). That is a schema, not a programming language.
You will still write Swift for every new widget type. The server can rearrange types that exist. It cannot invent a gesture you did not ship.
Not a downloaded script#
Apple's Guideline 2.5.2 is about executable code that was not in the binary you submitted. Declarative JSON that selects among compiled widgets is data. JavaScript you eval is not. This post is not legal advice. Read the guideline.
The practical test: could a reviewer explain the UI as "the app already contains these views; the server picks among them"? If you need a runtime interpreter, you have left SDUI as Swift teams mean it.
The three products in the package#
Flow-UI splits the work so a host app can take only what it needs.
FlowCore is the envelope, atoms, PageLoader protocol, mutations, and decode diagnostics. It does not import SwiftUI.
FlowRender is WidgetRegistry, FlowPageView, PageStore, actions, and UIKit hosting. This is the renderer.
FlowWidgets is eight starter widgets. They are examples. Last registration wins, so you override them from the app target.
PageLoader stays in your app.
URLSession, a fixture, GraphQL: all valid. The framework performs no HTTP.
Open registry, not a closed enum#
A Codable enum of widgets cannot represent a type the enum does not name. Synthesis looks tidy in a tutorial. Production traffic is messy. Marketing ships hero_v3 while 10% of users are a version behind.
An open registry stores decode and AnyView builder closures together. Registration is generic: register<V: WidgetView>(_ viewType: V.Type). That is the only erasure point. Unknown strings follow UnknownWidgetPolicy: placeholder in debug, skip in release, unless you pass a policy into the initializer.
What "practical" excludes#
It excludes a built-in router. Deeplinks are host ActionHandlers.
It excludes a built-in cache. Cache inside PageLoader.
It excludes a guarantee that you will skip App Review for new features. New widget types are a binary. Layout of existing types is data.
It excludes replacing MapKit, a game canvas, or a latency-critical camera UI. Those stay handwritten SwiftUI or UIKit, optionally wrapped as one widget.
How this differs from Android posts#
Compose SDUI articles often start from a sealed class of UI nodes. Swift's closest cousin is a closed enum with associated values. Both look elegant in a gist. Both freeze the catalogue in a type the compiler owns. Swift 6 then adds @MainActor and sendability, which is why WidgetView is main-actor isolated and why the registry stores @Sendable closures created in a generic register function.
If you are translating an Android design doc, keep the envelope and throw away the sealed class. The Swift shape is an open table of type strings.
A note on products versus slogans#
"SDUI library" and "SDUI framework" are search phrases, not SKUs. Flow-UI is a Swift package with three products. There is no paid tier. MIT licence. If you only need the schema in a test target, import FlowCore without SwiftUI.
Install path#
Add the Swift package from GitHub, iOS 17 or later, because Observation and modern scroll APIs are the renderer’s floor. There are no compatibility shims for iOS 16.
Present FlowPageView(store:) in SwiftUI. In UIKit, FlowHostingController wraps the same view.
Questions this article should close#
Is this the same as a headless CMS?#
A headless CMS can emit HTML or JSON. SDUI for Swift only starts when that JSON is a page envelope and the client is a widget registry. Contentful plus a WebView is not this. Contentful plus a page document plus FlowPageView can be.
Do I need a new backend team?#
You need someone who owns the page document. That can be the existing API team with one extra route. It cannot be iOS hardcoding the tree and calling it server driven.
Can I start with one page?#
Yes. Home or help. Register starters, one product widget, one loader. Expand the catalogue when a real surface needs a type.
What about Android?#
One schema, native renderers is the industry pattern. Flow-UI is the SwiftUI renderer. Android is a different codebase that should speak the same envelope if you want one backend.
Related reading#
SDUI for Swift is envelope, registry, renderer. Keep those three named and the rest of the internet's slogans stop mattering.
Related documentation
Get started
Introduction
Flow-UI is an open source server driven UI framework for SwiftUI. Your backend describes an iOS screen as JSON and Flow-UI renders it as native views.
Get started
Installation
Add the Flow-UI server driven UI package to an iOS or macOS app with Swift Package Manager. Requires iOS 17, no third party dependencies.
Related articles
- Server-Driven UI5 min read
SDUI vs WebViews on iOS
SDUI renders native SwiftUI from JSON. A WebView renders HTML in a browser process. Teams pick SDUI when the page should feel like the rest of the app.
- Server-Driven UI4 min read
API driven UI and remote UI, explained
API driven UI and remote UI are names for the same idea as server driven UI: the API returns page structure, the iOS app paints SwiftUI.
- Server-Driven UI4 min read
Backend driven UI vs server driven UI
Backend driven UI, server driven UI, BDU, and SDUI are the same split: the server describes the page, the client renders native views.
More on the blog.
Read the source
Flow-UI is MIT licensed. The schema, renderer and starter widgets live on GitHub.
GitHubGet started with Flow-UI
Install the Swift package, register a widget, and render a page from JSON.
Get started