TL;DR: Your project can have a real website for free. Turn on GitHub Pages, point it at a static-site generator like Jekyll, and you get a fast, secure, CDN-backed site built straight from your repo. Add a custom domain with a one-line
CNAMEfile, build a landing page that sells the project, add support and sponsor pages so people can get help and chip in, and run a blog — including scheduled, drip-released posts. The whole thing lives in the same repo as your code and deploys on every push.
Key takeaways
- GitHub Pages hosts a static website from your repo, free, with HTTPS and a CDN.
- A static-site generator (Jekyll) turns Markdown into a real site — no servers.
- A custom domain is a one-line
CNAMEfile plus a DNS record. - Support and sponsor pages let users get help and fund the work.
- Future-dated posts plus a daily build = a blog that drip-releases itself.
This is Part 10 of Build in the Open, a 14-part series on taking a software project from a blank idea to a public release using GitHub and Claude Code. Each post teaches a technique you can apply to any project in any language, then shows how the open-source GopherTrunk scanner does it for real.
In this post
- What GitHub Pages is and why it’s the easy default.
- Static-site generators — what Jekyll buys you over hand-written HTML.
- Custom domains with a
CNAMEfile. - Landing, support, and sponsor pages — the pages a project actually needs.
- Running a blog — including scheduled, drip-released posts.
- How GopherTrunk does it, as a concrete example you can copy.
What is GitHub Pages?
GitHub Pages is free static-site hosting built into GitHub. You enable it in
Settings → Pages, choose a source (a branch, a /docs folder, or — better —
GitHub Actions), and GitHub serves the result over HTTPS from a CDN at
username.github.io/repo. Because the site is static — plain HTML, CSS, and
JavaScript — there’s nothing to run, nothing to patch, and nothing to pay for.
“Static” sounds limiting but rarely is. Docs, landing pages, blogs, and marketing sites are all static by nature, and a static site is the fastest and most secure thing you can ship.
Why use a static-site generator?
Writing raw HTML for every page gets old fast. A static-site generator lets you write content in Markdown, share layouts and navigation across pages, and build the whole site with one command. Jekyll is the generator GitHub Pages supports natively — Pages can build a Jekyll site for you with no extra setup.
What a generator buys you:
- Markdown instead of HTML. Write content; the generator wraps it in your layout.
- Shared layouts and includes. Change the header once, every page updates.
- Plugins. SEO tags, sitemaps, and RSS feeds for free.
- A blog engine. Drop a file in a posts folder and it becomes a post.
Other generators (Hugo, Eleventy, Astro, MkDocs) work on Pages too, usually via a GitHub Actions build. Jekyll is just the path of least resistance.
Custom domains with a CNAME
A username.github.io URL works, but a real project wants a real domain. Pages
makes this a two-step affair:
- Add a file named
CNAMEto your site source containing just your domain, e.g.example.org. - At your DNS provider, point the domain at GitHub Pages (a
CNAMErecord tousername.github.io, orA/AAAArecords to GitHub’s IPs for an apex domain).
GitHub then provisions a free TLS certificate, and your site serves over HTTPS on your own domain. One file, one DNS record, done.
The pages a project actually needs
Beyond the docs, a few pages do real work:
- A landing page. The pitch: what the project is, who it’s for, and a prominent path to download or get started. This is where you convert a curious visitor into a user.
- A support / community page. Where to ask questions and report problems — links to issues, a Discord or forum, a FAQ. Reduces the “how do I get help?” friction to zero.
- A sponsor / funding page. If you want support for the work, make it easy.
GitHub reads a
.github/FUNDING.ymlfile and renders a Sponsor button on your repo automatically; you can list GitHub Sponsors, Ko-fi, Patreon, and more. - A blog. For release notes, tutorials, and build-in-the-open posts like this one — which doubles as SEO and a reason for people to come back.
Running a blog (and drip-releasing posts)
A static blog is just dated files in a posts folder. The clever part is scheduling. Most generators, Jekyll included, will exclude a post dated in the future from the build. Pair that with a daily scheduled rebuild and you get a powerful pattern:
- Write a whole series at once, dating the posts on consecutive future days.
- Commit them all in one pull request.
- A daily build job rebuilds the site; each day, the posts that have “come due” appear automatically.
No draft branches, no daily commits, no manual publishing — the calendar does the releasing for you. (This very series is published exactly that way.)
How GopherTrunk does it
GopherTrunk’s entire website —
gophertrunk.org — is a Jekyll site on GitHub Pages,
built from the repo’s docs/ folder. The pieces line up with everything above:
- Custom domain via
CNAME.docs/CNAMEcontains exactly one line —gophertrunk.org— and that’s what serves the site on its own domain over HTTPS. - The landing page is synthesized from the README at build time. The Pages
workflow (
.github/workflows/pages.yml) has a “Synthesize landing page from README.md” step that transformsREADME.mdintodocs/index.mdduring the build — rewriting asset paths and cross-links and stripping the duplicate hero. The homepage and the README can never drift apart, because there’s only one source (the doc-organization payoff from Part 9). - SEO comes from plugins.
docs/_config.ymlenablesjekyll-seo-tag(titles, meta descriptions, Open Graph/Twitter cards),jekyll-sitemap(sitemap.xml), andjekyll-feed(an Atom feed at/feed.xml) — so search engines and readers get structured metadata for free. - Support and sponsor links are real files. There’s a
docs/support.mdpage, and.github/FUNDING.ymllists GitHub Sponsors (github: MattCheramie) and Ko-fi (ko_fi: Mrcheramie), which GitHub turns into the repo’s Sponsor button. - The blog drip-releases itself.
docs/_config.ymlsetsfuture: false(a future-dated post stays out of the build until its date), andpages.ymlruns a dailycron: "0 16 * * *"rebuild. A whole series is committed at once on consecutive future dates and goes live one post per day — with ascripts/schedule-series.pyhelper to assign the dates. That’s the mechanism publishing the post you’re reading now.
You don’t need a radio project to copy this. Any repo can flip on Pages, drop a
CNAME, point Jekyll at a /docs folder, add a FUNDING.yml, and schedule a
blog — all for the price of a push.
FAQ
Is GitHub Pages really free? Yes, for public repositories, including HTTPS and CDN delivery, within generous soft bandwidth and size limits. For a project site, docs, or blog you will almost certainly never hit them.
Do I have to use Jekyll? No. Jekyll is the generator Pages builds natively with zero config, but you can deploy any static site — Hugo, Eleventy, Astro, plain HTML — by building it in a GitHub Actions workflow and publishing the output. Jekyll is just the lowest- friction option.
How do I add a custom domain to GitHub Pages?
Add a CNAME file containing your domain to the site source, then create a DNS
record at your registrar pointing the domain at GitHub Pages. GitHub provisions
a free TLS certificate automatically once DNS resolves.
How do I schedule blog posts to publish on a future date?
Date the post in the future and configure your generator to exclude future-dated
content (future: false in Jekyll), then run a daily scheduled build. Each
build reveals the posts whose date has arrived — so you can write a series now and
have it release one post per day.
How do I add a Sponsor button to my repo?
Add a .github/FUNDING.yml listing your funding platforms (GitHub Sponsors,
Ko-fi, Patreon, etc.). GitHub reads it and shows a Sponsor button on the repo
automatically — no other setup required.
Series navigation
Part 10 of 14 · ← Part 9 · Next → Part 11: Releases — Pre-release, SemVer & Changelogs