Dirework

Design System

Dirework's design tokens, the dw-* utility layer, and shared UI primitives.

Dirework ships a small, generated design system so the web app, the docs site, and the OBS overlays all speak the same visual language. The source of truth is a single JSON file; everything else is generated from it.

Source of truth

design-system/
  tokens.json          # canonical tokens — edit this
  scripts/generate.ts  # bun script that emits per-platform outputs
  README.md            # full reference
  components/          # markdown catalog (one .md per primitive)

Regenerate the outputs from the repo root:

bun run tokens

This writes three committed files:

OutputConsumed by
apps/fumadocs/src/app/tokens.generated.cssDocs --ds-* CSS variables
apps/web/src/tokens.generated.cssWeb app --ds-* CSS variables
apps/fumadocs/src/app/(home)/_widgets/overlay-themes.generated.tsLanding-page theme gallery

CI verifies the outputs are in sync: bun run tokens && git diff --exit-code. Never edit a generated file by hand.

Brand

Dirework's primary is a blue-leaning purple #6E5AF5 — a nod to Twitch purple (#9146FF) without copying it, nudged toward blue. Dark mode lightens the brand to #9385FB for contrast on near-black surfaces.

  • Display / headings: Montserrat (--ds-font-family-display)
  • Body: Roboto (--ds-font-family-sans)
  • Code: JetBrains Mono (--ds-font-family-mono)

Tokens

All tokens are exposed as --ds-* CSS custom properties. Highlights:

NamespaceVariable patternExample
Brand scale--ds-color-brand-{50…900}--ds-color-brand-500: #6E5AF5
Semantic--ds-color-{success,warning,error,info}--ds-color-success: #34C759
Phase--ds-color-phase-{work,break,long-break,paused}timer ring accents
Surface--ds-color-surface-{base,surface,elev,hairline}light/dark aware
Text--ds-color-text-{primary,secondary,muted}light/dark aware
Partner--ds-color-partner-{twitch,discord,obs}partner brands only
Type--ds-font-size-{xs…6xl}, --ds-font-weight-*--ds-font-size-5xl: 48px
Space--ds-space-{0…11}4px-based scale
Radius--ds-radius-{xs…2xl,pill}--ds-radius-pill: 9999px
Motion--ds-motion-duration-*, --ds-motion-easing-*fast: 150ms
Shadow--ds-shadow-{xs…lg,glow}--ds-shadow-glow

Dark-mode values are swapped under .dark / [data-theme="dark"] automatically.

The dw-* utility layer

The marketing and docs surfaces use a thin set of utility classes (defined in apps/fumadocs/src/app/global.css) that read the tokens. These keep the landing page token-backed without pulling in a component framework.

ClassPurpose
dw-displayMontserrat heading style
dw-text-1 / dw-text-2 / dw-text-brandText hierarchy
dw-bg-base / dw-bg-surface / dw-bg-elevSurfaces
dw-glassLiquid-glass translucent card
dw-card / dw-card-hoverContent container
dw-btn + dw-btn-primary/secondary/ghostButtons
dw-pillMetadata / trust chip
dw-codeInline code block
dw-reveal-{1,2,3}Staggered entrance animation

Component catalog

Shared primitives are documented one-per-file under design-system/components/:

  • Button, Card, Glass Card, Pill — marketing chrome
  • Timer Ring — the overlay progress ring (circle + squircle), mirroring apps/web/src/lib/timer-utils.ts
  • Task Card — the grouped task overlay, mirroring task-list-display.tsx
  • Chat Bubble — the Twitch command preview
  • Theme Swatch — the overlay theme gallery, driven by the generated OVERLAY_THEMES

Overlay themes

overlay.themes in tokens.json mirrors the 11 presets in apps/web/src/lib/theme-presets.ts, holding the four swatch colors each exposes (bg, accent, text, username). That data is generated into a typed module the landing-page gallery renders. When a preset's preview colors change, update tokens.json and run bun run tokens.

Accessibility rules

  • Two themes, always. Every surface must read in light and dark.
  • Never color alone. Done tasks use strike-through and a dimmed color.
  • Honor reduced motion. Animated primitives stop under prefers-reduced-motion: reduce.
  • Real interactive elements. Buttons and links are <button>/<a>, never clickable <div>s.

On this page