Back to blog

Re-writing my blog in Next.js 15

December 31, 2024
BlogTechnical

This winter break, I re-wrote my personal website. It went great. Here’s the behind-the-scenes story.

Motivation

In the summer of 2020 (—in the midst of the COVID-19 pandemic, locked in my parent’s basement), I, as a bright-eyed computer science freshman, decided to take on a nobel endeavor: re-writing my personal website.

My previous instances (v1, v2, and v3) had used Jekyll (i.e., a lot of mangled HTML and CSS, managed with Ruby). I had recently learned React, and was overall a much more component developer. It was time for an upgrade!

I shopped around for frameworks. I knew I wanted something with built-in static site generation, since I was probably going to blog. I remember evaluating things like Hugo (Go), Pelican (Python), and Next.js, but ultimately settled on a lil’ ol’ framework called Gatsby.

That was not a very good idea.

I subsequently endured 4 years of errors like…

Invalid clockspec? Are you kidding me?!
Invalid clockspec? Are you kidding me?!

…or…

AHHHHHHHHHHHHHHHHHHHHHHHHHHHHH.
AHHHHHHHHHHHHHHHHHHHHHHHHHHHHH.

Not fun. I had to perform maintaince constantly, and it felt like there was always something to upgrade. It wasn’t fun for me to work on my site anymore; I dreaded adding new features. No good! After Netlify acquired Gatsby, I knew it was completely doomed.

This Christmas break, I decided it was time for a change. Here’s the old site in case you’re curious. I have been writing a lot more in 2024, and need a platform to support that. I briefly evaluated 2 options.

  1. Go full ā€œNat Friedman,ā€ and only use HTML and CSS—keep it plain
  2. Go full ā€˜out’—opt for the latest-and-greatest in web tech, and add a bunch of fancy (useless) features

Option one solves the exact pain point from my most recent website… but option two is more fun! (Don’t worry, I’m aware I’m probably going to have to deal with an onslaught of Next and React upgrades).

After all, I’m (at least these days, primarily) a web developer—ultimately, I love writing websites. It’s a chance to learn something new and explore the ecosystem. Also—Next.js has a fairly rich community, and Vercel seems like a wonderful hosting platform.

~62 commits later, I’m more or less done. Here’s how I got there.

Re-write

As mentioned, I went with option two. That translated to an app with React 19, Next.js 15, Tailwind, and shadcn/ui, deployed on Vercel. To make things more interesting, I’m using Notion as a kind-of CMS, since I like writing on here, and I like Notion sites, but still want my corner of the Internet to feature my blog, portfolio, and travel writing.

Ultimately though, I wasn’t super interested in doing all the basic boilerplate by hand. Thankfully, it’s not 2020 anymore—I have access to Claude Sonnet. For a mere price of $20 a month, I have (what feels like) ā€˜2020 Michael’ in my back pocket. Let’s put him to use!

Adventures with Claude

First things first: I made a project.

My Claude project.
My Claude project.

OpenAI recently shipped this feature too, but I find Anthropic a far more deserving company of my hard-earned dollars, o3 or otherwise. Let’s hope they catch up in 2025.

Anyhoo, here was the project prompt.

I'm in the midst of re-writing my personal website. The old version is written in Gatsby, under the folder \\\\\\\\wsl.localhost\\\\Ubuntu\\\\home\\\\mdema\\\\code\\\\michaeldemar.co (note the escaped slashes). The new code is written in Next.js 15, available in \\\\\\\\wsl.localhost\\\\Ubuntu\\\\home\\\\mdema\\\\code\\\\michaeldemar.co-v5. It also now uses TypeScript, shadcn, and Tailwind. It follows best practices. Currently, the basic website is in place, and we have a blog and design portfolio made. The new website is mostly a superset of the old one, bringing over the existing features but also adding a bunch of new, cool functionality. You will help me finish the website re-write, by leveraging code and making sure I don't miss details from the old site.

and the snippet in project knowledge…

The old Gatsby.js code is at \\\\\\\\wsl.localhost\\\\Ubuntu\\\\home\\\\mdema\\\\code\\\\michaeldemar.co. The new Next.js 15 code is at \\\\wsl.localhost\\Ubuntu\\home\\mdema\\code\\michaeldemar.co-v5. You have access to the filesystem (note the paths). You have access to your own memory bank; use it as you'd like. You have access the Brave Search, in case you need to look anything up. The new site uses Next.js 15, TypeScript, Tailwind, shadcn. We’re in the middle of the re-write; some progress has been made

