Development
Migrating from Jekyll to Astro without rebuilding the whole site
I migrated my personal site from Jekyll to Astro while keeping the content and publishing layers intact.
This site did not start on Jekyll.
It started on Tumblr, then moved to Octopress, and later settled on Jekyll.
By the time I was on Jekyll, I already knew the content and publishing layers should not have to change just because the renderer did.
I wanted the content to stay in Markdown or plain text. I wanted publishing to stay cheap and stable. And I did not want every redesign to force me to rethink the whole system.
So when I migrated this site again, I was not trying to invent a new structure from scratch. The job was not to rebuild the site. It was to replace the layer that had become the constraint.
Jekyll was simple, and the structure already made sense
For a long time, Jekyll worked because it made publishing cheap and straightforward.
I could keep the site on GitHub Pages, pay only for the domain, and not think too much about infrastructure. In fact, I have always felt like the site should stay alive even if I pass away suddenly. Renewing the domain for long periods makes sense to me. And even without the domain, the site can still stay alive as long as GitHub is still around.
What I liked was that the structure already made sense.
There was a content layer, a renderer layer, and a publishing layer.
That mattered because the writing could stay stable even if the frontend changed.
The migration was really about replacing the renderer
When I decided to use AI to help with the migration, I already knew I did not want to keep building on Jekyll. It worked, but it was too limiting.
The obvious job was porting the renderer. The real question was how much work it would take to do that cleanly without disturbing the rest of the setup.
I already knew I wanted to keep the structure. I just needed to replace the part that had become the constraint.
The three layers still made sense
In practice, those layers are three separate repos.
sayzlim-content is where the posts live. Pages, notes, tools, redirects, all the markdown-driven parts of the site belong there. It is the source of truth for what I write.
sayzlim-renderer is the app layer. It used to be Jekyll. Now it is Astro. It owns the layout, design system, build logic, and deployment workflow.
sayzlim.github.io is still the publishing layer. I wanted to keep that part stable so I would not have to touch DNS or rethink where the final site should live.
That was the main thing I wanted to preserve through the migration. The renderer could change completely without forcing the content and publishing layers to be reinvented.
What connected them
The repos were already split. The job here was reconnecting them in a way that still felt lightweight after the renderer changed.
During the prompt session, I realized I do not even have to clone the publishing layer locally. The only repos I need to work with directly are the content repo and the renderer repo.
That clicked immediately for me.
The important local contract is SITE_CONTENT_DIR. The renderer reads from that path instead of assuming the content has to live inside the same repo. That one detail made the split feel simple instead of fragile.
Codex recommended using GitHub Actions to connect the pieces, and that clicked immediately. Content changes could trigger the renderer, the renderer could pull the latest content, and the publishing layer could stay concerned only with the generated output.
I also learned a few GitHub Actions features through this process. That matters to me because I do not just want AI to generate code for me. I want to understand the shape of the system well enough to guide it.
The flow is simple now. A push to sayzlim-content triggers the renderer workflow. The renderer pulls the latest content, builds the site with Astro, and publishes the static output to sayzlim.github.io.
That means I still get a simple publishing flow without forcing the content to live inside the renderer repo.
That was the shape I wanted to keep, even though the renderer itself changed.
Why this setup feels better
What I like about this setup is simple: writing and frontend work no longer get in each other’s way.
Writing now feels lighter because content has its own place.
Frontend changes also feel clearer because the renderer has its own history and responsibilities.
And publishing stays boring, which is exactly what I want from a personal site.
I do not think this is the only correct way to structure a site like this. But if changing the renderer forces you to rebuild everything around it, the system is shaped wrong.
If this was useful, continue through the archive or follow the thread through related notes.