Bye Bye Jekyll, Hello Astro

I’ve been running tecnobrat.com for a long time, and the site has worn a lot of hats: Octopress, Jekyll, a theme, custom plugins, and enough “just make it work” glue to qualify as archaeology.

It worked, until it didn’t.

This post is the write-up of migrating the site from the old Jekyll build to the Astro version you’re reading now.

What I was running before

The old site was a Jekyll build with date-based permalinks, the Minimal Mistakes theme, taxonomy pages, and Disqus comments. The piece worth calling out was photography: a bespoke Ruby plugin that walked a folder, generated thumbnails, and stripped EXIF using ImageMagick. A lot of power, and a lot of native dependency surface area.

The Gemfile told the rest of the story. It pinned specific versions just to keep things compiling on Fedora, the kind of “works on my machine, please don’t touch it” friction I was ready to retire.

My constraints for the migration

I didn’t want a “new app”. I wanted the same site, with a better build.

  • Static-only output (no server runtime)
  • Same hosting (S3 + CloudFront)
  • Keep old blog permalinks working
  • Markdown-first content, with MDX when it’s useful

The big shift: themes → content + components

Jekyll is a wonderful tool, but it encourages an ecosystem of theme conventions, Liquid templates, and plugin hooks. With Astro, the unit of composition becomes components plus data, rendered statically by default. Instead of discovering behavior by digging through theme docs, the behavior lives right there in the repo.

The quiet win is typed content. Blog and page frontmatter share a validated shape, which makes it hard to accidentally ship a broken post.

Photography: Ruby pipeline → framework assets

This was the most satisfying refactor.

In the Jekyll version, a custom plugin did a ton of image work at build time. In Astro, I just drop photos into a folder, point a little gallery metadata at it, and let the framework handle resizing, optimization, and the full-size versions for the lightbox.

Net effect: no Ruby native deps, no custom plugin execution, and a much simpler mental model: files plus a small amount of metadata.

CI/CD: PR previews and static deploys

The new setup formalizes how the site ships. Every pull request builds and deploys to its own scoped preview, pushes to main go to production, and closing a PR cleans the preview up.

The payoff is being able to review a static site change as a real deployed site before it hits production, without standing up any extra infrastructure.

One migration footgun is URLs. The old site used dated permalinks like /2012/03/15/octopress-up-and-running.html; the new one uses slugs like /blog/2012-03-15-octopress-up-and-running/.

To preserve inbound links (and my own muscle memory), I added redirect rules so the known old post paths 301 to their new homes. Not everything needs to be permanent, but the old blog post URLs absolutely do.

What I like better now

This migration wasn’t about chasing shiny things. It was about removing friction.

  • Build is Node-based (no Ruby toolchain, no native gems)
  • Site metadata is typed
  • Layouts and components are local and explicit
  • Images are handled by the framework
  • Deploys are automated and reviewable

What’s next

I intentionally kept the migration lean: get the new generator in place, keep the look and feel, keep content working, preserve URLs.

Things I’m still considering: a dedicated tags page, client-side search if it ever feels necessary, and comments again, but only if they’re low-noise and low-maintenance.

For now: the site is static, fast, and a lot easier to live with.

Leave a comment

Your comment will be pending admin review. If you're not logged in, we'll email you to confirm first.

Comments

Loading…