.comThis is falkster.com, the notebook. Falkster.AI is the company.Go to falkster.ai

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,...

falkster-design-system.md20 KB2,608 words

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 @theme config (not tailwind.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)

TokenHexUse for
bg#0a0e1aPage background, root
bg-elevated#12182bNav bar, sticky headers, footer
bg-card#1c2337Cards, panels, pre/code blocks
bg-hover#272f44Hover state on cards and list rows
border#2d3548Default dividers, card outlines
border-bright#3a4760Hover border, focused outline
text#e6ecf4Headings, primary body
text-muted#9eafc7Secondary body, descriptions
text-dim#6b7a94Captions, timestamps, metadata
accent#38bdf8Primary CTA fill, links, active state
accent-bright#7dd3fcHover on accent, link hover
neon-cyan#22d3eeMethodology, analytics, "passing"
neon-green#34d399AI agents, shipped, "go", signals
neon-pink#e879f9Foundation chapters, alerts, high-intensity
neon-orange#818cf8Leadership, execution, warning

Typography scale

RoleClasses
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 2text-3xl font-bold tracking-tight
Heading 3text-2xl font-semibold
Heading 4text-xl font-semibold
Body largetext-lg text-text-muted leading-relaxed
Bodytext-base text-text-muted leading-relaxed
Smalltext-sm text-text-dim
Mono captiontext-[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-muted for body copy by default, not text-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-green sparingly, 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 #7c5cff or #9d82ff you 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-accent utility 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:

  1. Hero: eyebrow "prototype · review", headline "Before I ship to the customer", one-sentence intro in first person.
  2. Checklist: 8 items across 3 groups (Signal, Build, Ship). Each item is a card with a checkbox, a title, and a one-sentence description.
  3. Footer CTA: "Open the lab" link to /prototype/lab.

Use the design system above. No external libraries beyond lucide-react. Output src/app/prototype/review/page.tsx and src/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.

More from the toolkit


All templates →