The astute reader may notice something weird. I’m giving Claude file paths… but no files? And access to Brave Search? A memory bank?! What is this hersey?

This hersey is Claude’s ā€œModel Context Protocol.ā€ I’m still surprised when I meet other developers that haven’t heard of it. The short is that it gives LLMs a standard protocol to interface with MCP servers, which can take actions on their behalf. For example, if you have an MCP server with access to filesystem operations (e.g., listing files in a directory, reading files, writing files), an MCP client (such as Claude Desktop) can take those operations with your permissions.

Setting up my MCP server was a bit tricky. I use Ubuntu on Windows (i.e., WSL); to get Claude Desktop to connect, I had to run the MCP servers on Windows, and then provide those wonky filepaths you see in my prompt. After a bit of hair pulling to get it all working, the end product is fantastic.

Once it was setup, I used Claude as a fully-fledged junior engineer. Below are some highlighted conversations. It was able to walk me through the entire re-write, step-by-step. It also helped me write a fully-functional ā€˜build step’ for using Notion as a CMS. I also had it develop some fun features, like a sitemap view or a list of other sub-domains under michaeldemar.co.

(I want to put them in toggles here, but for now I’ll just link the files. Go to take a look at the filesystem MCP server if you’re curious)

Conversation #1: Setup

Conversation #2: Notion CMS

Conversation #3: Polish

All in all, I don’t think I would’ve been able to get this project done at nearly the same quality or efficiency without Claude or MCP. Shoutout to the Anthropic team!

shadcn is magic

I’d seen a lot of shadcn in the wild, but never really bothered to look it up. Candidly, I assumed it was just another CSS framework. I could not have been more wrong!

This is the component library. In mere seconds I’m able to able to sketch out features that would’ve taken my days or weeks prior, thanks to npx shadcn@latest add (component). It works beautifully with my chosen color scheme (in src/app/globals.css) right out of the box. It feels like magic!

It was so easy and fun to use this tool, I ended up shipping a few nonsense features like search (hit CTRL + \ on my site) and an image gallery for each of my design portfolio entries. (For example, take a look at this page.) And I’m not done either.

Vercel is (also) magic

Vercel is a wonderful hosting platform. For a long-time, I had been a bit of a Vercel doubter—one of the ā€œit’s just an AWS wrapperā€ folks. To be honest, that’s still probably true, but with a generous hobby tier and a bunch of very handy bells and whistles, I don’t care. What really sold me was Guillermo Rauch (Vercel’s CEO) stating…

@rauchg speaks!
@rauchg speaks!

If it’s good enough for him, it’s good enough for me. And that makes me inclined to believe I’m not going to get Heroku’d off of Vercel. (Never forgive, never forget.)

I’m trying out the analytics and speed insights available on the platform. Will follow-up with thoughts on those in due time.

The new michaeldemar.co

So, go check it out! Here are some of my favorite pages and features from the new site.

The hero of my website.
The hero of my website.
The below-the-fold content of the homepage.
The below-the-fold content of the homepage.
The /blog page.
The /blog page.
The /subdomains page.
The /subdomains page.

Next (up)

So what’s Next for my website? A few things…

Smarter CMS

Right now, on a prebuild script, I’m pulling all of my Notion and Cloudflare data. This is a bit expensive.

For Notion, each database entry has an Edited property. If Edited is before the current date, I can skip that item.

For Cloudflare, I can save a lastFetched field to the JSON, and skip the query if we’ve fetched within, say, the last week. That’s probably sufficient.

Better MDX

The MDX logic (for rendering content pulled from Notion could improve). Some easy examples: render to-do list blocks properly, and show YouTube embed blocks.

Automated deployments

OK, of course Vercel has automated deployments when I push to main. What I mean is the ability to trigger new builds when a blog post is released.

Better search

My search is a bit lazy. I’m hard-coding in available pages, and it currently doesn’t support searching for page content. Lots to improve there.

Design re-think

The color scheme is okay, but I could definitely do gruvbox a bit more justice.

Closing

Thanks for reading! Hope you enjoy the new site.

Also while you’re here—consider subscribing to my Buttondown newsletter here.

Happy New Year!

Some fireworks :-)
Some fireworks :-)
Comments