Everything KoPitch ships with.
A tour of the theme — and exactly how to configure each piece. This page lives in your copy of the theme, so the docs are always where your code is.
01
The centered one-pager — quiet credibility
KoPitch is the business one-pager archetype: a single centered column (max-w-xl, ~36rem), hero → stats → offerings → FAQ → CTA. No grids to fight, no sidebar to fill — the structure does the selling.
Setup & config
The column lives in src/layouts/PageLayout.astro(max-w-xl). All one-pager copy lives in the safe zone:src/data/page.ts — a typed object you edit directly. Hero, stats, offerings, FAQ, and final CTA are all there.
hero: { kicker: 'North & Form — design partners…', headline: 'We help founders build products that earn trust.', subline: '…', cta: { label: 'Start a conversation', href: 'mailto:hello@…' }, secondary: { label: 'See how we work →', href: '/features' }, }02
Fast — measured, not promised
Every KoPitch release is audited with Lighthouse before it ships. These are the real numbers from v1.0.0; they ship with the theme so you can re-run them yourself.
Mobile
99
Performance
95
Accessibility
100
Best practices
100
SEO
Desktop
100
Performance
95
Accessibility
100
Best practices
100
SEO
mobile: FCP 1.2 s · LCP 1.8 s · TBT 0 ms · CLS 0.012 — Lighthouse 13.4.0, median of 3 runs, 2026-06-10
Setup & config
Why it's fast: Fraunces and Instrument Sans load withfont-display: optional so it never blocks the LCP element, and there's one small JS file for the GSAP count-up. Verify it yourself:
npm run build && npm run preview npx lighthouse http://localhost:4321 --view03
GSAP stat count-up — the only animation
When the stat row scrolls into view, each number counts from 0 to its value (~1 s, expo.out). Suffixes ('hr', '+') stay static. Runs once. Skipped entirely with prefers-reduced-motion — values in the HTML are always real, never blanked.
Setup & config
Stats are defined in src/data/page.ts. The count-up reads data-stat (numeric target) anddata-stat-suffix from the rendered elements.
stats: [ { value: '48', suffix: 'hr', label: 'typical first response' }, { value: '120', label: 'products launched' }, { value: '12', label: 'years in practice' }, ]Implementation: src/scripts/stat-countup.ts (IntersectionObserver + gsap.to on a proxy object). Remove the call insrc/scripts/motion.ts to disable it.
04
FAQ — native details, styled to match
Each FAQ item is a native HTML <details> element: accessible, no JS, keyboard-navigable. The → marker rotates 90° on open via CSS transition. Styled to match the offerings list hairlines.
Setup & config
Edit FAQ items in src/data/page.ts:
faq: [ { q: 'What kind of teams do you work with?', a: 'Seed to Series A — usually a technical founder…', }, ]The rotating marker and border styles live insrc/styles/global.css under.ko-faq.
05
CTA button — the only filled element
KoPitch uses exactly one filled-background element: the rounded-full button. Everything else is text and hairlines. On hover it shifts from ink to accent-1 (business blue). The secondary action is always a text link.
Setup & config
.ko-btn { border-radius: 9999px; background-color: var(--color-ink); transition: background-color 150ms ease; } .ko-btn:hover { background-color: var(--color-accent-1); }Change accent1 in theme.config.ts to retheme the hover color.
06
Fraunces speaks, Instrument Sans works
The voice is Fraunces — a warm display serif with a true italic for emphasis — over an Instrument Sans body. Both self-hosted at build time; display: optional keeps them off the LCP path.
Setup & config
heading: { provider: 'google', family: 'Fraunces', weights: [400, 600], styles: ['normal', 'italic'], display: 'optional' } body: { provider: 'google', family: 'Instrument Sans', weights: [400, 500], display: 'optional' }Switch to any other Google, Adobe, or local font by changing family. A system stack is { provider: "system", stack: "sans-serif" }— zero bytes.
07
Every setting in one file
Colors, fonts, firm name, meta tags, social links and navigation live in theme.config.ts — typed, validated, and impossible to typo silently.
Setup & config
logo: { type: 'text', value: 'North & Form' }, colors: { accent1: '#3056d3', /* business blue */ }, nav: { links: [{ label: 'Features', href: '/features' }] }Invalid values fail the build with a readable error pointing at the exact field.
Light, dark and system color schemes are built in: the grey ramp inverts automatically in dark mode, colors.dark overrides any accent, and the toggle in the nav cycles auto → light → dark (persisted, no flash on load). Set dark: false to ship light-only.
08
SEO without a plugin
Canonical URLs, Open Graph and Twitter cards, sitemap, robots.txt — fed by your config and per-page frontmatter. Privacy and Terms pages are pre-built at /privacy and /terms.
Setup & config
<PageLayout title="Page title" description="…" ogImage="/og-custom.png">Legal copy lives in src/content/pages/privacy.md and src/content/pages/terms.md — replace the placeholder text before going live.
09
Demo content — keep it or strip it
The theme arrives as North & Form's site so every section has something to show. One command makes it yours.
Setup & config
npm run freshResets src/data/page.ts to a neutral skeleton with generic labels and stubs legal pages. Structure, config and styles stay — the site builds immediately after.
10
Updates that respect your changes
Theme updates arrive as git pulls. Your config, content, styles and overrides live in safe zones updates never touch.
Setup & config
theme.config.ts src/styles/custom.css src/data/page.ts src/content/ src/components/overrides/ public/Don't edit src/_core/ — copy a component intosrc/components/overrides/ and change its import instead. Updating:
git fetch upstream && git merge upstream/main && npm install