Pakkit.net

Colophon

How this corner of the internet is built.

This page is the build log for pakkit.net — not a badge wall. It explains the decisions behind a static, typed, content-driven site, and why each one earns its keep.

The short version: ship HTML, keep the moving parts few, let content and types do the heavy lifting, and treat AI as an accelerator that still answers to human review.

// COLOPHON static-by-default pipeline content + data components .astro astro build type-checked dist/ static html CDN edge cloudflare metadata + OG sitemap.xml rss.xml > no server Typed, content-driven, static by default

Foundation

Why a static site

The site is built with Astro and ships as fully static output — there is no server adapter, so every route prerenders to plain HTML in dist/.

Static-by-default means almost no client-side JavaScript: the only scripts are a tiny inline progressive-enhancement snippet on the contact page and a deferred analytics loader. The pages are durable, hosting is simple (static files behind a CDN), and there are far fewer runtime pieces to break or patch.

Tools with reasons

The stack, and why each piece is here

Nothing in the stack is here for fashion. Each tool removes a category of mistake or busywork.

Astro 6
A component model that compiles to static HTML, with no framework runtime shipped to the browser unless a slice explicitly asks for one.
TypeScript (strict)
Extends astro/tsconfigs/strict. If it compiles clean, a whole class of bugs never reaches a branch.
Tailwind CSS v4
Wired through the @tailwindcss/vite plugin. Design tokens live in one @theme block and double as utilities, so styling stays consistent without a sprawling config.
MDX
Long-form project and blog content is authored in MDX, so prose and components share one file format.
Astro Content Collections
The Content Layer API with a glob loader and a Zod schema validates every project/blog entry's frontmatter at build time.
Docker dev workflow
All Node, Astro, and build commands run inside a hardened, low-privilege container — the host stays clean and reproducible.

How it fits together

Content architecture

The codebase separates concerns deliberately. Page routes in src/pages stay thin and compose components. Typed data modules in src/data hold presentation-agnostic copy. Project and blog entries live as MDX in content collections with a validated schema.

Reusable primitives and route-grouped sections live in src/components, and a single shared layout plus its metadata helpers (BaseLayout, siteMetadata, the SEO resolver) wrap every page so titles, canonical URLs, and social cards are handled in one place.

Build pipeline, top to bottom
  1. src/pages/* File-based routes — thin pages that compose components.
  2. src/layouts + src/lib One BaseLayout plus shared metadata and SEO helpers.
  3. src/components/* Reusable primitives and route-grouped sections.
  4. src/data/* + src/content/* Typed data modules and schema-validated MDX.
  5. astro build → dist/ Prerendered static HTML and hashed assets. No server.

Personality, on a leash

Visual language

The look is dark-first — the document opts into a dark color scheme, and the palette is a small set of tokens: electric cyan as the primary accent, purple as secondary, and warm amber for cozier moments.

Surfaces use a single frosted glass-card utility; technical details fall back to a JetBrains Mono monospace face. A faint grid backdrop and a fox-flavored, terminal-and-network personality give it character, but it's deliberately restrained: the tokens are few, and they're not a formal design system — just a consistent set of decisions.

Usable and quick

Accessibility and performance

The building blocks are semantic HTML with real landmarks, a skip-to-content link, and a visible keyboard focus ring on anything that doesn't define its own. Layouts are responsive from small screens up.

Because pages render statically and fonts are self-hosted at build time, there's little to download and nothing to hydrate. The little JavaScript that exists is used carefully — animations and smooth scrolling back off when a visitor prefers reduced motion. These are practices, not a certification or a claim of universal compliance.

Posture, not theater

Security and privacy

Static output keeps the runtime attack surface small — there's no application server answering requests. No secrets belong in the build: only public PUBLIC_* values are ever embedded in the HTML.

Contact delivery uses the existing static-provider strategy — the form POSTs to a configured third-party endpoint with a honeypot field, so there's no backend to defend. Recommended security headers ship with the site, and a Content-Security-Policy is documented as a starting point rather than enforced blindly. Analytics is opt-in: it loads only in production when a measurement ID is set, and it's deferred so it never blocks first paint.

Acceleration, not ownership

AI-assisted development

AI is part of how this site gets built, but it doesn't get to own the architecture. Work lands in small, scoped slices. Guardrails (the agent and execution docs) keep changes inside the lines, and every slice is validated with check and build before it merges.

Humans review the pull requests, documentation steers the agents, and accountability stays with the person — AI accelerates the work, it doesn't sign off on it.

Said no on purpose

Deliberate non-features

Some of the best decisions are the things that aren't here.

  • No server runtime — static output, no adapter.
  • No unnecessary client framework — Astro ships HTML, not a default island.
  • No giant animation layer — motion is subtle and respects reduced-motion.
  • No remote live-data dependency for ordinary pages — content is built in.
  • No design-by-plugin — the visual language is a small, hand-kept token set.

Keep reading

Related pages

The neighboring rooms — where the same engineering taste shows up in practice.