How to use the Next.js authoring UI to build, edit, and ship a server-driven screen.
The admin needs the API running:
docker compose up -d postgres
pnpm --filter @sdui/api exec prisma migrate dev # first run only
pnpm dev:api
pnpm dev:adminOpen http://localhost:3001.
The landing page lists every screen the API knows about. Each row shows the screen id, the published revision, and (if any) the unpublished draft revision.
Click a row to open the editor.
Three panes:
- Palette (left): drag sources for new sections — section header, promo banner, product carousel, category rail, spacer, stack.
- Layout (center): the live, sortable list of sections. Drag to reorder. Click any row to select it.
- Properties (right): the form for the selected section. Generated from the same Zod schema the API resolver uses, so anything you can edit here is also something the API can validate.
Above the layout: Preview JSON, Save draft, Publish.
- Click a card in the Palette.
- The new section appears at the bottom of the Layout with a generated id (e.g.
pl-9k3a1b). - The new section is selected automatically — fill in the Properties panel.
- Click Save draft.
Drag any section's handle (⋮⋮) up or down. The list reflows live. Click Save draft to persist.
- Click the section in the Layout.
- In Properties, type into
TextorSubtext. - To insert a dynamic value (e.g. the user's first name), drop a token like
{{user.firstName}}into the field. The catalog of available tokens lives in the same panel — drag-clickable. - Save draft.
For sections like productCardList, categoryRail, and promoBanner, the Properties panel exposes a Source group:
- Repo — a dropdown populated from
GET /api/admin/composition/catalog. Chooseproducts,promos, orcategories. - Segment — for repos that support it (e.g.
products: picked | trending | new). - Limit — how many items the API should fetch.
The admin UI cannot let you pick an invalid repo or segment — the catalog is the closed set.
Targeting limits who sees a section:
- OS —
ios,android, orall. - OS version range — minimum and maximum.
- App version range — minimum and maximum.
Sections that fail their targeting rule are dropped from the response server-side. The mobile client never sees them; the resolver simply doesn't emit them.
Click Preview JSON to see exactly what the API will emit for a synthetic user given your current draft. Use this to confirm dynamic-value substitution and source binding before you publish.
- Save draft writes to
draftRevonly. Mobile clients keep seeing the previously published revision. - Publish promotes the draft to
rev. The API emits an SSEscreen-updatedevent. The next mobile refetch returns the new layout.
The flow is intentional: a half-finished draft never reaches a user.
Use DELETE /api/admin/screens/:id from the API. There's no delete button in the UI yet — adding one is straightforward but deferred. See Production readiness.
- Multi-user collaboration / locking.
- Audit log / undo / version diff between revisions.
- Scheduled publishes ("publish at 9am tomorrow").
- WYSIWYG visual preview of the rendered tree (only JSON preview today).
- Real auth — currently a shared
x-admin-secretheader.
These are documented in Production readiness as next steps.