Theme: Smoke
Background: Field
Theme: Smoke
Background: Field
System

Overview of Rift DS

How the system is built, and why its docs stay true

Rift DS ships as the npm package rift-ds: layered CSS tokens, React components, and complete themes, each applied by one data-brand attribute. This site installs it like any consumer, and the build holds these docs to the code: generators write them from the registries in the repo, and validators fail the build when the two disagree. You can install it yourself and re-theme it live.

The specs (CLAUDE.md, design.md, content-design.md), the skills, and the loops are yours to lift into your own codebase or AI tooling. Agents read the same contracts through the MCP endpoint at /api/mcp, or as files: one JSON schema per component and the tokens in the DTCG format.

The system is designed and built by Robert Ritacca, who writes the specs Claude Code builds from.

Using it in your product

Install the package, import the token stylesheet and the base sheet, and compose the components. A data-brand attribute on your root element applies a complete theme, light and dark. Your coding agent joins through this site: one command installs the agent skills, and the MCP endpoint serves the exact contracts while it builds.

The packagerift-ds · ESM · React 19 peer
Your productany React 19 stack with a bundler
Componentsone barrel + deep subpaths
Tokenstokens.css · tokens/values · primitives → semantic → components
Theme presetspresets.css · one generated stylesheet per look
Chat widgetrift-ds/chat · npx rift-ds init chat scaffolds the routes
Your appimport, compose, override tokens
Root elementdata-theme="dark" · data-brand="<look>"
Your coding agentbuilds with exact prop and token contracts
This site/api/mcp · JSON schemas · agent skills · .md pages · shadcn registry
npm install, then importone stylesheet importan AI chat over your own endpointone attribute applies a complete looknpx rift-ds init installs the skillsreads contracts over MCP
Your product on the right, the package on the left, this site serving your agent between them.

The rules it keeps

The same rules hold across the whole library, and the build or CI checks each one, so a broken rule fails instead of shipping.

  • Tokens. Three tiers, never skipped: primitives hold raw values, semantic tokens point at them, and components use only the semantic tokens. The action colour is reserved for actions, and shape is set per element type, so every button matches every other. A theme changes the values, never the tiers.
  • Props. Every component passes its ref and your attributes to its element. State you can own takes the same names everywhere: value to control it, defaultValue to let the component keep it, and onValueChange either way, with the same shape for checked, values and open. Every word a component writes is a prop with an English default, so all of it translates.
  • Behaviour. Every overlay joins one layer stack, so Escape closes only the top one and a menu inside a Dialog closes first. Key bindings share one listener, layout follows the reading direction, and numbers and dates follow your locale. The accessibility page has the detail.
  • The API. It only grows. A prop or export is deprecated, never removed, so an older name keeps working after an upgrade.

design.md holds the full set.

How the system fits together

One repo becomes a website, a Storybook, and an npm package through one gate: generators derive every surface from one source of truth, validators fail the build on drift, and CI runs the chain on every push. Each map below pans, zooms, and expands to full screen.

  • Figma
  • Claude Code
  • GitHub
  • Storybook
  • Vite
  • Next.js
  • Vercel
  • npm
One repocode · registries · specs
Generate · validate · gateone chain, before every build
Vercelwebsite + Storybook
npm registryrift-ds
Visitors + agentspages · chat · MCP
Package consumersimport the components
push to mainmanual release
One repo, one gate, two destinations.

What the repo holds

The repo is five layers deep: primitives feed the semantic tokens, tokens feed the components, and the components compose the site UI and every page. The graph page reads every edge from the CSS and imports at build time; pick a token or component to trace what it depends on and what depends on it.

The live instrument, mid-trace on Button: 964 nodes and 14462 dependencies, drawn from the same generated data. Open it to trace any node yourself.

How a change ships

Every change goes live in five stages: author, generate and validate, build, gate, ship. A push to main deploys the site; the package publishes to npm on its own lane, with provenance and no stored token. The map shows each check in the gate.

