Skip to content
Step 4Phase 1: product definition~15 min

Design system: Colorway C + two knobs

The look is decided. The boilerplate ships Colorway C: off-black / off-white surfaces, hairline structure, one accent used only as a line. Per project you turn exactly two knobs, the default mode and the accent hue, and the whole component tree re-skins from one place.

At a glance

Purpose: give the site its own accent without rebuilding a design system per project.

Run: ai_rules/generators/design_system_generator.md (3 phases) → ai_rules/app_approach/claude_design_prompt.md

Output: the --accent pair in app/globals.css + config.ts colors.main.

Feeds: every link, underline, cursor, focus ring, numbered marker, and the single CTA re-color from one variable pair.

Why it works this way

A boilerplate that ships looking like the boilerplate is a tell, but a full per-project palette is a slow, contrast-bug-prone detour. Colorway C splits the difference: the neutrals, hairlines, type stack, layout, and motion are fixed and already tuned, so the only thing that varies between sites is one accent hue (and which mode is the default). The restraint is the signature, and you cannot accidentally regress it.

The three phases

1

Browse real product UI first

Before you lock anything, spend ten minutes looking at how shipped products actually solve the screens you are about to build. styles.refero.design is a searchable library of real product UI patterns: pricing tables, onboarding, empty states, settings. You are not changing Colorway C, you are sharpening the layout and component decisions the build step will make, so the accent has something well-composed to sit on.

2

Phase A: choose the two knobs

Read the PRD plus any brand input, then decide: the default mode (dark for dev tools / AI / night use, light for editorial / daytime), and the single accent hue. The generator writes the decision to ai_rules/app_approach/claude_design_prompt.md, a Colorway-C-locked prompt that never asks for new neutrals, type, or layout.

3

Derive the accent: one hue, two values

The accent is authored in OKLCH as a single hue with two lightness values: a deeper value for light mode (it sits on off-white paper) and a brighter value for dark mode (it sits on off-black). Same hue both modes, with at least a 0.4 OKLCH lightness gap from the background it sits on.

the accent pattern (Colorway C's own teal)
/* light mode, deeper, sits on off-white #FAFAF8 */
--accent: #1F6F73;   /* oklch(0.4969 0.0744 199.95) */

/* dark mode, brighter, sits on off-black #0E0E10 */
--accent: #3BA9AE;   /* oklch(0.6756 0.0976 199.43) */
4

Phase B: write only the accent

A surgical edit, not a palette generation. Set the --accent pair in the two mode blocks of app/globals.css, mirror it into the mapped --primary / --ring, and set config.ts colors.main to the dark accent hex. Everything else, --bg, --surface, --fg, --muted, --hairline, stays untouched.

5

Phase C: guardrail sweep

Sweep for accent misuse. Each accent hit must be a hairline, an underline, a focus ring, the cursor motif, a numbered marker, or the single primary CTA fill. A hero background, a section fill, a gradient, or a second accent is a violation, replace it with hairline / surface / fg tokens. Then rebuild.

$
grep-rn "bg-primary\|var(--accent)" src/app src/components \
| grep -iv "border\|underline\|ring\|cursor\|cw-btn\|NumberMarker\|focus"

What is fixed (and stays fixed)

  • Off-black / off-white neutrals, never pure #000 / #fff.
  • Hairline structure: borders are the structure, flat fills, no drop shadows.
  • Type: Bricolage Grotesque display, Geist body, Geist Mono for the numbered eyebrows.
  • Motion: one hero reveal, the blinking accent cursor, underline-grow-from-left links.
  • Accent is a line, never a fill: the one primary CTA is the only accent fill on the page.

The canonical spec lives in design.md at the repo root and ai_rules/templates/design.md. If code ever drifts, fix the code to match the spec.

Feeds the next step
With copy and the accent set, Phase 1 is complete. The memory bank (Step 5) records the accent pointer in .memory/10-product.md so future sessions know the design language without re-deriving it.

This two-knob approach is not specific to this boilerplate. It ships as an open-source design system our components follow, so you can see the exact rules an AI coding tool is held to before it ships a button or a card.