North & Form

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.

src/data/page.ts
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:

terminal
npm run build && npm run preview npx lighthouse http://localhost:4321 --view

03

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.

src/data/page.ts
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:

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
src/styles/global.css
.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
theme.config.ts
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
theme.config.ts
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
any page
<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
terminal
npm run fresh

Resets 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
update-safe
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:

terminal
git fetch upstream && git merge upstream/main && npm install