Ship a Static Site With Nothing but Git Push
Why GitHub Pages beats Vercel, Netlify, and a VPS for a solo founder's first landing page: zero cost, no third-party login, and the deploy is a git push.
Every product needs a front door — a landing page that exists before the product does, collects a few emails, and proves to you that the idea is worth another weekend. The tooling industry has spent a decade convincing solo builders that this front door requires a platform account, a build pipeline, and a dashboard to babysit. It does not.
After shipping a handful of small apps, each needing its own landing page, I cycled through the usual suspects — Vercel, Netlify, a VPS I rented and felt clever about — and moved every single one back to GitHub Pages. Not because the others are bad, but because for a static front door they add a layer of account, billing, and third-party login you get nothing for. GitHub Pages is free, it needs no login beyond the GitHub account you already have, and the deploy is the git push you were going to run anyway. Here's the whole setup, including the one gotcha that will otherwise cost you an afternoon.
Why GitHub Pages wins for this specific job
The pitch is narrow on purpose. This isn't "GitHub Pages beats Vercel for everything" — it obviously doesn't. It's that for a static landing page, the things Vercel and Netlify are good at (serverless functions, preview deploys, edge middleware) are things you don't need yet, and the price of having them is another account to manage and another place your project's state lives.
Three concrete reasons it wins for a first landing page:
- Zero cost, permanently. No trial that expires, no "you've used your free build minutes" email. Public repos get Pages for free with no asterisk.
- Zero new logins. Your code is already on GitHub. The host is the same account as the repo. There's no OAuth handshake to a second platform that then wants access to all your repositories.
- The deploy is a git push. You were going to commit and push anyway. On GitHub Pages, that push is the deployment. There's no separate deploy step, no CLI to install, no dashboard to click through.
The mental model is one line: your repository is the deployment. Everything downstream follows from that.
What you need before you start
Not much: a GitHub account, Git installed locally, and — optionally — a domain. If you skip the domain, GitHub gives you a free <username>.github.io address with SSL that just works, no configuration at all. That's a completely legitimate place to launch from while you decide whether the idea deserves a real domain. (When it does, the domain-to-DNS walkthrough covers the twenty-minute path.)
One repo rule to know: if you want the site served at <username>.github.io, the repository must be named <username>.github.io exactly. If you're binding a custom domain instead, the repo name can be anything. Either way the repo has to be Public — GitHub Pages on the free tier only serves public repositories.
Two ways to build: plain HTML or a real generator
You have a fork in the road, and the right branch depends on how much the site will grow.
Path A — static HTML. The simplest possible thing. Drop an index.html in the repository root and GitHub Pages serves it directly. No build step, no framework, no generator. For a single landing page this is genuinely the correct choice — a hand-written HTML file with inline styles will load faster and break less than anything with a build pipeline. Don't over-engineer a front door.
Path B — a static site generator. The moment you want more than one page — a blog, a changelog, docs, anything that benefits from SEO and shared layout — reach for Hugo. Hugo is the fastest static site generator around: you write Markdown, it generates HTML, and it supports themes so you're not designing from scratch. Setup is brew install hugo, then hugo new site . --force in your repo, then add a theme like PaperMod as a git submodule. Now every article is a Markdown file you commit, and Hugo builds the whole site into static HTML on push.
The tradeoff is honest: Path A is less to learn and impossible to break; Path B is more setup up front but scales to a hundred articles without you touching HTML again. Start with A for a pure landing page. Switch to B the first time you catch yourself copy-pasting a header between two HTML files.
The GitHub Actions workflow that builds on every push
Path A needs no build — GitHub serves the HTML as-is. Path B needs a build step, and this is where GitHub Actions turns the whole thing back into "just a git push."
You add one file, .github/workflows/deploy.yml, that says: on every push to main, build the site and publish it. The pattern is three well-known actions chained together — peaceiris/actions-hugo to install Hugo and build, actions/upload-pages-artifact to package the output, and actions/deploy-pages to publish it. Then in the repo's Settings → Pages → Source, you select GitHub Actions as the source instead of a branch.
Once that's wired, the loop is exactly what you already do: write Markdown, git commit, git push. The Action fires automatically, rebuilds the site, and the new version is live in a minute or two. You never run a deploy command, because pushing your code is the deploy command. No CLI, no dashboard, no "deploying..." spinner in a browser tab — just the terminal you were already in.
Binding a custom domain
When the idea earns a real domain, the binding is two steps. In Settings → Pages → Custom domain, enter your root domain; GitHub auto-generates a CNAME file in the repo recording it. On the DNS side, you point four A records at GitHub's IPs and a www CNAME at <username>.github.io — the exact records and the registrar-side setup are laid out in the domain article. Two systems, five records, done.
The gotcha: "DNS Check in Progress" forever
Here's the one that will otherwise eat your afternoon, and it lives right at the seam between GitHub and Cloudflare.
If you routed your DNS through Cloudflare with the records set to Proxied — the orange cloud — GitHub's domain-verification check will sit at "DNS Check in Progress" and never turn green. It's not broken and you didn't misconfigure it. The problem is that GitHub looks up your domain, sees Cloudflare's proxy IP instead of its own 185.199.x.x addresses, and refuses to confirm ownership of an address it doesn't recognize.
The fix: flip the A records and the
wwwCNAME to grey (DNS only), wait for GitHub's check to go green, then flip them back to orange.
That's the whole cure. Set the records to DNS only temporarily so GitHub can see the real GitHub Pages IPs, let the verification pass and the certificate issue, then re-enable the Proxied orange cloud to get Cloudflare's CDN and DDoS protection back in front of the site. The rule underneath it — any host that issues its own SSL certificate needs to see your real DNS first — is the same one that governs the orange/grey toggle across every static host, and it's worth internalizing once so you never lose an afternoon to it again.
The honest limitations
GitHub Pages is static hosting, full stop. There are no serverless functions, no server-side rendering, no databases. If your landing page needs to do something — capture emails to a backend, run a form handler, gate access — you pair it with something else: a form service, a Cloudflare Worker, or an external waitlist tool. That pairing is a feature, not a workaround; it keeps the front door dead simple while the dynamic bits live where dynamic bits belong. The zero-server waitlist walkthrough shows exactly how to bolt email capture onto a static page without standing up a backend, and Cloudflare Workers covers the case where you need a little compute at the edge.
For the thing GitHub Pages is actually for — a fast, free, permanent front door that deploys when you push — nothing else on the market is simpler. Six landing pages taught me that the winning move for a solo builder isn't the platform with the most features. It's the one with the fewest accounts, the smallest bill, and a deploy step you were going to run regardless. That's git push, and it's already in your muscle memory.
Part of the Vibe-entrepreneurs series on the solo founder's infrastructure stack. Previously: Domain Name to Live DNS in Twenty Minutes. Next: Build a Waitlist Page in 30 Minutes With Zero Servers and Deploy Global Infrastructure Free With Cloudflare Workers. More builder insights.