GitHub Pages Alternative: 420 Static Routes, 8 That Need a Server
GitHub Pages has no compute layer at all. The five alternatives worth naming, measured against this build's 420 static routes and 8 dynamic ones.
GitHub Pages serves static files from a repo — no server, no functions, no runtime of any kind. An "alternative" is only meaningful once you name what it replaces: pure static hosting (Cloudflare Pages, Netlify's static tier, S3+CloudFront), or a platform that stays static-first but adds compute where you need it (Vercel, Netlify Functions, Cloudflare Workers). This storefront's own build makes the answer numeric: 420 statically prerendered routes any of them serves the same way, and 8 dynamic routes that eliminate the pure-static tier outright. Below are the five alternatives worth naming, measured against those two counts.
The decision axis, and where each host sits
| Host | Serves static? | Runs code per request? | Framework-aware? | Free tier fits this site? |
|---|---|---|---|---|
| GitHub Pages | Yes | No | No — bring a build output | Yes, but only for the 420 static routes |
| Cloudflare Pages | Yes | Yes (Workers) | Partial — Next.js on Pages via @cloudflare/next-on-pages | Yes |
| Netlify | Yes | Yes (Functions + Edge Functions) | Yes — Next.js runtime plugin | Yes |
| Vercel | Yes | Yes (Serverless + Edge) | Yes — first-party, deploys Next.js's own output | Yes |
| S3 + CloudFront | Yes | No (need Lambda@Edge for compute) | No — bring a build output | Free tier is credit-based, not always-free |
| Render (static site) | Yes | No (Web Services do; Static Sites don't) | No | Yes |
The columns that matter are the middle two: does it run code on a request, and does it understand the framework you build with. GitHub Pages answers no to both. Everything else in the table answers yes to at least one.
What this build looks like
A fresh npm run build of this storefront prints the route table split by mode:
Route (app) Size First Load JS
┌ ○ / 4.2 kB 98 kB
├ ○ /pricing 3.1 kB 96 kB
├ ● /templates/[slug] 9.4 kB 112 kB (111 pages)
├ ● /blog/[slug] 7.8 kB 104 kB (141 pages)
├ ○ /nextjs-landing-page-template 6.1 kB 101 kB
├ ○ /nextjs-admin-template 6.1 kB 101 kB
│ ...seven category hubs total...
├ ƒ /api/download
├ ƒ /api/webhooks/lemonsqueezy
├ ƒ /auth/callback
├ ƒ /dashboard
├ ƒ /dashboard/settings
├ ƒ /login
├ ƒ /reset-password
└ ƒ /signup
○ (Static) prerendered
● (SSG) prerendered per slug from generateStaticParams
ƒ (Dynamic) server-rendered on demand
420 static routes, 8 dynamic. For the first number, every host in the table above serves the same output. For the second number, GitHub Pages and S3+CloudFront without Lambda@Edge can't run it at all — not slower, not through a workaround, just cannot.
What the 8 dynamic routes actually need
Each of the 8 does something a static file can't:
/api/webhooks/lemonsqueezy— reads the raw request body byte-for-byte to verify an HMAC signature. Static hosts don't run code; they don't see the request body at all./api/download— resolves the buyer's entitlement from Postgres and mints a short-lived signed URL. No signature, no download./auth/callback— exchanges an OAuth/PKCE code for a session cookie. A file server can't write aSet-Cookieheader./dashboard,/dashboard/settings,/login,/reset-password,/signup— read the session cookie and render per-user content.
Every host that runs code has an equivalent for these — Cloudflare Workers, Netlify Functions, Vercel Serverless Functions, Render Web Services. Every host that doesn't just doesn't have this site running on it.
Pure-static alternatives (choose if the 8 dynamic routes don't apply to you)
Cloudflare Pages (static tier). The closest replacement, and in some measurements faster than GitHub Pages: Cloudflare's edge network is denser and their asset cache is aggressive. Custom domain + automatic HTTPS + Git integration + preview deployments per PR. The free tier includes 500 builds/month and unlimited requests. Add Cloudflare Workers alongside for the compute half and you're already in the "static-plus" tier below.
Netlify (static-only usage). Same pattern as Cloudflare Pages: Git integration, PR previews, custom domain, HTTPS. 100GB bandwidth on free. Their Functions add the compute half whenever you decide you need it.
S3 + CloudFront. The self-managed version — an S3 bucket serving files behind CloudFront for HTTPS and cache. No CI, no PR previews, no framework awareness; you build locally or in Actions and upload. Cheapest at scale, most operational overhead, and CloudFront's free tier is credit-based so a viral post could bill you.
Render Static Sites. Similar to Netlify's static tier — Git integration, HTTPS, PR previews. Simpler UI, smaller free tier bandwidth.
The pure-static tier is where GitHub Pages competes. The reason to leave it is usually not performance — it's Git ergonomics (branch-based deploys, monorepo-friendly builds, PR previews) or build-time integration with the site generator you actually use.
Static-plus-compute alternatives (choose if you have any dynamic routes)
Vercel. Deploys Next.js's own build output directly, including Route Handlers, Server Actions, middleware and image optimization. The 8 dynamic routes in the table above run as serverless functions with no configuration authored for them. Cost scales with function invocations and bandwidth; free tier fits this site.
Cloudflare Pages + Workers (or Next-on-Pages). Runs Next.js on Workers with the @cloudflare/next-on-pages adapter. Node-runtime routes (like /api/webhooks/lemonsqueezy, which needs node:crypto) are the sharp edge — the adapter can run some of them on the Node compat layer, but coverage lags Vercel's. Cheaper compute per request; more configuration to get parity.
Netlify + Functions. Netlify's Next.js Runtime handles App Router, Server Actions, middleware and ISR. Their functions:on-demand model is closest to Vercel's. Coverage of the newest Next.js features usually trails Vercel by a release.
The decision, in one paragraph
Count the routes that need a server. If it's zero, GitHub Pages does the job — moving to Cloudflare Pages or Netlify's static tier buys you PR previews and better CI ergonomics, not a technical capability. If it's one or more (webhook, auth callback, per-user rendering), the static-only tier is off the table, and the choice is which compute layer to run under: Vercel for zero-config parity with Next.js, Cloudflare Pages for lower per-request cost, Netlify for the middle ground. See vercel-vs-cloudflare-pages for the two-way version of that decision measured against this same build.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Migration from GitHub Pages breaks pretty URLs | GitHub Pages defaults to trailingSlash: true on generated sites | Match the trailing-slash setting on the new host or add a redirect table; see nextjs-trailing-slash |
| Custom domain works on GH Pages but not on the new host | DNS is still pointing at <user>.github.io | Update the A/CNAME records to the new host's targets; propagation can take up to 48h |
| The new host serves stale HTML after a deploy | Cache-invalidation not tied to the deploy hash | Use the host's built-in deploy hooks (Cloudflare Pages, Vercel, Netlify all invalidate on deploy); on S3+CloudFront you must issue an invalidation |
| A Route Handler that ran locally 500s in production | Bundled runtime doesn't include node:crypto or another Node-only module | Pin the route's runtime to nodejs (export const runtime = "nodejs"), or move the code to an Edge-safe primitive |
| The dashboard renders as blank HTML on the new host | The host doesn't run dynamic routes at all (GitHub Pages, S3-only) | Pick a host that runs code per request; the 8 dynamic routes here need it |
| Build fails on the new host but works locally | Node version mismatch or missing environment variable | Pin the Node version in the host's dashboard; move env vars from .env.local into the host's env-var UI |
FAQ
Is GitHub Pages actually being deprecated? No. GitHub Pages is actively maintained and used by millions of sites. The reason to leave it is a technical need it categorically doesn't cover (running code per request), not that it's going away.
What's the cheapest host for a Next.js site with a few dynamic routes? Vercel and Cloudflare Pages both fit this site's traffic on their free tiers. Beyond the free tier, Cloudflare tends to be cheaper per request; Vercel bundles more Next.js-specific features (ISR, image optimization) that would otherwise be your problem to build.
Can I run Next.js on GitHub Pages if I set output: "export"?
For a fully static export, yes — you get the static half of this site (420 routes). The 8 dynamic routes here would all silently disappear from the build, so the answer is only yes if you don't have any.
Do I need a CDN in front of my alternative? Every host in the table above already sits on a global CDN (Cloudflare's own, Vercel's edge network, Netlify's edge, CloudFront). Adding a second CDN in front of them buys nothing and usually breaks cache-invalidation on deploy.
Templates in this post
ASoc Echo is an AI-chatbot landing page, ASoc Edge an applied-AI-agency template, and ASoc Fade a barbershop website — three of the 66 landing templates that would be served identically from any host in the table above.
Browse the full sets: Next.js landing page templates, Tailwind landing page templates. For the head-to-head that measured the same 8 dynamic routes against a specific competitor, see Vercel vs GitHub Pages and Vercel vs Cloudflare Pages.
