Pay it forward: Fork this blog template and make it yours

The code behind this site is now a template you can clone and deploy for yourself. A sneaky peak at the journey from a public repo to a forkable template.
This site began life as a fork from a starter template. Back in October 2024 I took the Next.js and Contentful example that Vercel publishes, the one with draft mode and a basic layout already wired in, tweaked a few things here and there, and then left it unchanged for eighteen months.
It was never supposed to be a web development project. It was a sandbox for generative AI experiments, somewhere to play with the copy and image creation. The code underneath was completely ignored.
This summer, I decided to take a different approach. Through a series of conversations with Claude, I realised the codebase could also be an area I worked on. And that's the site you're visiting now, the results of many weeks of peeling back the layers and conducting extensive renovations. It's been fun!
I also had an epiphany. A group of talented folks at Vercel and Contentful were kind enough to give me a running start. I could do the same for the next person. So when I started thinking about the purpose of this codebase (beyond running my own personal fiefdom), the answer was simple: pay it forward under an MIT license.
In this post, let's dig into the process of taking a codebase from "my repository is public” to “you can fork this for yourself.” It was slightly trickier than I envisaged, but worth the effort.
What a fork actually carries
First and foremost, a headless CMS like Contentful needs a working content model before it can manage a single post or page.
A content model is the schema for your content. It defines the types of content you can create, like a Post, an Author or a Category. It also documents the fields that belongs to each type, like a title, a slug or a body. The owner of the content model decides the spec based on their own needs, so no two models are necessarily alike.
The other core concept is the relationship between one content type and another. In the model for this blog, for example, a single Post (which is a content type) points to single Author (which is another content type). That relationship can be mandatory – in my world, you cannot publish a blog post without an author – or it can be optional. It's entirely up to you.
The starter template from Vercel ships with a basic content model that you import to bootstrap your space. Run the setup script and you have the same content types the demo had, ready to go. It's a tidy mechanism that's very helpful at the outset.
Much later, I expanded this model to fill out the edges a bit, to enable more ambitious things like landing pages for authors and categories, or blocks to render longer snippets of code. All of which is to say is that development of the model is an ongoing process; it will change as my needs for the site change.
But for the purpose of forking, I took a snapshot of the model as it functions today so it could be exported into the template.
A snapshot of the content model underpinning this blog.
Making it universal, not just public
Making the repository genuinely forkable meant generating that snapshot fresh from my own space and being deliberate about what made the cut.
I scoped it to the content model and the locales, the parts a fork needs to actually function, and left the rest out. The roles tied to my organisation went. The user IDs that mean nothing to anyone but me went. What remains creates a working content model and stops there, so others have a blank slate to work from.
I also split the import in two. One command sets up the content model and nothing else. The schema is universal and belongs in the template.
A second, optional one drops in a few placeholder posts so a fresh clone renders something rather than an empty page. The seed ships a single placeholder image, reused for every cover and avatar, so the import stays light and carries no other bundled media.
The rest was housekeeping in the same spirit. I wrote down every environment variable a cold clone needs in a .env.local.example. And I added a section to the README that walks the whole path start to finish, from cloning the repo to a deployed site.
A mock post on the forkable template, written by one "Alex Placeholder". That kid will go far.
Cha-cha-changes
Some things you should consider before you deploy:
Site URL (required). Set
NEXT_PUBLIC_SITE_URLto your own domain in.env.localand in your host. Without it the canonical links, sitemap, OG tags, and RSS fall back to a localhost URL.Site identity. Edit
SITE_TITLE,SITE_DESCRIPTION,SITE_AUTHOR, andSITE_REPO_URLinlib/constants.ts.llms.txt. The document at
public/llms.txtis a hand-written file describing the original site for LLMs. Replace it with your own, or delete it.Brand assets. Replace the Open Graph image
public/be_useful.jpg, swap the favicon and app icon, and retune the palette tokens andthemeColorinapp/globals.cssandapp/layout.tsxif you want a different look.Seed images (optional). If you re-run the seed, repoint
PLACEHOLDER_ASSET_URLincontentful/build-seed.mjsto your own copy, then replace the placeholder cover, avatar, and thumbnail with real assets afterwards.CLAUDE.md (optional). Useful as-is for working with Claude Code on the repo. Review it for any notes specific to the original author.
Take it, it's yours
The repository is here. It's the same code this site runs on, generated clean and documented clearly enough to get going.
If you fork it and build something of your own, I'd dearly love to see what you end up with.
Thank you for reading.

