Generate, compile, install, and preview design systems from one source of truth. Compatible with shadcn/cli v4 presets and registries.
- Compile theme graph to shadcn v4
registry:base+registry:fontpresets - Convert between 19+ theme formats (shadcn/ui, VS Code, terminals, design tools)
- Generate semantic color palettes using OKLCH color space
- Extract themes from images via Ray API
- Live theme editing with real-time preview
- Serve installable presets:
npx shadcn@latest add https://tinte.dev/api/preset/{slug}
- Next.js 16 with TypeScript and App Router
- Tailwind CSS + shadcn/ui for UI components
- Culori for OKLCH color manipulation
- Shiki + Monaco Editor for syntax highlighting
- Zustand + nuqs for state management
- React Context for theme state
- Bun for package management
src/
├── app/ # Pages (workbench, experiment, bingo, vscode)
├── providers/theme.tsx # Single theme context provider
├── components/
│ ├── shared/ # Theme components (switcher, selector, editor)
│ ├── preview/ # Provider-specific previews (vscode, shadcn, terminals)
│ └── workbench/ # Workbench components
├── hooks/ # Custom hooks (theme, monaco, shiki, workbench)
├── stores/ # Zustand stores (workbench, export)
├── lib/ # Conversion logic and providers registry
└── types/ # TypeScript definitions
Continuous Scale: bg → bg-2 → ui → ui-2 → ui-3 → tx-3 → tx-2 → tx
- Light mode: bg (lightest) → tx (darkest)
- Dark mode: bg (darkest) → tx (lightest)
- OKLCH color space for perceptual consistency
Token Meanings:
bg/bg-2: Main/elevated surfacesui/ui-2/ui-3: Borders, hover states, active statestx-3/tx-2/tx: Faint, muted, primary textprimary/accent/secondary: Functional colors
- Single
ThemeProviderwraps entire app - localStorage persistence with DOM updates
- Zero state desync between components
- Perfect SSR/hydration handling
- Zustand stores: Server state (chatId, split, loading)
- nuqs: URL state (activeTab, provider) with automatic sync
- Zero prop drilling, zero useState/useEffect patterns
- Perfect browser navigation support
- ThemeProvider: Basic conversion & export
- PreviewableProvider: Adds live preview component
- Registry-based with compile-time validation
Editors: shadcn/ui, VS Code Terminals: Alacritty, Kitty, Warp, Windows Terminal Design Tools: GIMP, Slack
All providers have rich visual previews using actual theme data.
bun install # Install dependencies
bun dev # Start development server
bun build # Production build
bun run lint # Lint code
bun run type-check # TypeScript validation/workbench- Main theme editor with live preview/experiment- Rayso → shadcn conversion testing/bingo- TweakCN → Rayso conversion testing/vscode- VS Code theme preview and export
- Modular components: monaco-preview, shiki-preview, tokens-preview
- Custom hooks: use-monaco-editor, use-shiki-highlighter
- Version-based caching, 50ms transitions, zero theme conflicts
- Perfect consistency using
@shikijs/monaco - Identical theme structure between both systems
- Smart initialization, no disposal conflicts
- All previews use real converted theme data
- Dynamic light/dark mode switching
- Type-safe integration with provider outputs
- Performance optimized with memoization
- No comments unless requested
- Semantic naming following Flexoki philosophy
- Type safety throughout
- Modular architecture with single responsibility
- Custom hooks for complex logic
- Minimal useEffect usage
- Test all format conversions (Rayso ↔ TweakCN ↔ VS Code ↔ shadcn)
- Verify WCAG contrast ratios
- Test light/dark mode switching
- Export and install themes in target applications
- URL synchronization with browser navigation
- Theme persistence across page refreshes
- Component isolation with global state access
- No infinite loops or circular dependencies
- Live workbench: Real-time editing with instant preview
- Universal previews: Rich visuals for all supported providers
- Type-safe conversions: Compile-time validation throughout
- Performance optimized: Smart caching, minimal re-renders
- URL state sync: Shareable URLs with preserved state
- Provider status: Clear indicators for available vs planned providers
- Export functionality: Download themes in multiple formats
- Responsive design: Works on mobile and desktop
Concise rules for building accessible, fast, delightful UIs Use MUST/SHOULD/NEVER to guide decisions
- Keyboard
- MUST: Full keyboard support per WAI-ARIA APG
- MUST: Visible focus rings (
:focus-visible; group with:focus-within) - MUST: Manage focus (trap, move, and return) per APG patterns
- Targets & input
- MUST: Hit target ≥24px (mobile ≥44px) If visual <24px, expand hit area
- MUST: Mobile
<input>font-size ≥16px or set:<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover" />
- NEVER: Disable browser zoom
- MUST:
touch-action: manipulationto prevent double-tap zoom; set-webkit-tap-highlight-colorto match design
- Inputs & forms (behavior)
- MUST: Hydration-safe inputs (no lost focus/value)
- NEVER: Block paste in
<input>/<textarea> - MUST: Loading buttons show spinner and keep original label
- MUST: Enter submits focused text input In
<textarea>, ⌘/Ctrl+Enter submits; Enter adds newline - MUST: Keep submit enabled until request starts; then disable, show spinner, use idempotency key
- MUST: Don’t block typing; accept free text and validate after
- MUST: Allow submitting incomplete forms to surface validation
- MUST: Errors inline next to fields; on submit, focus first error
- MUST:
autocomplete+ meaningfulname; correcttypeandinputmode - SHOULD: Disable spellcheck for emails/codes/usernames
- SHOULD: Placeholders end with ellipsis and show example pattern (eg,
+1 (123) 456-7890,sk-012345…) - MUST: Warn on unsaved changes before navigation
- MUST: Compatible with password managers & 2FA; allow pasting one-time codes
- MUST: Trim values to handle text expansion trailing spaces
- MUST: No dead zones on checkboxes/radios; label+control share one generous hit target
- State & navigation
- MUST: URL reflects state (deep-link filters/tabs/pagination/expanded panels) Prefer libs like nuqs
- MUST: Back/Forward restores scroll
- MUST: Links are links—use
<a>/<Link>for navigation (support Cmd/Ctrl/middle-click)
- Feedback
- SHOULD: Optimistic UI; reconcile on response; on failure show error and rollback or offer Undo
- MUST: Confirm destructive actions or provide Undo window
- MUST: Use polite
aria-livefor toasts/inline validation - SHOULD: Ellipsis (
…) for options that open follow-ups (eg, “Rename…”)
- Touch/drag/scroll
- MUST: Design forgiving interactions (generous targets, clear affordances; avoid finickiness)
- MUST: Delay first tooltip in a group; subsequent peers no delay
- MUST: Intentional
overscroll-behavior: containin modals/drawers - MUST: During drag, disable text selection and set
inerton dragged element/containers - MUST: No “dead-looking” interactive zones—if it looks clickable, it is
- Autofocus
- SHOULD: Autofocus on desktop when there’s a single primary input; rarely on mobile (to avoid layout shift)
- MUST: Honor
prefers-reduced-motion(provide reduced variant) - SHOULD: Prefer CSS > Web Animations API > JS libraries
- MUST: Animate compositor-friendly props (
transform,opacity); avoid layout/repaint props (top/left/width/height) - SHOULD: Animate only to clarify cause/effect or add deliberate delight
- SHOULD: Choose easing to match the change (size/distance/trigger)
- MUST: Animations are interruptible and input-driven (avoid autoplay)
- MUST: Correct
transform-origin(motion starts where it “physically” should)
- SHOULD: Optical alignment; adjust by ±1px when perception beats geometry
- MUST: Deliberate alignment to grid/baseline/edges/optical centers—no accidental placement
- SHOULD: Balance icon/text lockups (stroke/weight/size/spacing/color)
- MUST: Verify mobile, laptop, ultra-wide (simulate ultra-wide at 50% zoom)
- MUST: Respect safe areas (use env(safe-area-inset-*))
- MUST: Avoid unwanted scrollbars; fix overflows
- SHOULD: Inline help first; tooltips last resort
- MUST: Skeletons mirror final content to avoid layout shift
- MUST:
<title>matches current context - MUST: No dead ends; always offer next step/recovery
- MUST: Design empty/sparse/dense/error states
- SHOULD: Curly quotes (“ ”); avoid widows/orphans
- MUST: Tabular numbers for comparisons (
font-variant-numeric: tabular-numsor a mono like Geist Mono) - MUST: Redundant status cues (not color-only); icons have text labels
- MUST: Don’t ship the schema—visuals may omit labels but accessible names still exist
- MUST: Use the ellipsis character
…(not ``) - MUST:
scroll-margin-topon headings for anchored links; include a “Skip to content” link; hierarchical<h1–h6> - MUST: Resilient to user-generated content (short/avg/very long)
- MUST: Locale-aware dates/times/numbers/currency
- MUST: Accurate names (
aria-label), decorative elementsaria-hidden, verify in the Accessibility Tree - MUST: Icon-only buttons have descriptive
aria-label - MUST: Prefer native semantics (
button,a,label,table) before ARIA - SHOULD: Right-clicking the nav logo surfaces brand assets
- MUST: Use non-breaking spaces to glue terms:
10 MB,⌘ + K,Vercel SDK
- SHOULD: Test iOS Low Power Mode and macOS Safari
- MUST: Measure reliably (disable extensions that skew runtime)
- MUST: Track and minimize re-renders (React DevTools/React Scan)
- MUST: Profile with CPU/network throttling
- MUST: Batch layout reads/writes; avoid unnecessary reflows/repaints
- MUST: Mutations (
POST/PATCH/DELETE) target <500 ms - SHOULD: Prefer uncontrolled inputs; make controlled loops cheap (keystroke cost)
- MUST: Virtualize large lists (eg,
virtua) - MUST: Preload only above-the-fold images; lazy-load the rest
- MUST: Prevent CLS from images (explicit dimensions or reserved space)
- SHOULD: Layered shadows (ambient + direct)
- SHOULD: Crisp edges via semi-transparent borders + shadows
- SHOULD: Nested radii: child ≤ parent; concentric
- SHOULD: Hue consistency: tint borders/shadows/text toward bg hue
- MUST: Accessible charts (color-blind-friendly palettes)
- MUST: Meet contrast—prefer APCA over WCAG 2
- MUST: Increase contrast on
:hover/:active/:focus - SHOULD: Match browser UI to bg
- SHOULD: Avoid gradient banding (use masks when needed)