Toggle Menu Icon

Switching to Astro

A year ago I wrote about switching this site to Nextra. Within the year, Nextra upgraded twice to v3 and then v4 and each upgrade was more painful, to the point that I couldn’t still have the same setup I wanted. It moved away from the great developer experience I initially enjoyed with Nextra.

My ideal setup: I want a folder of markdown files that contain my content and the framework handles the rest. So when I want a new post, create a new markdown file in the folder representing the category, for example this post is in a code folder.

pages/
    code/
        blog-switch-astro.mdx
    dataviz/
    life/
    ...
    about.md
    index.md
    now.md

The latest Nextra upgrade really wanted me to switch to the new Next.js app router that requires various hoops to navigate. A catch-all is tough to implement since I have folders for categories and top level, also does anyone think [...slug] as a directory name looks good? Dislike.

An alternate solution is to create a bunch of article-name/page.mdx directories and files for each. This is not an improved developer experience, why do I want a file called page.mdx for every article. It adds a folder and file just extra noise. I find a single file name article-name.mdx makes so much more sense.

Over the course of the last couple months, I attempted upgrading Nextra a few times and tried out various frameworks. Docusaurus is pretty nice but has equal headaches for top-level folders. It really wants all your pages to live in /docs/. Gatsby looks dead in the water.

I even rolled my own framework using Vite and mdx, but this ended up being more fragile and my initial implementation loaded every mdx file on every page. Not ideal.

I tried out plain Next.js (without Nextra) and it has many of the same worts as Nextra, which makes sense, Nextra inherited all the problems of the latest Next.js and no longer smooths them out for a simple site as it did before.

I finally tried out Astro and took me awhile to come onboard, initial examples seemed ok, though it looked overly complicated with its own .astro file format which is weird mix of frontmatter and React.

Also, the example pages showed importing the <Layout/> component in each mdx file which is not ideal, I want the content to just be the content.

Finally, I stumbled upon an example site that set the layout in the frontmatter of each file:

---
layout: ../layouts/BaseLayout.astro
---

This uses the component defined in BaseLayout and injects the rendered markdown into the <slot/> component in that layout. Yes!

This is what I want, directories of mdx files which define the site structure and pages, and a React component wraps it. When I want to create a new post, all I need to do is focus on the markdown.

If I was starting from scratch, some of the other frameworks may have worked fine. My site has been around 25 years or so, so I have a file structure and content that needs to be worked around.

Bonus: So I had to modify every content file (about 240) and add the layout line, a one-time chore, obviously a job for a script. A perfect time for AI using the Cursor editor. I asked it to write a script and go through all files and add the line. A nice touch it even wrote a check to see if the line already exists, which it did on 1 or 2 test files. AI is perfect for these tedious tasks, it’s a simple script I’ve written a hundred of times looping through files, parsing and inserting text, it’s not hard but annoying enough.

Astro Starter

I created a minimal Astro site with this structure, see https://github.com/mkaz/astro-starter to play around with it.

The starter site shows how I use the Astro Content Collections. For that site I only define one, for my site I define multiple a combine them together.