Falkster Design System, for Claude
This file is the source of truth for every prototype you build in my style. It's the tokens, components, and copy rules the site itself runs on. Use it any time I ask for a prototype, landing page,...
The template
name: falkster-design-system description: The design system every prototype on falkster.com is built on. Drop this into Claude (as a SKILL.md, a system prompt, or a chat paste) and every prototype Claude builds will match the site's look, feel, and voice. version: 1.0.0 owner: Falk Gottlob site: https://falkster.com updated: 2026-04-20
Falkster Design System, for Claude
This file is the source of truth for every prototype you build in my style. It's the tokens, components, and copy rules the site itself runs on. Use it any time I ask for a prototype, landing page, feature page, or internal tool that should look like it belongs on falkster.com.
There are three ways to plug this into Claude.
How to use
Mode 1, paste into Claude chat
Paste this whole file at the start of a conversation, then say:
Build a
{page | feature | prototype}that does{…}, using the falkster design system above. Next.js 16, Tailwind v4, TypeScript. Output the full file(s) only, no commentary.
Mode 2, Claude Code skill
Save this file at .claude/skills/falkster-design-system/SKILL.md in any repo.
Claude Code will load it automatically when it sees words like "prototype",
"landing page", "style the…", etc. Then just prompt:
/skill falkster-design-system
Build a pricing page for a PM automation tool.
Mode 3, API system prompt
Use the Compact preamble at the bottom of this file as a system prompt for API calls. It's ~400 tokens and covers 90% of cases. Expand from the full spec if the output drifts.
The voice rules (these come first)
Before any code, match the voice. Every prototype ships with copy, not lorem.
- First person. "My practice", "I've found", not "our users" or "we".
- No em dashes (, ). Ever. Use commas, periods, or "and".
- Short sentences. One idea per sentence. No throat-clearing.
- No AI tells. Banned words: genuinely, furthermore, it's worth noting, fundamentally, consequential, leverage (as a verb), unlock, delve, nuanced, robust, streamline.
- Concrete over abstract. Name a real tool, a real number, a real moment.
- End with action. "Pick one thing this week." "Try it tomorrow."
- Credit sources when you borrow a concept (Torres, Cagan, Reforge).
If you're writing a button label, use a verb: "Ship it", "See the eval", "Open the lab". Never "Learn More" or "Click Here".
Tech stack (assume unless told otherwise)
- Next.js 16 App Router, React 19, TypeScript strict mode
- Tailwind CSS v4 with CSS-first
@themeconfig (nottailwind.config.js) - Fonts loaded via Google Fonts in
globals.css: Inter (body), DM Sans (display), JetBrains Mono (captions/code), Source Serif 4 (prose) - Icons
lucide-react - No component libraries. No shadcn, no Radix. Tailwind utilities only.
- Deployment Railway, Nixpacks builder
Design tokens
Copy this @theme block straight into globals.css under @import "tailwindcss";.
These are the real values the site runs on, current as of the last update.
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,400;9..40,500;9..40,600;9..40,700&family=Inter:wght@400;500;600;700&family=Source+Serif+4:opsz,wght@8..60,400;8..60,500;8..60,600;8..60,700&family=JetBrains+Mono:wght@400&display=swap');
@import "tailwindcss";
@theme {
/* Surfaces, cool moonlit navy */
--color-bg: #0a0e1a;
--color-bg-elevated: #12182b;
--color-bg-card: #1c2337;
--color-bg-hover: #272f44;
--color-border: #2d3548;
--color-border-bright:#3a4760;
/* Text, cool whites */
--color-text: #e6ecf4;
--color-text-muted: #9eafc7;
--color-text-dim: #6b7a94;
/* Primary accent, vivid sky */
--color-accent: #38bdf8; /* sky-400 */
--color-accent-bright: #7dd3fc; /* sky-300 */
--color-accent-glow: rgba(56, 189, 248, 0.28);
/* Category accents, cool, saturated, each carries clear identity */
--color-neon-cyan: #22d3ee; /* cyan-400 · methodology, analytics */
--color-neon-green: #34d399; /* emerald-400 · AI agents, go, signals */
--color-neon-pink: #e879f9; /* fuchsia-400 · foundation, alerts */
--color-neon-orange: #818cf8; /* indigo-400 · leadership, execution */
/* Typography */
--font-sans: "Inter", "Google Sans Text", "Roboto", ui-sans-serif, system-ui, sans-serif;
--font-display: "DM Sans", "Google Sans Display", "Google Sans", "Inter", system-ui, sans-serif;
--font-serif: "Source Serif 4", Georgia, "Times New Roman", serif;
--font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}
/* Base body */
body {
background-color: var(--color-bg);
color: var(--color-text);
font-family: var(--font-sans);
font-size: 17px;
line-height: 1.6;
letter-spacing: -0.003em;
}
h1, h2, h3, h4 {
font-family: var(--font-display);
letter-spacing: -0.018em;
font-weight: 600;
}
h1 { line-height: 1.05; }
h2 { line-height: 1.15; }
h3 { line-height: 1.25; }
/* Gradient display text */
.gradient-text {
background: linear-gradient(120deg, #38bdf8 0%, #22d3ee 45%, #e879f9 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
/* Accent glow for primary CTAs */
.glow-accent {
box-shadow:
0 0 0 1px rgba(56, 189, 248, 0.40),
0 10px 34px -6px rgba(56, 189, 248, 0.55),
0 0 24px -4px rgba(34, 211, 238, 0.35);
}
Color semantics (which token to use when)
| Token | Hex | Use for |
|---|---|---|
bg | #0a0e1a | Page background, root |
bg-elevated | #12182b | Nav bar, sticky headers, footer |
bg-card | #1c2337 | Cards, panels, pre/code blocks |
bg-hover | #272f44 | Hover state on cards and list rows |
border | #2d3548 | Default dividers, card outlines |
border-bright | #3a4760 | Hover border, focused outline |
text | #e6ecf4 | Headings, primary body |
text-muted | #9eafc7 | Secondary body, descriptions |
text-dim | #6b7a94 | Captions, timestamps, metadata |
accent | #38bdf8 | Primary CTA fill, links, active state |
accent-bright | #7dd3fc | Hover on accent, link hover |
neon-cyan | #22d3ee | Methodology, analytics, "passing" |
neon-green | #34d399 | AI agents, shipped, "go", signals |
neon-pink | #e879f9 | Foundation chapters, alerts, high-intensity |
neon-orange | #818cf8 | Leadership, execution, warning |
Typography scale
| Role | Classes |
|---|---|
| Display XL (hero) | text-5xl md:text-7xl font-bold tracking-tight leading-[1.05] |
| Display L (section hero) | text-4xl md:text-5xl font-bold tracking-tight leading-tight |
| Heading 2 | text-3xl font-bold tracking-tight |
| Heading 3 | text-2xl font-semibold |
| Heading 4 | text-xl font-semibold |
| Body large | text-lg text-text-muted leading-relaxed |
| Body | text-base text-text-muted leading-relaxed |
| Small | text-sm text-text-dim |
| Mono caption | text-[11px] font-mono text-neon-cyan uppercase tracking-wider |
Spacing
Tailwind default scale, 4px base. Common steps: p-2 p-3 p-4 p-5 p-6 p-8 p-10 p-12 p-16 p-24. Section vertical padding: py-12 md:py-16 for normal, py-20 md:py-28 for heroes.
Radii
rounded-md (6px) small controls. rounded-lg (8px) buttons, inputs, pills.
rounded-xl (12px) cards. rounded-2xl (16px) hero panels. rounded-full
ticker pills and avatars.
Component patterns (copy-paste ready)
Primary button
<button className="px-5 py-2.5 rounded-lg bg-accent hover:bg-accent-bright text-white font-medium text-sm transition-colors glow-accent">
Ship it
</button>
Secondary button
<button className="px-5 py-2.5 rounded-lg border border-border hover:border-accent text-text hover:text-accent-bright font-medium text-sm transition-all">
See the eval
</button>
Tinted action buttons (go / warning / destructive)
<button className="px-5 py-2.5 rounded-lg bg-neon-green/10 border border-neon-green/30 text-neon-green hover:bg-neon-green/20 font-medium text-sm transition-colors">
Run the agent
</button>
<button className="px-5 py-2.5 rounded-lg bg-neon-orange/10 border border-neon-orange/30 text-neon-orange hover:bg-neon-orange/20 font-medium text-sm transition-colors">
Needs review
</button>
<button className="px-5 py-2.5 rounded-lg bg-neon-pink/10 border border-neon-pink/30 text-neon-pink hover:bg-neon-pink/20 font-medium text-sm transition-colors">
Kill it
</button>
Status pill / badge
<span className="inline-flex items-center gap-1.5 px-2.5 py-1 text-[11px] font-mono uppercase tracking-wider rounded-md border border-neon-green/30 bg-neon-green/5 text-neon-green">
<span className="w-1.5 h-1.5 rounded-full bg-current" />
Shipped
</span>
Swap neon-green for any accent: neon-cyan (eval passing), neon-orange
(needs review), neon-pink (blocked), accent (active).
Section eyebrow (mono caption)
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full border border-accent/30 bg-accent/5 text-[11px] font-mono uppercase tracking-wider text-accent-bright">
<span className="w-1.5 h-1.5 rounded-full bg-accent-bright" />
Section 01 · Public
</div>
Default card
<div className="rounded-xl border border-border bg-bg-card p-5 hover:border-border-bright transition-colors">
<div className="text-xs font-mono text-accent-bright uppercase tracking-wider mb-2">
Default
</div>
<h4 className="font-semibold text-text mb-2">Card title goes here</h4>
<p className="text-sm text-text-dim">
Neutral background, subtle border, the default container.
</p>
</div>
Accent card (pulls attention)
<div className="rounded-xl border border-neon-green/30 bg-neon-green/5 p-5 hover:bg-neon-green/10 transition-colors">
<div className="text-xs font-mono text-neon-green uppercase tracking-wider mb-2">
Accent · go
</div>
<h4 className="font-semibold text-text mb-2">Accent card</h4>
<p className="text-sm text-text-dim">
Use when the card should signal forward motion.
</p>
</div>
Input (text)
<input
type="text"
placeholder="The signal you saw today"
className="w-full px-4 py-3 rounded-lg bg-bg-card border border-border text-text placeholder:text-text-dim focus:border-accent focus:outline-none focus:ring-2 focus:ring-accent/20 transition-all"
/>
Inline code + code block
<p className="text-sm text-text-muted">
Reference a token like{" "}
<code className="px-1.5 py-0.5 rounded bg-bg-card border border-border font-mono text-xs text-accent-bright">
text-accent-bright
</code>
.
</p>
<pre className="rounded-lg border border-border bg-bg-card p-4 text-xs font-mono text-text-muted overflow-auto">
<code>{`const eval = loadEval('./evals/onboarding.md');
const score = await run(eval, 'claude-sonnet-4-6');
if (score < 0.82) throw new Error('blocked');`}</code>
</pre>
Link (inline)
<a className="text-accent-bright underline decoration-1 underline-offset-[3px] hover:text-neon-cyan transition-colors">
read the handbook
</a>
Layout templates
Page shell
export default function Page() {
return (
<div className="min-h-screen bg-bg">
<div className="max-w-5xl mx-auto px-6 py-12 md:py-16">
{/* content */}
</div>
</div>
);
}
Use max-w-5xl for prose-ish pages, max-w-6xl for dashboards with side rails,
max-w-7xl for full tool shells.
Hero section
<section className="pt-16 pb-12 md:pt-24 md:pb-20">
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full border border-neon-green/30 bg-neon-green/5 text-[11px] font-mono uppercase tracking-wider text-neon-green mb-6">
<span className="w-1.5 h-1.5 rounded-full bg-neon-green animate-pulse" />
Live · 133,562 builders
</div>
<h1 className="text-5xl md:text-7xl font-bold tracking-tight leading-[1.05] mb-6">
Ship the prototype to the customer{" "}
<span className="gradient-text">before engineering scales it</span>
</h1>
<p className="text-lg md:text-xl text-text-muted leading-relaxed max-w-2xl">
A signal arrived this morning. I shipped a working prototype by lunch. This
is how builders run now.
</p>
<div className="mt-8 flex gap-3">
<button className="px-5 py-2.5 rounded-lg bg-accent hover:bg-accent-bright text-white font-medium text-sm transition-colors glow-accent">
See the handbook
</button>
<button className="px-5 py-2.5 rounded-lg border border-border hover:border-accent text-text hover:text-accent-bright font-medium text-sm transition-all">
Open the lab
</button>
</div>
</section>
Card grid
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{items.map((item) => (
<div key={item.id} className="rounded-xl border border-border bg-bg-card p-5 hover:border-border-bright transition-colors">
<div className="text-xs font-mono text-accent-bright uppercase tracking-wider mb-2">
{item.category}
</div>
<h4 className="font-semibold text-text mb-2">{item.title}</h4>
<p className="text-sm text-text-dim">{item.description}</p>
</div>
))}
</div>
Two-column with sticky side rail
<div className="grid grid-cols-1 lg:grid-cols-[1fr_320px] gap-10">
<main>{/* primary content */}</main>
<aside className="lg:sticky lg:top-24 lg:self-start space-y-4">
{/* related links, articles */}
</aside>
</div>
Section with eyebrow + title + subtitle
<section className="mb-16">
<div className="mb-6 pb-4 border-b border-border/50">
<div className="text-xs font-mono uppercase tracking-wider text-neon-cyan mb-2">
02 · Methodology
</div>
<h2 className="text-3xl font-bold tracking-tight text-text mb-1">
The signal-to-prototype loop
</h2>
<p className="text-sm text-text-dim">
How I go from noticed signal to shipped prototype in under an hour.
</p>
</div>
{/* content */}
</section>
Motion patterns
Scroll reveal (fade + slide up)
Add data-reveal to any element. CSS in globals.css handles the transition.
Set html.js-reveal from a <ScrollReveal /> island client component.
<div data-reveal className="transition-all">
I fade up when I enter the viewport.
</div>
Live color-cycling pill (shipped events)
<div className="live-pill inline-flex items-center gap-2 px-3 py-1 rounded-full border text-[11px] font-mono uppercase tracking-wider">
<span className="live-dot w-1.5 h-1.5 rounded-full" />
Live · shipping now
</div>
.live-pill and .live-dot are defined in the globals.css block above, they
cycle through the four neon colors on an 8s loop.
AI border (comet-of-light on hover)
Wrap anything in .ai-border to get a Gemini-style traveling light streak on
hover. The CSS is in the globals block.
<div className="ai-border rounded-[22px] bg-bg-card p-6">
Hover me.
</div>
Horizontal ticker / marquee
Duplicate content twice, use the .ticker-marquee class, set duration inline.
<div className="relative overflow-hidden">
<div className="ticker-marquee flex gap-8 whitespace-nowrap" style={{ animationDuration: "40s" }}>
{items.concat(items).map((item, i) => (
<span key={i} className="text-sm text-text-dim">{item}</span>
))}
</div>
</div>
File structure for a new prototype
When I ask for a prototype, create this shape:
src/app/{slug}/
├── page.tsx # server component, exports metadata, returns <Client />
├── {Slug}Client.tsx # client component with the actual UI
└── (optional files)
page.tsx template:
import type { Metadata } from "next";
import SlugClient from "./SlugClient";
export const metadata: Metadata = {
title: "The Page | Falkster",
description: "What this prototype does, in one sentence.",
alternates: { canonical: "https://falkster.com/slug" },
openGraph: { title: "The Page | Falkster", description: "…", type: "website" },
};
export default function Page() {
return <SlugClient />;
}
Always include canonical URL and OG metadata, the site is SEO/GEO optimized.
Copy patterns (not just words, structure)
Hero headline formula
[action verb] the [noun] [constraint], [contrast clause]
Good examples from the site:
- "Ship the prototype to the customer before engineering scales it."
- "Kill the roadmap. Build the loop."
- "The eval is the spec."
Bad:
- "Accelerate your product velocity with AI." (vague verb, buzzwords)
- "Empowering PMs to leverage AI." (AI-smell, no stakes)
Card title + desc formula
Title = 3–6 words, imperative or declarative. Description = one sentence, no fluff, ends with a period.
- "Kill the status meeting. Replace the ritual with a Loom and a KPI."
- "Your first OST. Pick the outcome you care about. The tree writes itself."
CTA verbs
Always active. "Ship", "Run", "Open", "See", "Read", "Watch", "Try", "Fork". Never "Learn more", "Get started", "Discover".
Do / don't
Do
- Use
text-text-mutedfor body copy by default, nottext-text. The muted cool-blue reads better on the navy than bright white. - Put the eyebrow (mono uppercase caption) above every section title.
- End every landing page with a clear next action (enter the lab, read the handbook, etc).
- Use
neon-greensparingly, it's for moments of success / signal, not decoration.
Don't
- Don't use shadcn, Radix, or any component library. Tailwind utilities only.
- Don't use purple. The old theme used purple, the new theme is sky-navy.
Any
#7c5cffor#9d82ffyou see in old screenshots is wrong. - Don't write "Learn More" on a button. Replace with a verb.
- Don't use em dashes. Ever. Commas, periods, "and".
- Don't center body copy. Left-align prose, only center hero headlines and status indicators.
- Don't use drop shadows. Use borders and the
.glow-accentutility only.
Example prompt (start-to-finish)
Here's what a good prompt looks like once you've loaded this file:
Build a "Prototype Review Checklist" page at
/prototype/review.Three sections:
- Hero: eyebrow "prototype · review", headline "Before I ship to the customer", one-sentence intro in first person.
- Checklist: 8 items across 3 groups (Signal, Build, Ship). Each item is a card with a checkbox, a title, and a one-sentence description.
- Footer CTA: "Open the lab" link to
/prototype/lab.Use the design system above. No external libraries beyond
lucide-react. Outputsrc/app/prototype/review/page.tsxandsrc/app/prototype/review/ReviewClient.tsx.
Compact preamble (~400 tokens, use as a system prompt)
You are building a prototype on falkster.com. Match this design system exactly.
Stack: Next.js 16 App Router, React 19, TypeScript strict, Tailwind v4 (CSS-first
@theme, no tailwind.config.js), lucide-react icons. No shadcn, no Radix.
Colors (Tailwind tokens → hex):
bg=#0a0e1a bg-elevated=#12182b bg-card=#1c2337 bg-hover=#272f44
border=#2d3548 border-bright=#3a4760
text=#e6ecf4 text-muted=#9eafc7 text-dim=#6b7a94
accent=#38bdf8 accent-bright=#7dd3fc
neon-cyan=#22d3ee neon-green=#34d399 neon-pink=#e879f9 neon-orange=#818cf8
Fonts: Inter (body), DM Sans (h1-h4 via font-display), JetBrains Mono (captions
and code). Body 17px, line-height 1.6.
Patterns:
- Page: <div class="min-h-screen bg-bg"><div class="max-w-5xl mx-auto px-6 py-12 md:py-16">…
- Eyebrow: px-3 py-1 rounded-full border border-accent/30 bg-accent/5 text-[11px] font-mono uppercase tracking-wider text-accent-bright
- Hero h1: text-5xl md:text-7xl font-bold tracking-tight leading-[1.05]
- Primary btn: px-5 py-2.5 rounded-lg bg-accent hover:bg-accent-bright text-white font-medium text-sm transition-colors
- Secondary btn: px-5 py-2.5 rounded-lg border border-border hover:border-accent text-text hover:text-accent-bright
- Card: rounded-xl border border-border bg-bg-card p-5 hover:border-border-bright
- Pill: inline-flex items-center gap-1.5 px-2.5 py-1 text-[11px] font-mono uppercase tracking-wider rounded-md border border-{color}/30 bg-{color}/5 text-{color}
- Body copy: text-text-muted (not text-text)
Voice: first person, short sentences, no em dashes, no "genuinely /
fundamentally / leverage / unlock", verbs on CTAs ("Ship it", not "Learn
more"), end with an action.
Always export metadata (title, description, canonical) from page.tsx. Put UI
in a client component. Output only full file contents, no commentary.