Northstar Design System
A token-driven design system showcase built for AI-assisted development workflows. React 19 · Vite 8 · TypeScript (strict) · Vitest · oxlint.
Quick start
npm install
npm run dev # dev server on 0.0.0.0:5173
Auth and the API proxy
/api is proxied to the Go backend (API_URL, default
http://localhost:8080) so the browser only ever sees the vite origin —
on localhost or *.preview.k6n.net. That keeps OIDC redirects and the
session cookie first-party: the topbar's Sign in and the overview Session
card go through /api/auth/login, the issuer returns to
/api/auth/callback on the same host, and useSession()
(src/auth) polls /api/auth/session. The proxy forwards
X-Forwarded-Host/X-Forwarded-Proto so the backend registers the right
redirect URI per host. See the backend README for the server side.
The quality gate
npm run check
One command, four gates, in order:
oxlint— lint over every source file.scripts/check-tokens.mjs— the token contract: bans hardcoded colors (hex / named /rgb()/hsl()/oklch()/lab()), px font sizes and undefinedvar(--x)references — in both CSS files and inlinestyle={{ … }}objects. Values may span lines; comments are ignored.vitest run— unit + component tests (tests/).tsc -b && vite build— strict typecheck, then production build.
CI runs the same gate on every push and PR (.github/workflows/ci.yml).
Design tokens
src/tokens.css is the single source of truth. Every color, font size,
spacing, radius and shadow goes through a var(--token) — components never
hardcode values. Themes are plain CSS: :root[data-theme='light'] /
.light and :root[data-theme='dark'] / .dark, with a pre-paint script in
index.html that applies the saved (or OS-preferred) theme before first paint.
The global density knob is --root-font-size — one line scales the whole app.
Layout
src/
tokens.css ← lab() design tokens, dark & light themes
index.css ← fonts, token import, base resets
utils.css ← token-compliant utility classes
App.css ← application showcase styles
app/ ← AppStateProvider + useAppState(), and the route table (wouter)
auth/ ← useSession() + UserMenu / SessionCard (OIDC identity via the API proxy)
pages/ ← one page component per route
components/
ui/ ← composable primitives (Overlay, Dialog, Sheet, Tabs, Alert, …)
icon-registry.ts← the one icon name → lucide component map
examples/ ← reusable patterns (MetricsDashboard, SettingsPanel, …)
dev/ ← ErrorBoundary + dev error sink (#dev-errors)
utils/ ← cn(), useTimeout()
tests/ ← vitest suites (jsdom)
scripts/
check-tokens.mjs ← token contract guard
For agents
Read AGENTS.md before changing anything — it documents the
token contract, the overlay/icon registries, and the parallel-subagent rules.