CW Logo
Back to posts

Moving This Blog from Next.js to Astro

essay

This blog now builds with Astro. If you came here to read an article, there should not be much to notice: the narrow layout, dark mode, code highlighting, and article URLs are still here.

That was the point. I wanted to simplify the setup without giving the site another redesign.

Next.js had been working fine. Most pages were already statically generated, so this was not a rescue from slow server rendering. But after removing things like the gallery and separate tag pages, the blog had settled into a fairly small job: read local files, render articles, and keep a few interactive controls around. Astro felt like a closer fit for what remained.

The migration moved routes and layouts into src/pages/ and src/layouts/. Astro generates the site into dist/, and Vercel still hosts it. Node.js and pnpm stayed too. I did not want to change the framework, package manager, and deployment platform all at once.

I also kept React. Existing page components can render to HTML through Astro's React integration without becoming interactive client components. The theme controls and homepage previews still need browser behavior, so those are explicitly hydrated as islands. There was no reason to rewrite every working component just to make all the filenames end in .astro.

Code blocks went the other way. Their markup now comes from an Astro component, while a small browser script handles copying and the reading progress bar. The highlighted article does not need to become a hydrated React tree for a copy button to work. The site still has JavaScript, including client-side navigation; getting to zero was never the goal.

The articles needed a little care. The old renderer treated both .md and .mdx files as MDX, and some Markdown files contained custom components. I renamed the 82 .md files to .mdx, keeping their names, dates, and contents unchanged. The existing content index stayed in place as well, including date parsing, sorting, and previous/next links. Switching renderers did not seem like a good reason to rewrite those rules.

RSS and Atom still contain summaries. Share images are now generated during the build, with a Vercel rewrite preserving their old URLs. These are easy details to overlook when the homepage already looks right.

Once Astro was in place, a separate cleanup removed the old app/ directory, Next configuration, next-mdx-remote, and the unused framework-specific components and tooling. That was the satisfying part: opening the repository and no longer seeing two implementations of the same site.

I do not have a controlled before-and-after benchmark to attach to this. The weight loss here is mostly about removing a framework and its leftover plumbing, not claiming a particular speed increase. There are still dependencies to maintain and interactions worth keeping.

For now, the blog does the same small job with a setup I would rather work on. That is enough reason for this move.