AZ
All writing
2 min read

When a static site is the correct amount of engineering

nextjstailwindstaticmarketing
Part of the projectFivestickA single-page marketing site for an AI-automation consultancy — static content, no backend, one interactive island, full SEO via static Next metadata (a standard server build, not a static export).View project

Fivestick is the landing site for an AI automation consultancy, and its primary job is to send a visitor to a WhatsApp chat or a free 30-minute audit call. Building it as static content — not as an application — is the whole design decision.

Match the tool to the job

A marketing page has a narrow, honest mandate: load fast, read clearly, convert. None of that needs a database, a session, or a server round-trip. Fivestick has no backend at all — no api routes, no use server actions, no external fetch in src/. It's Next.js with React Server Components rendering the page at build, and exactly one client island: a dependency-free SVG animation (workflow-animation.tsx, an <animateMotion> + CSS-keyframe piece, no animation library). There's no form handler and no lead store because conversion is offloaded to a third party (a wa.me link), which removes an entire category of runtime failure by simply not having a runtime to fail.

Static content, stated precisely

One honest nuance: this is static content, not a hard static export. The README calls it "statically rendered," and it is — but next.config.ts carries no output: 'export' (it's the empty-defaults file), so the build is a standard Next.js server bundle that assumes a Node runtime (or Vercel), not an exported /out directory. It's a fair "right amount of engineering" story either way; it's just not a file-server-only site, and saying so keeps the claim accurate.

Styling, and the shadcn that wasn't

Styling is Tailwind v4, CSS-first — no tailwind.config.* at all; the theme lives in globals.css behind @import "tailwindcss" and an @theme inline block of brand tokens. shadcn was scaffolded (there's a components.json, base UI via @base-ui/react rather than Radix), but no src/components/ui directory was ever generated and cn/Radix are never imported — the page uses hand-written Tailwind components. Full SEO and crawler discoverability is achieved purely with static Next metadata conventions (sitemap.ts, robots.ts, OpenGraph/Twitter image routes, a manifest) plus ProfessionalService JSON-LD.

Restraint as a skill

It's easy to reach for the same heavy app shell you use everywhere. Recognising that this problem is a document, not an application, is a design decision worth naming. The right amount of engineering is sometimes noticeably less than you're capable of — and knowing where that line sits is its own kind of experience.

Back to the projectFivestickSee the full case study and related write-ups.View project