Skip to content

2 cases built from this template

Same prompt, different [VARIABLES]. Click one to preview it above.

About this template

A one-page launch site for a command-line developer tool, written here for a fast code review CLI called Ferrule. It opens with a split hero: a short promise, an install command with npm, brew and npx tabs and a one-click copy button on the left, and a terminal window on the right that types two believable review sessions on a loop, with a spinner, color-coded findings and a passing pre-commit hook. Below it, a diff viewer drawn from scratch shows a real-looking TypeScript change where review comments slide in under specific lines one after another, each with a severity tag, a rule name and a suggested-fix block you can apply. The rest keeps a dense, scannable rhythm: a six-cell feature grid with hairline borders, a config snippet, a benchmark bar race that counts up on scroll, plain text integration chips, an expandable changelog timeline and a final install block with three copyable steps. The whole site is keyboard-first. Press the question mark key, or click the hint chip in the corner, and a shortcut overlay opens with kbd-styled keys; the shortcuts really work, from copying the install command to jumping between sections and replaying the terminal. The palette is near-black with a single lime signal color, semantic green and red for diffs, and amber and blue for severities. Space Grotesk sets the headlines, Inter the body and JetBrains Mono every label, number and line of code, all self-hosted. It suits indie hackers and teams launching a CLI, linter, test runner, migration tool or AI coding assistant. Change the brand, command name, product type, languages and audience, and the copy, terminal sessions, diff and benchmarks are rewritten while layout and motion stay the same. Every animation jumps to its final state when reduced motion is on.

The template prompt

The live demo was built from exactly this text — nothing added. The other cases only change the values of the [VARIABLES].

# Dark Developer Tool Launch Page

Build this website exactly as described below. Replace the [VARIABLES] with your own values; keep everything else.

## Brief
A one-page launch site for [BRAND], a local-first [PRODUCT] for [LANGUAGES]. The page proves speed and precision by showing the product working: a hero terminal that types real-looking review sessions, a diff viewer where line comments stream in, a benchmark bar race, a keyboard shortcut overlay opened with '?', a changelog teaser and copy-to-clipboard install commands. Everything is drawn in code; there are no photos.

- Audience: [AUDIENCE]: engineers and tech leads who live in the terminal, distrust marketing pages and decide in under a minute whether a tool is worth one install command.
- Goal: Get the visitor to copy the install command and run a first review. Secondary: show exactly what a review looks like (terminal + diff), back the speed claim with an illustrative benchmark, and signal an active project through the changelog.
- Tone: Terse, technical and confident, like a well-written README. Short sentences, concrete numbers, real command names, no hype words (no 'revolutionary', 'blazing', 'supercharge', 'magic'). Monospace for anything a developer would type or read in a terminal.

