Jerbix

Design System

Color, font, and scale tokens, plus where to put your own logo

Last updated November 3, 2026


Every color, size, radius, and shadow on the site traces back to this page. The code is the source of truth: values live in src/styles/globals.css, and the repo-root DESIGN.md has the fuller rules; when they disagree, trust the CSS.

Color

Use semantic tokens only. Never write raw color scales — bg-zinc-100, text-gray-500, bg-white, and #6B46FF are all disallowed. For neutrals, use derived forms like bg-foreground/10.

TokenPurposeNote
--background / --foregroundPage / body textContrast 18.01 / 17.39
--card / --popoverRaised surfacesOne step above background
--primary / --primary-foregroundBrand, links, selection / text on brandDark theme foreground is ink, not white
--secondarySecondary surfaceCarries purple, small areas only
--muted / --muted-foregroundLarge section backgrounds / secondary textNear-neutral cool gray
--accentMenu hover, selected backgroundA surface, not an accent color — don't draw dots with it
--highlightDecorative dots, rails, connectorsSame hue, one step lighter; ≥ 3:1 for non-text graphics
--destructive / --success / --warningStatus semanticsText and icon color only
--border / --input / --ringDividers / form borders / focus ring--input is darker than border to reach 3:1
--sidebar and --sidebar-*Sidebar--sidebar matches --background, separated by --sidebar-border
--chart-1..5Default chart seriesData visualization only

tests/unit/theme-consistency.test.ts scans src/ (excluding ui/ and mail/) and fails on color literals — new exceptions need a documented reason in the test.

Minimal example:

tsx
<div className="bg-background text-foreground">
  <div className="bg-card text-card-foreground rounded-xl border border-border p-6">
    <p className="text-muted-foreground">Secondary note</p>
    <button className="bg-primary text-primary-foreground rounded-md px-4 py-2">
      Primary action
    </button>
  </div>
</div>

Typography

TokenValueNotes
--font-sansInter Variable → Quicksand Variable → system stackBody
--font-monoJetBrains Mono Variable → system monoCode
--font-displayQuicksand Variable → Inter VariableBrand wordmark
--tracking-normal-0.01emPairs with Inter

Fonts are self-hosted via @fontsource-variable/*, not Google Fonts — so CSP font-src needs no third-party origin and there is no render-blocking external request.

None of the three fonts include CJK glyphs. Keep the PingFang SC / Microsoft YaHei fallback in --font-sans or Chinese text falls back to the browser default.

Scale

DimensionValue
--radius0.75rem (sm/md minus 4/2px, xl plus 4px)
Card radiusrounded-xl
Table framerounded-lg
--card-spacing1.5rem
--shadow-2xs..2xlEight steps; light theme tints with brand purple

Shadows must be written per theme, not wrapped in `light-dark()`. It only resolves in a color context; box-shadow treats it as an unknown value and you get box-shadow: none.

Changing the theme colors

  1. Pull real values from the registry, not the CSS pasted on the website:

``bash curl -sL https://tweakcn.com/r/themes/<id> ``

  1. Check contrast pair by pair (body ≥ 4.5:1, non-text ≥ 3:1) and apply the correction

table in DESIGN.md.

  1. Declare new tokens in both :root and @theme inline; declaring only one leaves a

value empty in one theme.

  1. Sync four places: ui.themeColor in src/config/website.ts, public/manifest.json,

EMAIL_THEME in src/mail/components/EmailLayout.tsx, and the examples in content/docs/configuration*.md.

  1. Run pnpm test — theme-colors.test.ts and theme-tokens.test.ts guard against drift.

The logo has two parts: a graphic mark and the site name.

  • The mark is a static SVG in src/components/layout/brand/. BrandLogo.tsx imports it as

text with ?raw, strips the asset's own <style>, and injects it. Keep the variable names and class names that the SVG's `<style>` block declares — BrandLogo.tsx maps those class names onto CSS variables, and renaming them breaks the mapping.

  • The site name is text, taken from metadata.name in src/config/website.ts and

rendered with --font-display. The wordmark is deliberately not baked into the SVG.

What to changeWhere
Graphic markThe SVG under src/components/layout/brand/
Site namemetadata.name in src/config/website.ts
Two-tone wordmark accent suffixmetadata.logoAccent in src/config/website.ts (leave empty if none)
Share image and iconsmetadata.images in src/config/website.ts
Browser address bar colorui.themeColor in src/config/website.ts

The logo is inline SVG, not `<img>`: CSS variables cannot cross the <img> document boundary, so with <img src> theme switching has no effect on it. Never derive a dark logo with CSS filters — invert / hue-rotate are global color matrices and cannot map the ink and the brand purple correctly at the same time.