- Date: 2026-06-09
- Status: Accepted
- Phase / Feature: Sorgente UX consolidation
- Builds on: ADR 0052 (shared-DB), ADR 0053 (Foundation rules), ADR 0048 (Constructor/Limiter)
- Supersedes: the separate
/app/sorgenteroute (kept as a redirect until adoption settles)
Context
ADR 0053 shipped two parallel surfaces for editing the same Sorgente token graph:
-
/app/sorgente— a functional form-row editor (tokenId | value | Apply | Reset | ×per row + sub-tabs Primitives / Semantic / Component / WCAG). Good for direct table-style edits, but visually disconnected from how the design system actually appears. -
/app/library?project=prj-arno-sorgente-seed— the Library showroom layout (Design System — Arno Sorgentehero, chips with brand metadata, numbered sub-tabs, swatch grid). Visually rich, but the swatches were rendering Foundation primitives (Foundation's own neutral/red/green/blue) — not the live Sorgente graph. Editing in this surface had no effect.
Maintainer sees two surfaces showing different content for the same conceptual thing, and edits in one don't materialize in the other.
Decision
Collapse to one surface: the Library showroom layout, backed by Sorgente state, with inline edit affordances on every specimen.
§1 — Routing
/app/library?project=prj-arno-sorgente-seedis the canonical Sorgente library entry.- The
prj-arno-sorgente-seedproject id is a constant (SORGENTE_PROJECT_ID) recognized by the library page. Currently exists on dev Neon; this ADR does not create/move it. /app/sorgentestays as a parallel route during migration. Either route lands on the same underlying surface once unified. After observation period,/app/sorgentebecomes a redirect →/app/library?project=prj-arno-sorgente-seed. Not done in this ADR — see §6.
§2 — Detection
The library page detects projectId === SORGENTE_PROJECT_ID (constant import). When true, the surface routes through a new component <SorgenteLibraryCatalog> instead of <FoundationCatalog>. The two components share visual look (same hero + chip layout + numbered sub-tabs + swatch grid) but differ in:
| Aspect | FoundationCatalog | SorgenteLibraryCatalog |
|---|---|---|
| Data source | @arno/foundation/tokens.css (static) | useSorgenteState() (live, polls 2s) |
| Token namespace | color.neutral.*, space.300, ... (Foundation) | mint, surface.base, space-12, ... (Sorgente — v9-synth ids per ADR 0053) |
| Inline edit | none (Foundation is read-only for users) | hover → Apply / Reset / × per specimen (same useSorgenteDraft hook the form editor uses) |
| Brand tab | per-project Foundation demos | <SorgenteBrandPanel> (already wired in ADR 0052 §14) |
| History | not present | apply_log Revert UI |
Foundation as a code artifact is NOT modified. SorgenteLibraryCatalog ships as a sibling component that consumes Sorgente exclusively.
§3 — Specimen shape
Every swatch / typography / spacing / radius cell is an <EditableSpecimen tokenId={...}> wrapper:
- Visual presentation — same showroom look as the Library (swatch box, token id label, resolved value, ref breadcrumb).
- Hover state — Apply / Reset / × buttons fade in (same affordances as
TokenField). - Edit state — clicking the value opens an inline editor (text input for scalars, color picker for hex, structured editor for typography composites, ref autocomplete for
{ref}syntax). - Status badges — WCAG fail badge (red), brand-bound badge (when binding overrides the literal), detached badge (composite).
Under the hood the wrapper calls useSorgenteDraft<T>({ kind: 'token', id: tokenId }) — same hook the form editor uses. Optimistic overlay merge works as before so edits propagate to every consumer in the same render cycle.
§4 — Sub-tab layout (Library numbered structure)
Match the existing showroom's numbered sub-tabs. Empty content is OK in v1 — fill incrementally.
| Sub-tab | What goes in (Sorgente version) |
|---|---|
00 Tokens | Default landing. Inside: Colors / Typography / Spacing / Radii / Effects (sub-sub-tabs). |
01 Primitives | Filter view: tier='primitive' rows. Grouped by ramp (mint / violet / pri / neutral). |
02 Composite | Filter view: valueType='typography' + valueType='shadow'. Composite editor inline. |
03 Layout | Read-only text describing layout shells (sidebar, navbar, canvas). May reference --space-* tokens used. Filled in later — empty placeholder in v1. |
3.5 Adaptive | Read-only text describing breakpoints. Filled later. |
04 Status | Filter view: pri.* semantic colors. Visualization of status palette. |
05 Anti-patterns | Doku content from ADR 0053 "Anti-patterns explicit" section. Read-only. |
§5 — Top-level tabs
Library top nav stays: Tokens / Components / Brand / Storybook. Adjusted for Sorgente:
| Tab | Sorgente behavior |
|---|---|
| Tokens | <SorgenteLibraryCatalog> showroom + numbered sub-tabs (above) |
| Components | List of ARNO chrome components stub; full editor lands later |
| Brand | <SorgenteBrandPanel> (already exists) |
| Storybook | iframe → /storybook/index.html (untouched) |
A new History link in the top nav opens the apply_log Revert UI (was a tab inside /app/sorgente).
§6 — Migration path for /app/sorgente
Keep /app/sorgente functional for the observation period (≥ 1 deploy cycle). After maintainer confirms the unified surface covers every workflow they used, switch /app/sorgente/page.tsx to a Next redirect() → /app/library?project=prj-arno-sorgente-seed. Drop the page contents in a follow-up. This ADR does not pick the cutover date.
§7 — Hero header / chips meta
The showroom header carries narrative copy ("deep near-black surface with warm undertone, mint as primary and violet as secondary, ...") and chips (tokens 1 file, fonts Plus Jakarta · Inter Tight · Geist Mono, radii 6 · 10 · 14 · 18 · 22 · pill, status 5 colors). In v1 this stays static text. Future polish: derive live from Sorgente state.
§8 — Sweep dependency
This ADR is independent of PR #64 (sweep of 1448 hardcoded values). The new <SorgenteLibraryCatalog> consumes existing Sorgente var-references where it can; remaining literals in the showroom CSS are picked up by the sweep on the next pass.
Anti-patterns explicit
- Do not modify
FoundationCatalogto know about Sorgente. Keep Foundation untouched — Sorgente has its own catalog component. - Do not invert the relationship: Sorgente is not "Foundation skinned with mint/violet"; it's its own design system that happens to share Foundation's architectural rules (ADR 0053).
- Do not remove
/app/sorgenteroute in the same PR as the new surface. Bookmark continuity matters until the unified surface is validated.
Open
- Cutover trigger for
/app/sorgente→ redirect: TBD on maintainer signal - Components tab content: needs its own ADR when ARNO chrome components are catalogued