July 1, 2026 · 2 min read
Rebuilding this site: Next.js, Three.js, and a bucket
This site used to run on Gatsby. It served me fine for a few years, but the ecosystem drifted, the dependencies aged, and every small change came with a side quest of build errors. So I did the thing every developer threatens to do and rarely does: deleted everything and started over.
The framework decision
The real choice was Next.js vs. Astro. For a static blog and portfolio, Astro is arguably the more natural fit — it ships less JavaScript by default and its content story is great.
I picked Next.js anyway, for one reason: the exit ramp. This site will eventually grow features that need a server — anything touching an LLM API, for example, since an API key can't live in the browser. With Next, adding a backend later is a deployment change, not a framework rewrite. The same app that statically exports today can grow server routes tomorrow.
Today it's a pure static export:
const nextConfig: NextConfig = {
output: "export",
trailingSlash: true,
images: { unoptimized: true },
};trailingSlash matters more than it looks — S3 has no routing layer, so
/about/ needs to resolve to a real about/index.html object in the bucket.
The architecture
No Vercel. Everything lives in my own AWS account, where I can inspect every piece with the CLI:
- Route 53 owns the domain and points at CloudFront
- CloudFront terminates HTTPS and caches at the edge
- S3 serves the exported files as a static website
The deploy is two commands:
next build
aws s3 sync out/ s3://kyleskudlarek.com --delete
aws cloudfront create-invalidation --distribution-id $DIST_ID --paths '/*'That last line is the one you should never skip. CloudFront caches aggressively — deploy without an invalidation and you'll stare at the old site wondering why nothing changed, questioning increasingly fundamental things about your build. Ask me how I know.
What's next
The plan is to grow this place slowly: more writing, a playground section for self-contained browser experiments, and pushing the WebGL terrain on the home page somewhere more ambitious. Each piece ships when it's actually good, not when the roadmap says so.
That's the whole point of a zen garden — you tend it. 🌱