ADRs
ADR 0054 — Sorgente as a Library surface
  • 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/sorgente route (kept as a redirect until adoption settles)

Context

ADR 0053 shipped two parallel surfaces for editing the same Sorgente token graph:

  1. /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.

  2. /app/library?project=prj-arno-sorgente-seed — the Library showroom layout (Design System — Arno Sorgente hero, 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-seed is the canonical Sorgente library entry.
  • The prj-arno-sorgente-seed project 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/sorgente stays as a parallel route during migration. Either route lands on the same underlying surface once unified. After observation period, /app/sorgente becomes 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:

AspectFoundationCatalogSorgenteLibraryCatalog
Data source@arno/foundation/tokens.css (static)useSorgenteState() (live, polls 2s)
Token namespacecolor.neutral.*, space.300, ... (Foundation)mint, surface.base, space-12, ... (Sorgente — v9-synth ids per ADR 0053)
Inline editnone (Foundation is read-only for users)hover → Apply / Reset / × per specimen (same useSorgenteDraft hook the form editor uses)
Brand tabper-project Foundation demos<SorgenteBrandPanel> (already wired in ADR 0052 §14)
Historynot presentapply_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-tabWhat goes in (Sorgente version)
00 TokensDefault landing. Inside: Colors / Typography / Spacing / Radii / Effects (sub-sub-tabs).
01 PrimitivesFilter view: tier='primitive' rows. Grouped by ramp (mint / violet / pri / neutral).
02 CompositeFilter view: valueType='typography' + valueType='shadow'. Composite editor inline.
03 LayoutRead-only text describing layout shells (sidebar, navbar, canvas). May reference --space-* tokens used. Filled in later — empty placeholder in v1.
3.5 AdaptiveRead-only text describing breakpoints. Filled later.
04 StatusFilter view: pri.* semantic colors. Visualization of status palette.
05 Anti-patternsDoku 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:

TabSorgente behavior
Tokens<SorgenteLibraryCatalog> showroom + numbered sub-tabs (above)
ComponentsList of ARNO chrome components stub; full editor lands later
Brand<SorgenteBrandPanel> (already exists)
Storybookiframe → /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 FoundationCatalog to 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/sorgente route 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