## Stack
- Framework: Vite 5 + React 18 + TypeScript
- Styling: Tailwind CSS 3.4
- Libraries: react (MIT), react-dom (MIT), motion (motion.dev, import from 'motion/react') (MIT), lucide-react (ISC), tailwindcss (MIT), postcss (MIT), autoprefixer (MIT), vite (MIT), @vitejs/plugin-react (MIT), typescript (Apache-2.0), @fontsource-variable/space-grotesk (OFL-1.1), @fontsource-variable/inter (OFL-1.1), @fontsource-variable/jetbrains-mono (OFL-1.1)
- Build: `npm run build` → static files in `dist/`. No backend, no server code, no external APIs.
- Setup:
  - Scaffold with npm create vite@latest using the react-ts template. One page: index.html at the project root with entry src/main.tsx. All sections live on this page and are reached by hash anchors (#demo, #features, #benchmarks, #integrations, #changelog, #install).
  - vite.config.ts: base './', plugins [react()], build { outDir 'dist', sourcemap false, assetsInlineLimit 0 }. Do not copy src/ into dist/.
  - Tailwind 3.4 through PostCSS (tailwindcss + postcss + autoprefixer), content ['./index.html', './src/**/*.{ts,tsx}']. In tailwind.config.ts add every color under Design to theme.extend.colors with kebab-case keys (ink, panel, panel-2, line, line-strong, text, muted, faint, signal, signal-ink, add, add-bg, del, del-bg, warn, info) and fontFamily display ['Space Grotesk Variable', 'system-ui', 'sans-serif'], sans ['Inter Variable', 'system-ui', 'sans-serif'], mono ['JetBrains Mono Variable', 'ui-monospace', 'monospace']. Add maxWidth { container: '1200px' } and borderRadius { DEFAULT: '6px', lg: '10px' }.
  - In src/fonts.ts import '@fontsource-variable/space-grotesk', '@fontsource-variable/inter' and '@fontsource-variable/jetbrains-mono'; import src/fonts.ts and src/index.css from src/main.tsx.
  - src/index.css: Tailwind layers; html { scroll-behavior: smooth; scroll-padding-top: 72px } (auto under prefers-reduced-motion); body bg ink, text text, font sans, antialiased; ::selection { background: #C6F43233 }; a .bg-grid utility (two linear-gradients of #FFFFFF08 1px lines every 48px, masked with radial-gradient(ellipse at 50% 0%, black 30%, transparent 75%)); a .noise utility that layers an inline SVG feTurbulence data URI (baseFrequency 0.9, opacity 0.035) as a fixed full-page overlay with pointer-events none; keyframes caret-blink (steps(1) 1s infinite) and pulse-line (signal left border fading from 100% to 0% over 1.2s).
  - File layout: src/content.ts (every string, number, terminal script, diff line, comment, benchmark row, feature, chip, changelog entry and shortcut, typed), src/lib/brand.ts (exports BRAND, BRAND_SLUG and installCommands { npm: 'npm i -g ' + BRAND_SLUG, brew: 'brew install ' + BRAND_SLUG, npx: 'npx ' + BRAND_SLUG + ' review' }), src/lib/clipboard.ts (navigator.clipboard.writeText with a hidden-textarea + document.execCommand('copy') fallback, wrapped in try/catch), src/lib/useReducedMotion.ts (re-export of Motion's useReducedMotion), src/lib/toast.ts (tiny external store via useSyncExternalStore: showToast(text) displays one toast for 1.8s).
  - Components in src/components/: Header.tsx, Wordmark.tsx (inline SVG glyph + name), InstallBox.tsx (tabs + command + copy button; the selected tab is shared through a small store so both install boxes stay in sync), Terminal.tsx (+ terminalScript.ts: the sessions as an array of steps), DiffViewer.tsx (DiffLine.tsx, ReviewComment.tsx, FindingsPanel.tsx), FeatureGrid.tsx, ConfigSnippet.tsx, BenchmarkRace.tsx, Integrations.tsx, Changelog.tsx, FinalCta.tsx, Footer.tsx, ShortcutOverlay.tsx, ShortcutHint.tsx, Toast.tsx, Kbd.tsx, SectionHeading.tsx, Reveal.tsx (Motion whileInView wrapper: opacity 0 to 1, y 16 to 0, 0.5s, once, amount 0.2). src/App.tsx composes them in the section order under Pages & Sections and registers the global keyboard handler (src/lib/useShortcuts.ts).
  - Syntax coloring in the diff, terminal and config snippet is done by hand with a tiny tokenizer in src/lib/highlight.ts (keywords, strings, numbers, comments, function names) mapped to Tailwind classes. No highlighting library.
  - public/favicon.svg as described under Assets. index.html: lang en, <meta name='theme-color' content='#0A0B0D'>, <link rel='icon' href='./favicon.svg' type='image/svg+xml'>, <title>[BRAND] — the [PRODUCT] that finishes before you push</title>.
  - Write ASSETS.md at the project root listing the three Fontsource font packages (OFL-1.1, with upstream authors), lucide-react (ISC) and a line saying every other graphic (wordmark glyph, favicon, grid, noise, terminal and diff chrome, bars) is drawn in code in this project.
  - dist/ holds index.html, hashed JS/CSS, the woff2 font files and favicon.svg. Target under 2 MB.

## Variables
- [BRAND] — Product name (default: "Ferrule"). Invented tool name, one or two words. Used in the wordmark, title, headlines, terminal banner, comment author line, feature copy, changelog and footer. Never a real developer tool.
- [BRAND_SLUG] — Command and package name (default: "ferrule"). Lowercase, no spaces. It is the CLI command typed in every terminal line, the npm/brew package name in the install box, the config file name (.[BRAND_SLUG].toml) and the bot name on diff comments. Derive nothing else from it.
- [PRODUCT] — What the tool is (default: "code review CLI"). Short noun phrase, lowercase. Drives the title, hero copy, feature cards, terminal session content, diff comments and benchmark metric. For a test runner the diff comments become failing-test annotations; for a linter they become rule violations.
- [LANGUAGES] — Languages or file types it covers (default: "TypeScript, Go and Python"). Two to four languages or formats. The terminal file paths, the diff code sample, the config snippet and the first integration chips use these languages.
- [AUDIENCE] — Who it is for (default: "teams that ship several times a day"). Short phrase, lowercase. Used in the hero subline, the features intro and the final call to action.
- [CREDIT] — keep a small "Template by VibeFather" link to https://vibefather.ai/t/dark-developer-tool-launch-page in the footer (default: yes; delete this line to remove it)

The copy under Pages & Sections is written for the default values. If your values differ, rewrite every headline, paragraph, label and image for them — same length, tone and structure. Layout, colors, type and motion stay as described.
Keep all copy, image paths and links in one content file (for example `src/content.ts`), keyed by section, so the content can be swapped later without touching components.

## Design
### Colors
- Ink `#0A0B0D` — Page background, terminal body
- Panel `#111317` — Cards, diff viewer body, install box, overlay panel
- Panel 2 `#171A1F` — Terminal and diff title bars, hunk header rows, hovered rows, kbd keys
- Line `#22262D` — All 1px hairline borders and dividers, inactive benchmark bars track
- Line Strong `#323842` — Hovered borders, inactive benchmark bars, kbd bottom border
- Text `#E7E9EC` — Headlines and body text
- Muted `#8C939D` — Secondary copy, line numbers, terminal prompt path, labels
- Faint `#5B626C` — Footnotes, disabled states, diff context gutter
- Signal `#C6F432` — The one accent: primary buttons, our benchmark bars, active tab underline, focus rings, caret, git branch in the prompt, 'Latest' tag, wordmark glyph
- Signal Ink `#0A0B0D` — Text on Signal buttons and tags
- Add `#3DDC97` — Added-line +/- gutter sign and text tint, success checkmarks, 'perf' and 'fix' changelog tags
- Add BG `rgba(61,220,151,0.09)` — Added-line row background
- Del `#FF6B6B` — Removed-line sign, 'high' severity dot and tag, 'breaking' tag
- Del BG `rgba(255,107,107,0.09)` — Removed-line row background
- Warn `#F5B841` — 'medium' severity dot and tag
- Info `#6CB4FF` — 'low' severity dot and tag, 'feat' changelog tag, code keywords

### Typography
- Display: hero headline (56px desktop / 38px mobile, weight 600, tracking -0.03em, line-height 1.02), section headings (36px / 28px, weight 600, tracking -0.02em), stat numbers: Space Grotesk (OFL), weights 500/600/700
- Text: body 16px/1.6 weight 400, card titles 16px weight 500, buttons 14px weight 500: Inter (OFL), weights 400/500/600
- Mono: terminal (13.5px/1.7), diff (13px/1.65), install commands (15px), eyebrows and labels (12px uppercase, tracking 0.08em), all numbers, kbd keys, chips, version tags: JetBrains Mono (OFL), weights 400/500/700

### Layout & motion
- Spacing: Container max-width 1200px with 24px side padding (16px under 640px). Sections are separated by 1px Line borders full-bleed, with 112px vertical padding on desktop and 72px on mobile. Grids use a 1px gap over a Line-colored background so cells share hairline borders. Inner card padding 24px. Base unit 4px; dense rhythm, no huge empty bands.
- Radius: 6px on buttons, chips, kbd keys, inputs and tags; 10px on the terminal window, diff viewer, install box, overlay panel and feature grid outer frame; 999px only on severity dots and the hint chip.
- Motion: Section reveal: every section heading and block fades up (opacity 0 to 1, y 16px to 0, 0.5s, ease [0.22, 1, 0.36, 1]) once when 20% visible; children stagger by 0.06s.
- Motion: Hero terminal: commands type character by character at 32ms per char with a blinking block caret (Signal, 1s steps); output lines appear one by one with 110ms between lines; the spinner cycles the braille frames ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏ every 80ms for 900ms before being replaced by its result line. After the last line of session 2 it waits 2.6s, fades the body out over 0.3s and restarts session 1. It starts only when the terminal is in view and pauses when off screen or when the tab is hidden.
- Motion: Diff viewer: when the viewer is 35% in view, the three comments open in order, 1.1s apart. For each, the anchored line gets a 1.2s pulse-line highlight, then the comment card expands from height 0 to auto with opacity 0 to 1 (0.45s); the matching item in the Findings panel ticks from a hollow dot to a filled severity dot.
- Motion: Benchmark race: when the chart is 40% in view, bars grow from width 0 to their value (1.1s, ease [0.22, 1, 0.36, 1], stagger 0.12s top to bottom) and the numbers count up in sync using Motion's animate() on a motion value, formatted to one decimal for seconds and integers for counts. Switching tabs replays the race from 0.
- Motion: Micro-interactions: copy buttons swap the Lucide Copy icon for Check with a 0.15s scale pop and show a toast 'Copied: <command>' bottom-center for 1.8s; buttons lift 1px and brighten on hover; chips and cards change border to Line Strong on hover; the active tab underline slides between tabs with a shared layoutId.
- Motion: Shortcut overlay: backdrop fades to rgba(10,11,13,0.72) with backdrop-blur 6px in 0.2s; the panel scales from 0.97 to 1 and fades in over 0.2s; Esc or a backdrop click reverses it.
- Motion: Changelog expand: older entries animate height 0 to auto and fade in over 0.35s.
- Motion: prefers-reduced-motion: no typing, spinner or loop (the terminal renders session 1 complete and static with a Replay button that swaps to session 2), diff comments are all open from the start, bars and numbers render at their final values, reveals are instant, smooth scrolling is off. Overlay and toast still appear but without scale or movement.
- Imagery: No photos and no illustrations. The visual interest comes from code-drawn UI: the terminal window, the diff viewer, the bar chart, hairline grids, a very faint 48px background grid under the hero masked with a radial fade, and a 3.5% SVG noise overlay across the page. The wordmark glyph is an inline SVG: a 20x20 rounded square (radius 5) in Signal with two Ink horizontal strokes of different length, like two diff lines, the lower one offset right by 4px. Icons are Lucide at 18–20px with stroke-width 1.75.

## Pages & Sections
### [BRAND] — launch page (`index.html`)
1. **Content file and copy rules** — All copy below is written for the default values ([BRAND] = Ferrule, [BRAND_SLUG] = ferrule, [PRODUCT] = code review CLI, [LANGUAGES] = TypeScript, Go and Python, [AUDIENCE] = teams that ship several times a day). Put every string, number, terminal step, diff line, comment, benchmark row and list in src/content.ts and render from it. If any variable value differs, rewrite every headline, terminal session, file path, code sample, review comment, rule name, feature, benchmark metric and row label, chip and changelog entry so it is specific and believable for the new product, keeping the same structure, counts and approximate lengths. Every command shown uses [BRAND_SLUG]; every repository, file path, function and commit in the samples is invented (the sample repository is called ledgerline). Product facts used throughout: current version 2.4.0; 212 rules, 143 of them with auto-fixes, 38 security rules; median review 1.8s on a 1,240-line pull request; re-review after a fix 0.4s; cold start 140 ms; runs fully offline; Apache-2.0 core.
   Layout: No visual output. content.ts exports typed objects: nav, hero, install, terminalSessions, diff (file, hunks, lines, comments, findings), features, config, benchmarks (tabs, rows, stats, footnote), integrations, changelog, finalCta, footer, shortcuts.
2. **Header (sticky, shared)** — Left: Wordmark (glyph + '[BRAND]' in JetBrains Mono 15px weight 700) linking to #top, followed by a version pill 'v2.4.0' (mono 11px, Muted text, 1px Line border, radius 6px) that links to #changelog. Center/right nav links (Inter 14px, Muted, hover Text): Demo (#demo), Features (#features), Benchmarks (#benchmarks), Changelog (#changelog). Far right: a ghost icon button with Lucide Keyboard and the tooltip/aria-label 'Keyboard shortcuts (?)' that opens the overlay, and a primary button 'Install' (Signal background, Signal Ink text, Lucide Download 16px) that scrolls to #install.
   Layout: Height 60px, full width, sticky top-0, z-40, background rgba(10,11,13,0.78) with backdrop-blur 10px and a 1px Line bottom border that appears only after scrolling 8px. Inner row uses the 1200px container, flex, items-center, justify-between. Under 768px the four nav links are hidden and only the wordmark, the keyboard button and Install remain; no hamburger menu.
   Motion: Border fades in over 0.2s when scrolled. Nav link of the section currently in view (IntersectionObserver, rootMargin -40% 0 -55% 0) turns Text color with a 1px Signal underline.
3. **Hero (#top)** — Left column, top to bottom: (1) Announcement link chip: a mono 12px pill with a Signal dot, text 'v2.4.0 — suggested fixes for 41 more rules' and Lucide ArrowRight 14px, linking to #changelog. (2) Headline (display): 'Code review that finishes before you push.' (3) Subline (Inter 18px, Muted, max-width 520px): '[BRAND] is a local-first code review CLI for TypeScript, Go and Python. It reads only what changed, leaves line-level comments on real bugs and hands you a fix you can apply with one key. Built for teams that ship several times a day.' (4) InstallBox (see below). (5) Button row: a ghost button 'See it review a diff' with Lucide ArrowDown linking to #demo, then a text hint 'or press ? for shortcuts' in mono 12px Faint with the ? rendered as a Kbd. (6) Mono 12px facts row separated by middle dots, Muted: '1.8s median review · 212 rules · runs offline · Apache-2.0 core'. InstallBox: a 10px-radius Panel box with 1px Line border; top row of three tabs 'npm', 'brew', 'npx' (mono 12px, the active one Text with a 2px Signal underline, inactive Muted); body row with a Signal '$' prompt, the command in mono 15px ('npm i -g ferrule' / 'brew install ferrule' / 'npx ferrule review', built from [BRAND_SLUG]) and a right-aligned 32px icon button (Lucide Copy, aria-label 'Copy install command') that copies the visible command. Right column: the Terminal window. Title bar (36px, Panel 2, 1px Line bottom border): three 10px circles in Line Strong (no traffic-light colors), centered mono 12px Muted title '~/work/ledgerline — zsh', right side two 28px icon buttons Lucide Pause/Play (toggle) and RotateCcw (replay, aria-label 'Replay session'). Body (Ink, 20px padding, fixed height 420px desktop / 360px mobile, overflow hidden, newest lines stay visible by scrolling the body to the bottom). Session 1, line by line (prompt = Muted '~/work/ledgerline' + Signal '(feat/retry-queue)' + Text '$'): typed command 'ferrule review --base main'; output '◆ ferrule 2.4.0 · 14 files changed · +312 −87' (◆ in Signal); spinner line '⠋ Reading diff and call sites…'; replaced by '✓ Reviewed in 1.8s' (✓ in Add); then five findings, each with a colored ● and a fixed-width severity word, path in Text, line number in Muted, message in Muted: 'high    src/billing/retry-queue.ts:40   async callback inside forEach is never awaited'; 'high    src/api/webhooks.ts:118   signature compared with === (timing leak)'; 'medium  src/billing/retry-queue.ts:46   retry limit hard-coded to 3'; 'medium  internal/ledger/post.go:203   error from tx.Rollback() ignored'; 'low     scripts/backfill.py:31   bare except swallows KeyboardInterrupt'; summary line '2 high · 2 medium · 1 low · 4 fixes available' (counts colored by severity); typed command 'ferrule fix 1 2 --apply'; output '✓ Applied 2 fixes · re-reviewed in 0.4s · 0 high remaining'. Session 2 (body clears first): typed 'ferrule review --staged'; '✓ Reviewed 3 files in 0.6s'; 'No high or medium findings. 1 low:'; '● low  src/ui/InvoiceTable.tsx:88  list key uses array index in a sortable table'; typed 'git commit -m "fix: await retries in queue"'; '◆ ferrule pre-commit hook · passed in 0.3s'; '[feat/retry-queue 4e1c9a2] fix: await retries in queue'; '2 files changed, 9 insertions(+), 6 deletions(-)'. Then loop.
   Layout: Full-width section with the .bg-grid background behind it, padding 96px top / 112px bottom (56px / 72px on mobile). Inside the container a 12-column grid at lg (≥1024px): left column spans 5 (vertically centered), terminal spans 7. Below 1024px the columns stack: copy first, terminal second, full width. Terminal has a 1px Line border, 10px radius and a soft shadow 0 30px 80px -30px rgba(198,244,50,0.12). Long terminal lines wrap with a 2-space hanging indent on mobile (font 12px). The InstallBox is max-width 460px, full width on mobile.
   Motion: Headline, subline, install box and facts row fade up in a 0.06s stagger on load. Terminal typing as described under Design motion. Pause toggles the script; Replay restarts session 1. Shortcut 'r' also replays.
4. **Diff review demo (#demo)** — Section heading block: eyebrow (mono 12px uppercase Signal) 'Line-level review'; heading 'Comments land on the line, not in a wall of text.'; intro (Muted, max 600px): 'Every finding is anchored to the exact line, tagged by severity and rule, and most come with a patch. This is the same retry-queue change from the terminal above.' Diff viewer, file header bar: Lucide FileCode2 16px, path 'src/billing/retry-queue.ts' in mono 13px Text, then '+9' in Add and '−6' in Del, right side a mono 12px label 'Unified' and a ghost button 'Replay comments' (Lucide RotateCcw). Hunk header row (Panel 2, Info text): '@@ -38,8 +38,14 @@ export async function drainQueue(queue: RetryQueue)'. Lines (old no. | new no. | sign | code): ' 38 | 38 |   | export async function drainQueue(queue: RetryQueue) {'; ' 39 | 39 |   |   const due = await queue.takeDue(new Date());'; ' 40 |    | - |   due.forEach((job) => {'; ' 41 |    | - |     chargeInvoice(job.invoiceId);'; '    | 40 | + |   due.forEach(async (job) => {'; '    | 41 | + |     await chargeInvoice(job.invoiceId);'; '    | 42 | + |     metrics.increment("billing.retry.charged");'; ' 42 | 43 |   |   });'; ' 43 | 44 |   |'; '    | 45 | + |   for (const job of queue.failed()) {'; '    | 46 | + |     if (job.attempts < 3) {'; '    | 47 | + |       queue.schedule(job, backoff(job.attempts));'; '    | 48 | + |     }'; '    | 49 | + |   }'; ' 44 |    | - |   log.info(`drained ${due.length} jobs`);'; '    | 50 | + |   log.info(`drained ${due.length} jobs, ${queue.failed().length} failed`);'; ' 45 | 51 |   | }'. Comment 1, under new line 40 — author row: wordmark glyph 16px, 'ferrule' mono 12px Text, rule 'async-foreach-await' mono 12px Muted, severity tag 'high' (Del text on Del BG, 1px Del/40% border); body: 'forEach ignores the promise each async callback returns, so drainQueue resolves before any invoice is charged and a failed charge is never caught.'; 'Suggested fix' label, then a mini code block with Add-tinted lines: 'for (const job of due) {' / '  await chargeInvoice(job.invoiceId);' / '  metrics.increment("billing.retry.charged");' / '}'; actions: primary small button 'Apply fix' with Kbd 'a', ghost button 'Ignore' with Kbd 'i'. Comment 2, under new line 46 — rule 'magic-number', tag 'medium' (Warn): 'The retry limit 3 is also hard-coded in src/api/webhooks.ts:77. Read it from config.billing.maxRetries so both paths stay in sync.' Suggested fix: 'if (job.attempts < config.billing.maxRetries) {'. Comment 3, under new line 50 — rule 'structured-logging', tag 'low' (Info): 'queue.failed() walks the whole queue a second time. Reuse the count from the loop above, and pass fields as data so the log is searchable.' Suggested fix: 'log.info("drained", { due: due.length, failed: failedCount });'. Findings panel (right): title 'Findings · 3', list of the three with severity dot, rule name, 'line 40' etc.; below a mono 12px line '1.8s · 14 files · 212 rules checked'. Clicking a finding scrolls the diff to that line and pulses it.
   Layout: Container with an 8/4 split at lg: diff viewer spans 8 columns, Findings panel spans 4 and is sticky (top 84px). Below 1024px the panel moves under the diff as a full-width card. Diff viewer: Panel background, 1px Line border, 10px radius, overflow hidden. Rows are CSS grid columns 44px | 44px | 20px | 1fr; line numbers right-aligned in Faint, sign in Add/Del, added rows Add BG, removed rows Del BG, context rows transparent; code text tinted by the hand tokenizer (keywords Info, strings Add, numbers Warn, function names Text, punctuation Muted). Comments are inserted as full-width rows after their anchor line: a Panel 2 card with 16px padding, inset from the left by 108px on desktop (8px on mobile), 1px Line border, 6px radius, and a 2px left border in the severity color. On mobile the code area scrolls horizontally inside the viewer (font 12px) while comment cards wrap to the viewer width; the page itself never scrolls sideways.
   Motion: Comment sequence as in Design motion. 'Apply fix' (click or 'a' while the comment has focus or is the latest opened unresolved one) collapses the comment to a single resolved row 'Resolved · fix applied' with a Lucide CheckCircle2 in Add, swaps the anchored lines for the suggested code with a 0.3s crossfade, and turns its Findings item to a struck-through Faint label; 'Ignore' collapses it to 'Ignored · reason: false positive'. 'Replay comments' restores the original diff and replays the sequence.
5. **Feature grid (#features)** — Eyebrow 'Why teams switch'; heading 'Built for the loop you already run.'; intro: 'Review on save, on commit and in CI with the same rules and the same output. Made for teams that ship several times a day.' Six cells, each: Lucide icon 20px in Signal, title (Inter 16px weight 500), body (Muted 14.5px, 2–3 lines), footer stat (mono 12px Faint, top 1px Line divider). (1) Zap — 'Reviews only the diff' — 'Reads the changed hunks plus the call sites they touch, so a 2,000-line pull request takes seconds instead of minutes.' — '1.8s median'. (2) HardDrive — 'Runs on your machine' — 'No code leaves your laptop or CI runner. Works on a plane, in air-gapped networks and behind strict proxies.' — '0 bytes uploaded'. (3) Wand2 — 'Fixes you can apply' — 'Most findings ship a patch. Preview it inline, apply it with one key, and [BRAND] re-reviews the result.' — '143 of 212 rules auto-fix'. (4) ShieldAlert — 'Security rules on by default' — 'Timing-safe comparisons, secrets in diffs, unsafe deserialization and SQL built from strings.' — '38 security rules'. (5) Keyboard — 'Keyboard-first TUI' — 'j and k to move, a to apply, i to ignore with a reason. ferrule review -i opens the interactive view.' — 'press ? on this page'. (6) FileCog — 'One config file' — 'Rules, severities and ignores live in .ferrule.toml next to your code and get reviewed like everything else.' — '.ferrule.toml'. Under the grid, ConfigSnippet: left text block 'Configure once, run everywhere.' (display 22px) + Muted line 'The same file drives the pre-commit hook, the CI step and the editor diagnostics.'; right a code panel titled '.ferrule.toml' with lines: '[review]' / 'base = "main"' / 'fail_on = "high"' / 'languages = ["typescript", "go", "python"]' / '' / '[rules]' / '"async-foreach-await" = "high"' / '"magic-number" = { level = "medium", ignore = ["tests/**"] }' / '"structured-logging" = "low"', with a copy button.
   Layout: Grid frame: 10px radius, 1px Line border, overflow hidden, display grid with gap 1px on a Line background so every cell shares hairline borders; cells are Panel with 24px padding. 3 columns at lg, 2 at md (≥768px), 1 below. ConfigSnippet sits 48px below: 5/7 split at lg, stacked below 1024px; code panel uses the same chrome as the diff viewer header.
   Motion: Cells reveal with a 0.06s stagger. On hover a cell's background shifts to Panel 2 and its icon nudges up 2px (0.2s).
6. **Benchmarks (#benchmarks)** — Eyebrow 'Benchmarks'; heading 'Fast enough to run on every save.'; a mono 11px badge next to the heading: 'Illustrative figures'. Segmented tabs: 'Review time' and 'Bugs caught'. Tab 'Review time' — caption 'Seconds to review a 1,240-line pull request · lower is better'; rows top to bottom (label, value): '[BRAND]' 1.8s; '[BRAND] --deep' 4.6s; 'Linter chain (5 tools)' 7.9s; 'Hosted review bot' 38.0s; 'Script calling a large model' 52.4s. Tab 'Bugs caught' — caption 'Seeded bugs found, out of 50 · higher is better'; rows: '[BRAND] --deep' 46; '[BRAND]' 41; 'Script calling a large model' 33; 'Hosted review bot' 29; 'Linter chain (5 tools)' 17. Right column, three stat tiles stacked: '21×' + 'faster than a hosted review bot'; '0.4s' + 'to re-review after applying a fix'; '92%' + 'of seeded bugs caught in deep mode'. Footnote under the chart (mono 11.5px, Faint, max 720px): 'Illustrative numbers for this page. Measured on an invented 1,240-line TypeScript and Go pull request with 50 seeded bugs, 10-core laptop, median of 10 runs. Other rows are generic tool categories, not specific products.'
   Layout: 8/4 split at lg (chart 8, tiles 4), stacked below 1024px with the tiles in a 3-column row on md and stacked on mobile. Each bar row: label column 220px (mono 13px; [BRAND] rows in Text with a Signal 6px square before them, others Muted) | track (height 28px, Panel background, 1px Line border, 6px radius) with the bar inside (Signal for [BRAND] rows, Line Strong for others) | value 64px right-aligned mono 14px (Text for [BRAND], Muted for others). Width = value / max value in the active tab. Under 640px the label sits above its track and the value moves inside the track's right end. Stat tiles: Panel, 1px Line border, 10px radius, 24px padding, number in display 40px Text with the unit in Signal, label Muted 14px.
   Motion: Bar race and count-up as in Design motion; the active tab pill slides with layoutId. Stat tile numbers count up once when visible.
7. **Integrations (#integrations)** — Eyebrow 'Integrations'; heading 'Fits where reviews already happen.' Two labeled chip rows. 'Works with' (label mono 12px Faint): Pre-commit hook, Pre-push hook, CI pipelines, Merge request comments, Editor diagnostics (LSP), SARIF output, JSON output, Monorepos, Self-hosted runners, Offline mode. 'Languages': TypeScript, Go, Python first (from [LANGUAGES], each with a Signal 6px dot meaning 'full support'), then JavaScript, Rust, Java, Kotlin, Ruby, SQL (no dot, a trailing mono 10px 'beta'). Plain text chips only, no logos. Under the rows a one-line mono command with copy button: '$ ferrule hooks install' and Muted text 'adds the pre-commit hook in one step'.
   Layout: Container, rows separated by 24px. Chips: inline-flex, mono 13px, 6px 12px padding, 1px Line border, 6px radius, Panel background, wrap with 8px gaps. Label column 140px on the left at md and above; on mobile the label sits above its chips.
   Motion: Chips fade in with a 0.02s stagger per row; hover turns the border Line Strong and the text Text.
8. **Changelog teaser (#changelog)** — Eyebrow 'Changelog'; heading 'Shipping every week.'; Muted line 'Four recent releases. Breaking changes are rare and always come with a migration command.' Entries (version tag mono 13px weight 700, type tag, one-line change): v2.4.0 [Latest, Signal tag] [feat] 'Suggested fixes for 41 more rules; ferrule fix now re-reviews automatically.'; v2.3.2 [fix] 'Go generics no longer trip the shadowed-variable rule.'; v2.3.0 [perf] 'Cold start down from 420 ms to 140 ms with a shared parse cache.'; v2.2.0 [feat] 'Interactive TUI: ferrule review -i with j/k navigation and inline apply.' Hidden until expanded: v2.1.1 [fix] 'SARIF output now includes rule help text.'; v2.1.0 [feat] 'Python support leaves beta with 64 rules.'; v2.0.0 [breaking] 'Config moved to .ferrule.toml; ferrule migrate converts the old file.'; v1.9.0 [feat] 'Hook installer: ferrule hooks install.' Button under the list: 'Show 4 older releases' with Lucide ChevronDown, toggling to 'Show fewer' with ChevronUp. No dates.
   Layout: Max-width 760px, left aligned in the container. Vertical timeline: a 1px Line rule at left 7px; each entry has a 9px dot on the rule (Signal for v2.4.0, Line Strong for others), then a row: version tag, type tag (feat Info, fix and perf Add, breaking Del; mono 11px, 1px border at 40% of the color, 6px radius), and the change text in Text 15px on the same line at md, wrapping under the tags on mobile. 20px between entries.
   Motion: Entries reveal with a 0.05s stagger; expanding as in Design motion. Shortcut 'l' scrolls here.
9. **Final install CTA (#install)** — Heading (display 44px / 32px mobile, centered): 'Run your first review in 30 seconds.' Muted subline: 'Free for teams that ship several times a day, from side projects to monorepos. No account, no upload.' The same InstallBox as the hero (shared tab state), centered. Below, three numbered steps as mono rows with copy buttons: '1  npm i -g ferrule' (follows the selected install tab), '2  ferrule review --base main', '3  ferrule hooks install'. Then a ghost button 'Keyboard shortcuts' with Kbd '?' that opens the overlay.
   Layout: Centered column, max-width 620px, inside a full-bleed band with a radial Signal glow (radial-gradient(600px circle at 50% 0%, rgba(198,244,50,0.08), transparent 70%)) and the faint grid. Step rows: Panel, 1px Line border, 6px radius, 12px 16px padding, step number in Signal, command in Text, copy icon button right; 8px between rows.
   Motion: Fades up on reveal. Copy behavior and toast as in Design motion.
10. **Footer** — Left: Wordmark and Muted line '[BRAND] — a local-first code review CLI for TypeScript, Go and Python.' Middle: two link columns — 'Product': Demo, Features, Benchmarks, Changelog (hash anchors); 'Install': npm, brew, npx (each copies that command and shows the toast; render as buttons styled like links). Bottom row (1px Line top border, mono 12px Faint): '© [BRAND] contributors · Apache-2.0 core' on the left; on the right the [CREDIT] link if it is kept.
   Layout: Container, 64px top / 40px bottom padding, 3-column grid at md (brand column wider: 2fr 1fr 1fr), stacked on mobile. Bottom row flex justify-between, wrapping on mobile.
   Motion: None besides link hover color.
11. **Keyboard shortcuts overlay and hint chip (global)** — Hint chip: fixed bottom-right, mono 12px, 'Press ? for shortcuts' with a Kbd '?', Panel background, 1px Line border, radius 999px; clicking opens the overlay. Overlay: modal titled 'Keyboard shortcuts' (display 20px) with a close button (Lucide X) and a two-column list of rows (description left in Text 14px, keys right as Kbd): '?' Open this panel; 'Esc' Close; 'c' Copy install command; 'd' Jump to the diff demo; 'f' Jump to features; 'b' Jump to benchmarks; 'l' Jump to changelog; 'i' Jump to install; 't' Back to top; 'r' Replay the terminal; 'a' Apply the open suggested fix (when the diff demo is in view). Footer line in mono 12px Faint: 'Shortcuts are ignored while typing in a field.' Kbd component: mono 12px, min-width 22px, height 22px, centered, Panel 2 background, 1px Line Strong border with a 2px bottom border, 6px radius.
   Layout: Overlay panel: width min(560px, 100vw - 32px), max-height 80vh with internal scroll, centered, Panel background, 1px Line border, 10px radius, 24px padding; rows separated by 1px Line dividers. Hint chip sits 20px from the bottom and right edges (16px on mobile) and hides while the overlay is open; on mobile it reads just 'Shortcuts' with the Kbd.
   Motion: Open/close animation as in Design motion. The global handler ignores keys with Ctrl/Meta/Alt and keys typed into input, textarea or contenteditable; 'c' copies the command of the selected install tab and toasts; section keys smooth-scroll (instant with reduced motion). The overlay is a role dialog with aria-modal true, aria-labelledby on its title, focus moves to the close button on open, Tab is trapped inside, and focus returns to the opener on close.

## Assets
- image: No photos, illustrations or bitmap images. Everything visual is drawn in code inside this project: the wordmark glyph (inline SVG described under Design imagery), the terminal and diff viewer chrome, severity dots, bar chart, background grid (CSS gradients) and noise overlay (inline SVG feTurbulence data URI). Note in ASSETS.md that these are original to the project.
- image: public/favicon.svg: a 32x32 SVG with a rounded square (rx 7) filled #C6F432 and two #0A0B0D horizontal bars (x 7, y 11, width 14, height 3 and x 11, y 18, width 14, height 3, both rx 1.5) — the same mark as the wordmark glyph. Written by hand, no generator.
- icon: lucide-react (ISC), installed from npm and tree-shaken: Copy, Check, Download, Keyboard, ArrowRight, ArrowDown, Pause, Play, RotateCcw, FileCode2, CheckCircle2, Zap, HardDrive, Wand2, ShieldAlert, FileCog, ChevronDown, ChevronUp, X. Size 16–20px, strokeWidth 1.75. No octicon-style or code-hosting glyphs, no brand icons.
- font: Self-hosted through Fontsource npm packages, imported in src/fonts.ts so Vite bundles the woff2 files into dist/: @fontsource-variable/space-grotesk (Space Grotesk, OFL-1.1, Florian Karsten), @fontsource-variable/inter (Inter, OFL-1.1, Rasmus Andersson), @fontsource-variable/jetbrains-mono (JetBrains Mono, OFL-1.1, JetBrains). List all three in ASSETS.md with package name, upstream source and license.

## Don'ts
- No backend of any kind: no server code, API routes, databases, auth, analytics, forms that submit anywhere or third-party APIs. Copy-to-clipboard and the shortcut overlay are the only interactions that touch the browser outside the page.
- Do not load fonts from fonts.googleapis.com, fonts.gstatic.com, Adobe Fonts or any CDN. Self-host through the three Fontsource packages only.
- No CDN <script>, <link> or import maps. Every script, style, font and icon is in the project and bundled into dist/.
- No source maps in the production build (build.sourcemap false), and src/ is not copied into dist/.
- Relative asset paths (Vite base './'). Internal links are hash anchors on index.html (#demo, #features, #benchmarks, #integrations, #changelog, #install, #top) or ./index.html, never a bare directory or a leading slash. No link points to a page that does not exist.
- Do not change the stack (Vite 5 + React 18 + TypeScript + Tailwind CSS 3.4 + Motion + lucide-react + Fontsource) unless the user asks. No router, no UI kit, no syntax-highlighting library, no chart library, no 3D.
- No names, logos or wordmarks of real code-review, linting, testing or AI coding tools. The product is the invented [BRAND]; its only mark is the code-drawn glyph and typeset name.
- No real benchmark numbers and no real competitor names in the bar race. Rows are generic categories ('Hosted review bot', 'Linter chain (5 tools)', 'Script calling a large model'), every figure is invented, and the chart keeps its 'Illustrative figures' badge and methodology footnote.
- No real company or open-source project logos in integrations or anywhere else; integrations are plain text chips with generic names, and languages are plain words.
- Do not copy the diff view styling, colors, layout chrome or octicon-style glyphs of real code-hosting sites. Draw the diff viewer from scratch as specified and use Lucide icons only.
- No real repository names, usernames, people or real code in terminal, diff, config or changelog samples. Use the invented ledgerline repository and the code given here.
- No commercial or custom fonts: only Space Grotesk, Inter and JetBrains Mono (OFL), self-hosted.
- Only dependencies under MIT, ISC, BSD, Apache-2.0, 0BSD, CC0 or Unlicense (OFL for fonts). No Aceternity UI, Tailwind Plus / Tailwind UI or purchased template code; write every effect yourself.
- No photos, stock images, placeholder-image services, Unsplash, Pexels or Pixabay. All visuals are drawn in code.
- One accent only: Signal lime. Add, Del, Warn and Info are semantic colors for diffs, severities and changelog tags only, never for buttons or headings. No purple gradients, no glassmorphism cards, no neon glows beyond the two subtle ones specified (terminal shadow and final CTA radial).
- No mention of VibeFather, its pricing, members or numbers anywhere in the site except the optional [CREDIT] footer link.
- Respect prefers-reduced-motion exactly as described under Design motion: typing, spinner, comment sequence and bar race jump to their end states. The terminal loop pauses when off screen or when the tab is hidden.
- Accessibility: every interactive element is keyboard reachable with a visible 2px Signal focus ring (outline-offset 2px); the overlay traps focus and closes on Esc; tabs use role tablist/tab with aria-selected; the terminal body has aria-live off and an sr-only summary of session 1; copy buttons have aria-labels; the toast uses role status.
- Must render at 1440×900 and 390×844 with zero console errors and no horizontal page scroll (only the diff code area and terminal lines may scroll inside their own boxes). Clipboard calls are wrapped in try/catch with the textarea fallback.
- Keep dist/ under 20 MB (target under 2 MB).
- No lorem ipsum, filler or hype words. No meta descriptions, Open Graph tags, JSON-LD or sitemap: only the <title> and favicon.

---
— Prompt by VibeFather · https://vibefather.ai/t/dark-developer-tool-launch-page · CC BY-NC 4.0 (non-commercial; commercial use needs a VibeFather Pro license) · Request removal: https://vibefather.ai/takedown

Free for personal projects under CC BY-NC 4.0. Commercial use comes with Pro.

DESIGN.md

The design system on its own — colors, type, spacing and motion. Apply this look to a project you already have.

---
name: "Dark Developer Tool Launch Page"
colors:
  ink: "#0A0B0D"
  panel: "#111317"
  panel_2: "#171A1F"
  line: "#22262D"
  line_strong: "#323842"
  text: "#E7E9EC"
  muted: "#8C939D"
  faint: "#5B626C"
  signal: "#C6F432"
  signal_ink: "#0A0B0D"
  add: "#3DDC97"
  add_bg: "rgba(61,220,151,0.09)"
  del: "#FF6B6B"
  del_bg: "rgba(255,107,107,0.09)"
  warn: "#F5B841"
  info: "#6CB4FF"
typography:
  display_hero_headline_56px_desktop_38px_mobile_weight_600_tracking_0_03em_line_height_1_02_section_headings_36px_28px_weight_600_tracking_0_02em_stat_numbers: { family: "Space Grotesk", weights: [500, 600, 700] }
  text_body_16px_1_6_weight_400_card_titles_16px_weight_500_buttons_14px_weight_500: { family: "Inter", weights: [400, 500, 600] }
  mono_terminal_13_5px_1_7_diff_13px_1_65_install_commands_15px_eyebrows_and_labels_12px_uppercase_tracking_0_08em_all_numbers_kbd_keys_chips_version_tags: { family: "JetBrains Mono", weights: [400, 500, 700] }
spacing: "Container max-width 1200px with 24px side padding (16px under 640px). Sections are separated by 1px Line borders full-bleed, with 112px vertical padding on desktop and 72px on mobile. Grids use a 1px gap over a Line-colored background so cells share hairline borders. Inner card padding 24px. Base unit 4px; dense rhythm, no huge empty bands."
radius: "6px on buttons, chips, kbd keys, inputs and tags; 10px on the terminal window, diff viewer, install box, overlay panel and feature grid outer frame; 999px only on severity dots and the hint chip."
---

# Dark Developer Tool Launch Page — Design System

Apply this design system to an existing project. It describes the look and feel only; for the full site, use prompt.md.

## Colors
- **Ink** `#0A0B0D` — Page background, terminal body
- **Panel** `#111317` — Cards, diff viewer body, install box, overlay panel
- **Panel 2** `#171A1F` — Terminal and diff title bars, hunk header rows, hovered rows, kbd keys
- **Line** `#22262D` — All 1px hairline borders and dividers, inactive benchmark bars track
- **Line Strong** `#323842` — Hovered borders, inactive benchmark bars, kbd bottom border
- **Text** `#E7E9EC` — Headlines and body text
- **Muted** `#8C939D` — Secondary copy, line numbers, terminal prompt path, labels
- **Faint** `#5B626C` — Footnotes, disabled states, diff context gutter
- **Signal** `#C6F432` — The one accent: primary buttons, our benchmark bars, active tab underline, focus rings, caret, git branch in the prompt, 'Latest' tag, wordmark glyph
- **Signal Ink** `#0A0B0D` — Text on Signal buttons and tags
- **Add** `#3DDC97` — Added-line +/- gutter sign and text tint, success checkmarks, 'perf' and 'fix' changelog tags
- **Add BG** `rgba(61,220,151,0.09)` — Added-line row background
- **Del** `#FF6B6B` — Removed-line sign, 'high' severity dot and tag, 'breaking' tag
- **Del BG** `rgba(255,107,107,0.09)` — Removed-line row background
- **Warn** `#F5B841` — 'medium' severity dot and tag
- **Info** `#6CB4FF` — 'low' severity dot and tag, 'feat' changelog tag, code keywords

## Typography
- **Display: hero headline (56px desktop / 38px mobile, weight 600, tracking -0.03em, line-height 1.02), section headings (36px / 28px, weight 600, tracking -0.02em), stat numbers** — Space Grotesk (OFL), weights 500/600/700. Self-host the font files.
- **Text: body 16px/1.6 weight 400, card titles 16px weight 500, buttons 14px weight 500** — Inter (OFL), weights 400/500/600. Self-host the font files.
- **Mono: terminal (13.5px/1.7), diff (13px/1.65), install commands (15px), eyebrows and labels (12px uppercase, tracking 0.08em), all numbers, kbd keys, chips, version tags** — JetBrains Mono (OFL), weights 400/500/700. Self-host the font files.

## Spacing & shape
- Spacing: Container max-width 1200px with 24px side padding (16px under 640px). Sections are separated by 1px Line borders full-bleed, with 112px vertical padding on desktop and 72px on mobile. Grids use a 1px gap over a Line-colored background so cells share hairline borders. Inner card padding 24px. Base unit 4px; dense rhythm, no huge empty bands.
- Radius: 6px on buttons, chips, kbd keys, inputs and tags; 10px on the terminal window, diff viewer, install box, overlay panel and feature grid outer frame; 999px only on severity dots and the hint chip.

## Motion
- Section reveal: every section heading and block fades up (opacity 0 to 1, y 16px to 0, 0.5s, ease [0.22, 1, 0.36, 1]) once when 20% visible; children stagger by 0.06s.
- Hero terminal: commands type character by character at 32ms per char with a blinking block caret (Signal, 1s steps); output lines appear one by one with 110ms between lines; the spinner cycles the braille frames ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏ every 80ms for 900ms before being replaced by its result line. After the last line of session 2 it waits 2.6s, fades the body out over 0.3s and restarts session 1. It starts only when the terminal is in view and pauses when off screen or when the tab is hidden.
- Diff viewer: when the viewer is 35% in view, the three comments open in order, 1.1s apart. For each, the anchored line gets a 1.2s pulse-line highlight, then the comment card expands from height 0 to auto with opacity 0 to 1 (0.45s); the matching item in the Findings panel ticks from a hollow dot to a filled severity dot.
- Benchmark race: when the chart is 40% in view, bars grow from width 0 to their value (1.1s, ease [0.22, 1, 0.36, 1], stagger 0.12s top to bottom) and the numbers count up in sync using Motion's animate() on a motion value, formatted to one decimal for seconds and integers for counts. Switching tabs replays the race from 0.
- Micro-interactions: copy buttons swap the Lucide Copy icon for Check with a 0.15s scale pop and show a toast 'Copied: <command>' bottom-center for 1.8s; buttons lift 1px and brighten on hover; chips and cards change border to Line Strong on hover; the active tab underline slides between tabs with a shared layoutId.
- Shortcut overlay: backdrop fades to rgba(10,11,13,0.72) with backdrop-blur 6px in 0.2s; the panel scales from 0.97 to 1 and fades in over 0.2s; Esc or a backdrop click reverses it.
- Changelog expand: older entries animate height 0 to auto and fade in over 0.35s.
- prefers-reduced-motion: no typing, spinner or loop (the terminal renders session 1 complete and static with a Replay button that swaps to session 2), diff comments are all open from the start, bars and numbers render at their final values, reveals are instant, smooth scrolling is off. Overlay and toast still appear but without scale or movement.

## Imagery
No photos and no illustrations. The visual interest comes from code-drawn UI: the terminal window, the diff viewer, the bar chart, hairline grids, a very faint 48px background grid under the hero masked with a radial fade, and a 3.5% SVG noise overlay across the page. The wordmark glyph is an inline SVG: a 20x20 rounded square (radius 5) in Signal with two Ink horizontal strokes of different length, like two diff lines, the lower one offset right by 4px. Icons are Lucide at 18–20px with stroke-width 1.75.

## Tone
Terse, technical and confident, like a well-written README. Short sentences, concrete numbers, real command names, no hype words (no 'revolutionary', 'blazing', 'supercharge', 'magic'). Monospace for anything a developer would type or read in a terminal.

---
— Prompt by VibeFather · https://vibefather.ai/t/dark-developer-tool-launch-page · CC BY-NC 4.0 (non-commercial; commercial use needs a VibeFather Pro license) · Request removal: https://vibefather.ai/takedown