Operator's Notebook design register — a dense BI/admin dashboard visual language built on OKLCH ink-blue tokens, hairline dividers, Bricolage Grotesque display, and 60/30/10 accent discipline. Use when designing or migrating admin dashboards, internal tools, BI consoles, or operator-facing surfaces that need editorial clarity over SaaS chrome. Triggers on tasks involving shadcn/ui dashboards, Next.js admin apps, Tailwind v4 token migration, or rewriting "default shadcn" SaaS-flavored UIs into a disciplined editorial register.
Full contract (chart tokens, popover, ring, semantic foregrounds) in references/recipes/tokens.md.
Semantic mapping (the only text-*/bg-* color utilities allowed in app code)
Role
Token
Canvas
bg-background
Card / popover surface
bg-card (visually equal to background)
Primary ink
text-foreground
Faded ink (labels, captions)
text-muted-foreground
Active / confirmed / positive
text-primary, bg-primary/5, border-primary/40
Negative / destructive
text-destructive, bg-destructive/5
Hairline
border-border
Subtle fill
bg-muted, bg-accent/55
Nobg-emerald-*, bg-green-*, bg-amber-*, bg-blue-*, bg-purple-*, bg-sky-*, text-red-500 or any raw Tailwind color. Map every existing literal to a semantic token. The grep grep -rE "(bg|text)-(emerald|green|amber|sky|purple|red|blue|gray|slate|zinc|neutral)-[0-9]" should return zero hits in app code (UI primitives excepted only if they ship with the shadcn defaults you haven't yet touched).
Type stack
Role
Font
CSS variable
Notes
Body
Noto Sans SC / Noto Sans JP / Inter
--font-body
Match the user-facing language. Weights 400/500/600/700.
Full chart contract (axes, bar radius=0, area fillOpacity: 0.12, hue-locked series) in references/recipes/charts.md.
Universal BANs (match-and-refuse)
These are absolute. If your PR adds one of these, the PR is wrong:
No border-left / border-right ≥ 2px as accent stripe — use a leading icon, tinted background, or the ink-dot pattern
No gradient text (bg-clip-text + any gradient) — text fills are solid color, always
No bounce / elastic easing — use ease-out curves only; one authored anticipation curve max per app
No animate-{width,height,top,left,padding,margin} — transform + opacity only
No bg-card shadow chrome — if you reach for shadow-sm/shadow-md, you've broken the register
No bg-white / bg-black — overlays use bg-foreground/40, surfaces use bg-card
No raw Tailwind color literals (bg-emerald-100, text-red-500, etc.) — map to semantic tokens
No icons in the metric strip — cells are label + figure only
No glassmorphism (backdrop-blur on chrome) — solid bg-popover / bg-card
No layout-prop animation in chrome — sidebar/header are CSS-transition only; framer-motion stays for genuine modal/form orchestration
Full taxonomy + the perl scrub commands in references/bans.md.
Implementation Checklist (big-bang migration)
Order matters. Don't skip phases — token drift propagates fast.
Phase 1 — Foundation: rewrite globals.css to the OKLCH contract, delete .dark block + tw-animate-css + next-themes, wire three fonts via next/font/google, set lang correctly
Hairlines, not chrome. A border border-border carries more hierarchy in this register than any shadow.
One accent per screen. Primary tint is the 10% of the 60/30/10 — it marks the single most-watched metric, the active nav row, the confirmed CTA. If two things on screen claim "primary," the screen is wrong.
Semantic tokens, always. Never reach for bg-emerald-100. If you can't name the role (positive, destructive, muted, foreground), the color doesn't belong.
Density beats whitespace. A 5-cell metric strip + chart + table on one viewport is the goal, not a 3-card grid with breathing room.
Editorial type, not SaaS type. Bricolage Grotesque on display moments + Sometype Mono on every number creates the voice. The body font carries language; the display and mono do the lifting.
CSS for chrome motion, framer-motion for orchestration. Sidebar/header/nav are pure transitions. Modals and multi-step forms can still use framer-motion where genuine orchestration helps.
No dark mode unless explicitly required. The register is light-mode canonical. Adding dark tokens without testing every screen creates drift.
1---2name: operators-notebook3description: Operator's Notebook design register — a dense BI/admin dashboard visual language built on OKLCH ink-blue tokens, hairline dividers, Bricolage Grotesque display, and 60/30/10 accent discipline. Use when designing or migrating admin dashboards, internal tools, BI consoles, or operator-facing surfaces that need editorial clarity over SaaS chrome. Triggers on tasks involving shadcn/ui dashboards, Next.js admin apps, Tailwind v4 token migration, or rewriting "default shadcn" SaaS-flavored UIs into a disciplined editorial register.4---56# Operator's Notebook78A complete design register for dense, glance-and-decide internal dashboards. Cool off-white canvas biased toward ink-blue, hairlines instead of card shadow, editorial display type, semantic-token-only color discipline. The visual opposite of "default shadcn SaaS."910## When to Apply1112Reach for this register when building:1314- Admin dashboards (ops, finance, content moderation)15- Internal BI consoles reading from PostHog / Metabase / warehouse16- CRUD-heavy operator tools (player lists, store management, audit queues)17- Multi-tenant back-office surfaces18- Any Next.js + Tailwind v4 + shadcn/ui app where the current look reads as "generic SaaS" and you want editorial discipline19- Migrations from default shadcn (12px rounded cards, blue-500 primary, Geist Sans) to a single coherent voice2021Avoid for:2223- Consumer marketing sites (the register is intentionally chrome-poor)24- Mobile-first apps where dense hairline strips collapse poorly25- Brand-led product surfaces that need a distinctive accent system (this register reserves accent for "active" state only)2627## What You Get28291. **A complete OKLCH token contract** (h~250, `--radius: 0.25rem`, no dark-mode drift)302. **A three-font stack** (Bricolage Grotesque display + body font + Sometype Mono numerics)313. **shadcn/ui primitive variants** tuned to the register (no shadow, no pillowy radius, transparent outline, ring-1 focus)324. **Shared primitives** (`PageHeader`, `StatCard`, `SectionLabel`, `EmptyState`)335. **Layout chrome** (60-wide hairline sidebar with ink-dot active, solid header, CSS-only mobile slide-in)346. **Chart typography contract** (recharts constants — flat bars, dashed grid, hue-locked series)357. **A migration playbook** for taking a default-shadcn admin to this register without touching data flow3637## Quick Reference3839### Token contract (the only colors you ever use)4041```css42:root {43 --background: oklch(98% 0.003 250);44 --foreground: oklch(22% 0.020 250);45 --card: oklch(99% 0.002 250);46 --primary: oklch(35% 0.040 250);47 --accent: oklch(92% 0.025 250);48 --muted: oklch(96% 0.003 250);49 --muted-foreground: oklch(52% 0.010 250);50 --destructive: oklch(52% 0.140 28);51 --border: oklch(88% 0.004 250);52 --radius: 0.25rem;53}54```5556Full contract (chart tokens, popover, ring, semantic foregrounds) in [`references/recipes/tokens.md`](references/recipes/tokens.md).5758### Semantic mapping (the only `text-*`/`bg-*` color utilities allowed in app code)5960| Role | Token |61| ---------------------------- | ------------------------------------------- |62| Canvas | `bg-background` |63| Card / popover surface | `bg-card` (visually equal to background) |64| Primary ink | `text-foreground` |65| Faded ink (labels, captions) | `text-muted-foreground` |66| Active / confirmed / positive | `text-primary`, `bg-primary/5`, `border-primary/40` |67| Negative / destructive | `text-destructive`, `bg-destructive/5` |68| Hairline | `border-border` |69| Subtle fill | `bg-muted`, `bg-accent/55` |7071**No** `bg-emerald-*`, `bg-green-*`, `bg-amber-*`, `bg-blue-*`, `bg-purple-*`, `bg-sky-*`, `text-red-500` or any raw Tailwind color. Map every existing literal to a semantic token. The grep `grep -rE "(bg|text)-(emerald|green|amber|sky|purple|red|blue|gray|slate|zinc|neutral)-[0-9]"` should return zero hits in app code (UI primitives excepted only if they ship with the shadcn defaults you haven't yet touched).7273### Type stack7475| Role | Font | CSS variable | Notes |76| -------- | ---------------------------------- | ------------------- | ---------------------------------------------------------------- |77| Body | Noto Sans SC / Noto Sans JP / Inter | `--font-body` | Match the user-facing language. Weights 400/500/600/700. |78| Display | Bricolage Grotesque (variable) | `--font-display` | Section labels, headlines, metric figures. Tight tracking. |79| Mono | Sometype Mono | `--font-mono` | IDs, timestamps, prices, tabular metrics. Never running prose. |8081Globally enable tabular figures: `body { font-feature-settings: "tnum" }`.8283Recipes for `next/font/google` wiring in [`references/recipes/fonts.md`](references/recipes/fonts.md).8485### Canonical patterns (memorize these five)8687#### 1. Hairline metric strip (replaces the SaaS card grid)8889```tsx90<div className="grid grid-cols-1 divide-x divide-y divide-border border border-border md:grid-cols-5 md:divide-y-0">91 {cells.map((c) => (92 <StatCard key={c.label} label={c.label} value={c.value} hint={c.hint} accent={c.accent} />93 ))}94</div>95```9697- Each cell: label + Bricolage 28px figure + optional hint98- **No icons in the strip**99- **Exactly one cell per screen** carries `accent` — that's the 60/30/10 highlighter100101#### 2. Mini-cap section label (replaces card titles)102103```tsx104<h2 className="font-display text-[11px] font-medium uppercase tracking-[0.1em] text-muted-foreground border-b border-border pb-2">105 预约日程106</h2>107```108109Same shape across dashboard, list views, and chart sections so the whole app reads as one ledger.110111#### 3. Ink-dot active nav (no border-left stripe)112113```tsx114<Link115 href={item.href}116 className={cn(117 "flex items-center gap-2 px-3 py-2 text-sm transition-colors hover:bg-accent/30",118 isActive ? "bg-accent/55 text-foreground" : "text-muted-foreground",119 )}120>121 {isActive ? <span className="h-1.5 w-1.5 rounded-full bg-primary" /> : <span className="h-1.5 w-1.5" />}122 <item.icon className="h-4 w-4" />123 <span>{item.label}</span>124</Link>125```126127#### 4. Hairline card surface (replaces shadow + pillowy radius)128129```tsx130<Card className="border border-border bg-card p-5">131 {/* No `shadow-sm`, no `rounded-2xl`, no backdrop-blur */}132</Card>133```134135The `Card` primitive itself is tuned to ship `rounded-md border border-border bg-card` with no shadow — see [`references/recipes/primitives.md`](references/recipes/primitives.md).136137#### 5. Charts (recharts, flat + editorial)138139```ts140export const CHART_GRID_DASH = "2 4";141export const CHART_TICK_SM = { fontSize: 11, fill: "var(--muted-foreground)" };142export const CHART_TOOLTIP_CONTENT_STYLE = {143 background: "var(--card)",144 border: "1px solid var(--border)",145 borderRadius: 4,146 fontSize: 12,147 color: "var(--foreground)",148};149```150151Full chart contract (axes, bar radius=0, area `fillOpacity: 0.12`, hue-locked series) in [`references/recipes/charts.md`](references/recipes/charts.md).152153## Universal BANs (match-and-refuse)154155These are absolute. If your PR adds one of these, the PR is wrong:1561571. **No `border-left` / `border-right` ≥ 2px as accent stripe** — use a leading icon, tinted background, or the ink-dot pattern1582. **No gradient text** (`bg-clip-text` + any gradient) — text fills are solid color, always1593. **No bounce / elastic easing** — use `ease-out` curves only; one authored anticipation curve max per app1604. **No `animate-{width,height,top,left,padding,margin}`** — transform + opacity only1615. **No `bg-card` shadow chrome** — if you reach for `shadow-sm`/`shadow-md`, you've broken the register1626. **No `bg-white` / `bg-black`** — overlays use `bg-foreground/40`, surfaces use `bg-card`1637. **No raw Tailwind color literals** (`bg-emerald-100`, `text-red-500`, etc.) — map to semantic tokens1648. **No icons in the metric strip** — cells are label + figure only1659. **No glassmorphism** (`backdrop-blur` on chrome) — solid `bg-popover` / `bg-card`16610. **No layout-prop animation in chrome** — sidebar/header are CSS-transition only; framer-motion stays for genuine modal/form orchestration167168Full taxonomy + the perl scrub commands in [`references/bans.md`](references/bans.md).169170## Implementation Checklist (big-bang migration)171172Order matters. Don't skip phases — token drift propagates fast.173174- [ ] **Phase 1 — Foundation**: rewrite `globals.css` to the OKLCH contract, delete `.dark` block + `tw-animate-css` + `next-themes`, wire three fonts via `next/font/google`, set `lang` correctly175- [ ] **Phase 2 — shadcn/ui primitives**: transplant the Notebook-tuned variants of `button`, `card`, `input`, `dialog`, `badge`, `label`, `textarea`, `tabs`, `select`, `dropdown-menu`, `tooltip`, `switch`, `checkbox`, `scroll-area`, `separator`, `skeleton`, `avatar`, `table`176- [ ] **Phase 3 — Shared primitives**: create `components/shared/{page-header,section-label,stat-card,empty-state}.tsx` + `lib/chart-typography.ts`177- [ ] **Phase 4 — Chrome**: rewrite `sidebar`, `header`, `mobile-nav` (CSS slide-in), root layout (`md:pl-60` shell)178- [ ] **Phase 5 — Auth pages**: login → centered 360px column with mini-cap eyebrow + Bricolage title + hairline divider179- [ ] **Phase 6 — Page-level chrome swap**: visit every route, swap `<Card className="shadow-sm">` → `<Card>`, stat grids → hairline strips, section dividers → `<SectionLabel>`, color literals → semantic tokens. **Do not touch oRPC calls, React Query hooks, form schemas, mutation callbacks, or permission checks.**180- [ ] **Phase 7 — Verification**: `grep -rE "border-l-[2-9]|bg-clip-text|bg-(white|black)|shadow-sm|rounded-(xl|2xl|3xl)|text-[0-9]"` returns zero in app code. `pnpm typecheck && pnpm lint && pnpm build` all green. Playwright sweep every route, screenshot, assert no React warnings.181182Full migration playbook in [`references/recipes/migration-checklist.md`](references/recipes/migration-checklist.md).183184## File Map185186| Path | What it gives you |187| ------------------------------------------------------- | ------------------------------------------------------ |188| `references/design-contract.md` | Full register description (aesthetic, why, when, where) |189| `references/bans.md` | All 10 absolute BANs + grep commands to enforce them |190| `references/recipes/tokens.md` | Drop-in `globals.css` (full token block + keyframes) |191| `references/recipes/fonts.md` | `lib/fonts.ts` + `app/layout.tsx` wiring |192| `references/recipes/primitives.md` | shadcn/ui variant overrides (button/card/input/dialog) |193| `references/recipes/shared-primitives.md` | `PageHeader`, `StatCard`, `SectionLabel`, `EmptyState` |194| `references/recipes/chrome.md` | Sidebar / header / mobile-nav / layout shell |195| `references/recipes/login.md` | Centered 360px login chrome |196| `references/recipes/charts.md` | `chart-typography.ts` + recharts patterns |197| `references/recipes/migration-checklist.md` | Big-bang migration playbook |198199## Key Principles2002011. **Hairlines, not chrome.** A `border border-border` carries more hierarchy in this register than any shadow.2022. **One accent per screen.** Primary tint is the 10% of the 60/30/10 — it marks the single most-watched metric, the active nav row, the confirmed CTA. If two things on screen claim "primary," the screen is wrong.2033. **Semantic tokens, always.** Never reach for `bg-emerald-100`. If you can't name the role (`positive`, `destructive`, `muted`, `foreground`), the color doesn't belong.2044. **Density beats whitespace.** A 5-cell metric strip + chart + table on one viewport is the goal, not a 3-card grid with breathing room.2055. **Editorial type, not SaaS type.** Bricolage Grotesque on display moments + Sometype Mono on every number creates the voice. The body font carries language; the display and mono do the lifting.2066. **CSS for chrome motion, framer-motion for orchestration.** Sidebar/header/nav are pure transitions. Modals and multi-step forms can still use framer-motion where genuine orchestration helps.2077. **No dark mode unless explicitly required.** The register is light-mode canonical. Adding dark tokens without testing every screen creates drift.
Run npx skillmds@latest add pseudoyu/operators-notebook in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Operator's Notebook design register — a dense BI/admin dashboard visual language built on OKLCH ink-blue tokens, hairline dividers, Bricolage Grotesque display, and 60/30/10 accent discipline. Use when designing or migrating admin dashboards, internal tools, BI consoles, or operator-facing surfaces that need editorial clarity over SaaS chrome. Triggers on tasks involving shadcn/ui dashboards, Next.js admin apps, Tailwind v4 token migration, or rewriting "default shadcn" SaaS-flavored UIs into a disciplined editorial register. It is listed under Web & Frontend on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
pseudoyu (@pseudoyu) published this skill. Their other Agent Skills are listed on their SkillMD profile.