1 · Authoreverything hand-written
2 · Generate + validateno build starts before this passes
3 · Buildthree artifacts
4 · Gateevery push and pull request
5 · Ship + servetwo destinations, two paths
Component sourcecode · prop JSDoc · token CSS
Root specsdesign.md · content-design.md · CLAUDE.md
Data registriescomponents · tokens · releases
Generatorsbarrels · corpus · prop API · schemas · token values · README · agent skills
Validatorsbyte-compare · JSON Schema · cross-check every claim
npm packagevite lib build → dist/
Storybookstatic build · every story a render + interaction test
WebsiteNext.js · static + ISR pages
Google Fontsfetched once, then self-hosted
GitHub Actions CIaxe on every story · API check against the last release · hydration smoke · gesture stress · drift guard
Release workflowmanual · OIDC trusted publishing · consumer smoke
npm registryrift-ds
Verceldeploys every push to main · two projects
before every buildbuild time onlypush to main deploysdispatched by handpublish from dist/ · provenance
Five stages, then down through the gate.

How Claude Code runs it

Claude Code drives the pipeline through skills named for their end state. A change sits in one of four states, and checkpoint, park, land, and ship move it between them. Audit skills read and fix but never deploy; only ship and super-ship, which runs a full drift audit first, reach production.

Claude Code · the operator layerskills named for their end state
Audit skillsdrift · token · content · api · seo · security · a11y · design-qa · …
Recurring loops2 loops · every run ends in a report for approval
pre-deploythe full verify, run locally · pushes nothing
Working treethe session's changes
Brancheswip topics · worktrees · stashes
maina push here always deploys
Live + provensmoked against production
fixes arrive as branch workseveral read the live siterehearses the gatecheckpoint · save, keep workingpark · save, back to a clean mainland · triage all, merge local, never pushship · push, watch CI, prove it livesuper-ship · drift-audit first, then ship the lot
States, not steps: the skills are the transitions.

What runs once it’s live

Pages come from Vercel with the fonts and the chat corpus baked in, and a scheduled smoke re-checks production.

  • The chat answers through Claude from the site's corpus, looking up prop and token contracts when it needs them. Rate limits and a daily budget cap it, and conversations are kept 30 days, tied to no name.
  • /api/mcp serves agents five tools with no key, no account, and no model behind them: the component list, prop APIs, tokens resolved per theme, install setup, and site search. Component and token answers cite the published file.
Vercelstatic edge + serverless routes
Visitor's browserthe WebGL background runs here
Google Analytics 4page views and engagement events
Google Fontsthe playground's fonts and DESIGN.md import
Agents + MCP clientsconnect with one URL, no key
GitHub Actions cronthe uptime workflow
Static + ISR pagesfonts and corpus baked in · the /r/ registry · the /schema/ files
/api/chatfollowups · feedback · guardrails
/api/mcpgenerated data from memory · no model, no auth
/api/github-contributionsthe contribution graph
ISRserved pages can change with no deploy
Anthropic APIClaude, with the corpus as context
Redischat log (30d) · spend + rate counters · feedback · registry tally
Contributions APIpublic contribution counts · third party
HTML + assetschatpage views + eventsa face loads on previewMCP toolssmokes production on a cronmodel callslog + budget + ratecounts registry fetchespolls
Who talks to whom once the site is live.

How the chat answers

The corpus holds everything published as prose, cached for an hour, so most answers come from context alone. Exact facts (a prop's type or default, a token count, a token's value in a theme) come from lookup tools that read the same data /api/mcp serves, shown in the widget as a trace point. The corpus keeps the chat fluent; the tools keep it exact.

/api/chat · one exchangestreams the whole way
Visitorthe chat widget, on any page
Guardrailsper-visitor rate + daily budget · pick the model tier
System contextpersona + the whole site corpus · cached 1h
Lookup toolsget_component · get_design_tokens
Generated contractsprop API + token registry and values, read from memory
Anthropic APIClaude answers from the corpus, and asks for a lookup when contracts matter
/api/mcpthe same lookups, served to agents
question, the last 10 turns, what's highlightedone streamed model calla prop or token question triggers a lookupin-memory readtool result, then the answerthe answer streams back · lookups show as trace points · it can end in a question to tapshared implementations
One exchange. The highlighted edge is where the model stops reading prose and reads the contract.