A token value can appear in several places, but that doesn't make every location authoritative. A design brief may approve the role. Project configuration may encode it. A preset or registry item may deliver files, while a component consumes the resulting variable and a local selector may override it. Finally, the browser renders an outcome. Each layer answers a different question.
Pick one correction owner for each layer. When the rendered button is wrong, this prevents the familiar loop of patching the button, then the theme, then the button again. Work from the approved decision toward the rendered surface, and stop at the first layer that disagrees with its input.
| What it establishes | Correction owner | |
|---|---|---|
| Approved design decision | The intended semantic role, mode behavior, and permitted exceptions | Design-system owner |
| Project token configuration | How the project represents the approved role | Project theme owner |
| Preset or registry delivery | Which files and settings arrived from a particular source version | Delivery or integration owner |
| Editable component code | Which role a component and its variants actually consume | Component owner |
| Local exception | A named, deliberate departure with limited scope | Feature or surface owner |
| Rendered evidence | What representative consumers visibly did in the tested build | Reviewer or acceptance owner |
The source of truth isn't one universal file
The authoritative location depends on the decision. Project configuration can own a token mapping without owning the product rationale. Component code can own variant behavior without owning the semantic color choice. Rendered output is evidence of behavior, not the source of the decision.
Map one semantic role before changing the system
Start with one role whose propagation you can observe. A primary action role is useful because it usually reaches several states and often has different expectations in light and dark modes. Don't invent a namespace or configuration key from a generic tutorial. Inspect the project's configuration and component source, then record the identifier it actually uses.
The record should separate the semantic job from its current value. Values can change between modes or releases while the job stays stable. Name consumers narrowly enough to inspect them. "Buttons" is too broad when a change should reach the primary variant but leave secondary, destructive, or disabled treatments alone.
Token change record
Source version: [kit, preset, or decision version]
Semantic role: [role name used by the project]
Purpose: [the job this role performs]
Light expectation: [approved value or visual expectation]
Dark expectation: [approved value or visual expectation]
Project mapping: [actual project variable or theme destination]
Delivered artifact: [file or configuration surface]
Named consumers:
- [component, variant, state]
- [component, variant, state]
Allowed local exceptions:
- [surface, reason, owner]
Protected surfaces:
- [surface that must remain unchanged]
Evidence status: expected | observed | unresolved
Correction owner: [decision, mapping, delivery, component, exception, review]
Disposition: accept | revise | block
Notes: [observations and unresolved limits]Component specimen · Button
Ambient Sage
Live renderThe button primitive in Ambient Sage, across 4 states.
Default
Hover
Focus
Disabled
Map the dark expectation separately. Don't assume automatic inversion. Then list any exceptions. An exception isn't simply whatever looks different today; it needs a reason, a defined scope, and an owner. Without those, it's an unresolved conflict.
Treat preset commands as consequential changes
The shadcn package reference gives each command a different job. Create starts a new project through a custom design-system flow. Init installs dependencies, adds the utility used by components, and configures Tailwind CSS and CSS variables. Apply changes an existing project by overwriting preset configuration, reinstalling detected UI components, and updating fonts and CSS variables. Add brings in a selected component and its required dependencies.
Apply therefore has the widest documented replacement surface. You don't need to avoid it automatically, but you do need to bound the change first. A successful command means the files were processed. It says nothing about preserved customizations, correct token consumption, or rendered acceptance.
Protect local work before applying a preset
Before the operation, record the current configuration, CSS-variable definitions, font setup, installed components, and known component edits. Mark every local change that must survive. If you can't identify the protected surfaces, you can't distinguish replacement from an intended update.
Preset preflight
- Identify the exact operation and source version you intend to use.
- Inventory project configuration and the locations that define CSS variables.
- Record the current font families, loading setup, and role mappings.
- List detected or installed components that the operation may revisit.
- Name component-local edits, selectors, and variants that must survive.
- Write the expected changes by file, role, component, state, and mode.
- Keep a separate protected-surface list for everything expected to remain unchanged.
- Choose representative consumers and unrelated surfaces for the post-operation check.
- Set the decision rule before running the operation: accept, revise, or block.
Inspect a complete kit before mapping it
Use a public kit to see the boundary between an upstream design artifact and the project-owned evidence still required after delivery.
Keep a source-to-consumer register
A preflight protects the operation. A source-to-consumer register keeps the system maintainable afterward. Give each semantic role and consumer relationship its own row. If one role reaches a primary button, link, focus ring, and selected navigation item, record them as separate consumers because each can fail independently.
| Record | Why it matters | |
|---|---|---|
| Source version | The approved kit, preset, or decision version | Separates current evidence from stale artifacts |
| Role and modes | Semantic job plus light and dark expectations | Prevents a single-mode pass from hiding a mismatch |
| Delivered artifact | The file or configuration surface received by the project | Locates delivery failures |
| Consumers and states | Named components, variants, and interaction states | Makes propagation falsifiable |
| Local overrides | Selector or component, reason, scope, and owner | Distinguishes exceptions from drift |
| Protected surfaces | Unrelated behavior or styling that must not change | Detects collateral replacement |
| Evidence | Expected, observed, or unresolved, with notes | Stops assumptions from being promoted to results |
| Disposition | Accept, revise, or block | Records the actual decision |
Avoid vague evidence such as "looks good." Write an observation a second reviewer can challenge: the primary button changed in both modes; its focus treatment was present; the secondary variant kept its prior treatment; the unrelated input error state didn't change. Screenshots or automated checks can support those observations, but the register should explain what each artifact demonstrates.
Run one controlled token change
A controlled change answers one narrow question: does an approved role reach its intended consumers without changing protected surfaces? It isn't a complete accessibility review, regression suite, or proof that every component uses the system. Keep that broader evidence separate.
- 1
Freeze the prior state
Record the source version, project mapping, current light and dark results, component-local overrides, and protected surfaces. Keep enough evidence to compare behavior after the operation.
- 2
State the expected propagation
Name the intended consumers and states. Also name what must remain unchanged. Put those expectations in the record before observing the result.
- 3
Perform the bounded project operation
Use the operation selected during preflight. Record the files and configuration surfaces it reports changing. Don't treat command completion as acceptance.
- 4
Inspect the implementation path
Confirm that the expected project mapping exists and that each named component consumes it. Look for component-local values or selectors that intercept the role.
- 5
Observe representative states and modes
Render the named consumers in light and dark modes. Include states that expose different paths, such as default, hover, focus, disabled, and error where supported.
- 6
Check protected and unrelated surfaces
Inspect the local customizations and unrelated consumers listed during preflight. Record whether they remained unchanged instead of relying on memory.
- 7
Choose a disposition
Accept only if intended consumers changed, protected surfaces did not, observations are recorded, and any unresolved evidence is non-blocking. Otherwise, revise the owning layer or block the change.
Keep expectations and observations in separate fields
When one sentence says both what should happen and what did happen, reviewers can mistake an assumption for evidence. Record the expectation first. Then add a dated observation from the consuming project.
Route failures to the layer that owns them
When the result is wrong, start at the top of the authority chain. The first mismatch owns the correction. A local patch may hide the symptom while every other consumer remains wrong.
- Wrong upstream decision: the approved role or mode expectation itself is unsuitable. Return it to the design-system owner.
- Stale project mapping: the approved role is correct, but the project's variable or theme destination still carries an older value. Correct the project token layer.
- Preset replacement: the operation replaced configuration, fonts, CSS variables, or component code that the preflight marked as protected. Restore them through the project's normal reviewed change process and revise the integration plan.
- Component-local override: the shared mapping is correct, but a selector, literal, variant, or local rule intercepts it. Correct the component layer or document a deliberate exception.
- Missing consumer: the component never references the intended role. Add or correct the source-to-consumer mapping.
- Absent observation: the code path appears correct, but no representative render was inspected. Leave the evidence unresolved instead of accepting by inference.
This order matters because rendered similarity can mislead. A component may happen to match the approved color through a local literal while bypassing the semantic role entirely. It looks correct until the next mode or preset change. The register catches that structural defect before it becomes drift.
Use Ambient Sage as a bounded intake example
Ambient Sage is a public Identity Forge kit. Its published page documents a warm sage surface system, a vivid yellow accent used sparingly, Plus Jakarta Sans for product typography, JetBrains Mono for technical strings, and component-scale treatments. Identity Forge also publishes a shadcn delivery route for the kit.
Token specimen · real values
Ambient Sage
Live renderAmbient Sage's actual tokens — the same values its exports use.
That evidence supports an intake record, not a compatibility verdict. You can record that the public kit and a shadcn artifact exist. This dossier doesn't establish that a particular project accepted the artifact, preserved its customizations, mapped every token correctly, or achieved rendered parity.
Ambient Sage intake record
Upstream artifact: Ambient Sage public design kit
Artifact availability: observed
Shadcn delivery route: observed
Upstream colors and typography: documented
Project token mapping: unresolved
Installed component behavior: unresolved
Local overrides: unresolved
Light-mode acceptance: unresolved
Dark-mode acceptance: unresolved
Protected-surface check: unresolved
Disposition: block acceptance until project-owned evidence is recordedAccept only what the evidence shows
Accept the change when the intended consumers changed in every required mode and state, protected surfaces stayed intact, local exceptions remain deliberate and owned, and the observations are recorded. Revise when the intended decision is sound but the mapping, delivery, or component layer is wrong. Block when a protected surface changed, a required consumer failed, or the evidence needed for the decision is still missing.
For your next token change, choose one semantic role and complete the register before touching the preset. If you can't name its consumers, exceptions, protected surfaces, and correction owner, the implementation isn't ready for a consequential operation.
Sources
- Introduction - shadcn/ui: Shadcn describes itself as open code and a code distribution platform, leaving the installed component source under the consuming project's control.
- The Foundation for your Design System - shadcn/ui: The official site presents shadcn as a customizable foundation whose components can be extended and made project-specific.
- shadcn - npm: The package reference says init configures Tailwind CSS and CSS variables, apply overwrites preset configuration and updates detected components, fonts, and CSS variables, and add installs a component with its dependencies.
- GitHub - shadcn-ui/ui: The public repository is the authoritative upstream source surface for shadcn code, history, issues, releases, and contributions.
- Ambient Sage Design Kit: Ambient Sage is a public kit with documented colors, typography, component-scale treatments, and a shadcn installation route.
- Visual kits for agents that need to design well: Identity Forge's public kit gallery describes its kits as systems containing fonts, colors, tokens, and component rules.