Static sites are HTML, CSS, JavaScript, and assets with no server-side execution at request time. In 2026, "static" does not mean simple — it includes statically exported Next.js, Astro, SvelteKit, and Eleventy apps that may pull data at build time. Deploying them correctly means getting CDN distribution, TLS, cache control, and rollbacks right. Here is how.
What changed in 2026
- Cloudflare Pages closed the gap with Vercel and Netlify on build speed and now has parity on framework detection. Its global network (300+ PoPs) often wins on TTFB.
- Astro 5 became the go-to framework for content-heavy static sites, with partial hydration and server islands replacing the need for a full SSR server.
- Edge middleware (Vercel Edge, Cloudflare Workers) lets you run lightweight personalization logic at deploy time without a dedicated server.
- All three major platforms added build caching by default — a full Next.js rebuild takes ~30 s instead of ~90 s on warm cache.
Platform comparison
| Platform |
Free tier limits |
Build minutes |
Edge functions |
Best for |
| Vercel |
100 GB bandwidth |
6,000/month |
Yes |
Next.js, React |
| Netlify |
100 GB bandwidth |
300/month |
Yes |
Any framework |
| Cloudflare Pages |
Unlimited bandwidth |
500/month |
Yes (Workers) |
High-traffic sites |
| GitHub Pages |
1 GB, 100 GB/month |
GitHub Actions |
No |
Docs, portfolios |
Deploy to Vercel
npm install -g vercel
vercel login
vercel --prod
Or connect via the Vercel dashboard: import your GitHub/GitLab repo, set the framework, and every push to main deploys automatically. Every branch gets a preview URL.
Deploy to Cloudflare Pages via GitHub Actions
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '22' }
- run: npm ci && npm run build
- uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
command: pages deploy ./dist --project-name=my-site
Cache header strategy
Correct caching is the highest-leverage performance win for static sites. Set it at the platform level:
| File type |
Cache-Control value |
Why |
index.html |
no-cache |
Ensure new deploy is seen immediately |
/assets/*.js (hashed) |
public, max-age=31536000, immutable |
Hash changes with content; safe to cache forever |
/assets/*.css (hashed) |
public, max-age=31536000, immutable |
Same as JS |
| Images (hashed) |
public, max-age=31536000, immutable |
Same |
robots.txt, sitemap.xml |
public, max-age=3600 |
Stale is fine for an hour |
In a Vercel vercel.json:
{
"headers": [
{
"source": "/assets/(.*)",
"headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
},
{
"source": "/(.*).html",
"headers": [{ "key": "Cache-Control", "value": "no-cache" }]
}
]
}
How to set up preview deployments
- Vercel / Netlify — enabled by default when you connect a git repo. Every PR gets
https://my-site-git-branch-org.vercel.app.
- Cloudflare Pages — also automatic; previews are at
https://<commit-hash>.my-project.pages.dev.
- Post the preview URL as a PR comment — most platforms do this automatically; if yours does not, add a GitHub Actions step using
actions/github-script.
How to pick your platform
- Using Next.js? → Vercel is the lowest-friction choice; first-party support.
- Need unlimited bandwidth on free tier? → Cloudflare Pages.
- Need form handling, split-testing, or identity built in? → Netlify.
- Internal tool, docs, or portfolio? → GitHub Pages is free and sufficient.
- Enterprise with existing AWS? → S3 + CloudFront + a GitHub Action is the path; managed platforms are simpler but may not fit procurement requirements.
Common mistakes
No preview deployment URL in PR checks. Reviewers cannot verify visual changes without a running preview. Make sure the platform integration posts the URL.
Deploying directly to main without a build check. Add a CI job that builds the site and fails the PR if the build breaks. Never merge a broken build.
Ignoring build output size. Static site bundles can bloat with unoptimized images and duplicate dependencies. Run npm run build -- --analyze (Next.js) or equivalent to catch regressions.
Not setting baseUrl for subdirectory deploys. If your site lives at /docs/, configure basePath or base in the framework config, or all asset paths break.
What to skip
- Self-hosted Nginx for a purely static site. You handle patching, TLS renewal, and CDN yourself. Managed platforms are free for most use cases and objectively less work.
- Server-Side Rendering for content that does not change per-user. Static export + ISR (Incremental Static Regeneration) covers most content sites without a running server.
- Complex deployment scripts. A
npm run build + a platform git integration is the entire pipeline for most teams.
FAQ
Can I use a custom domain on all these platforms?
Yes. All three support custom domains and handle TLS certificate provisioning via Let's Encrypt automatically.
How do I roll back a bad deploy?
Vercel, Netlify, and Cloudflare Pages all provide one-click rollback to any previous deployment in their dashboard.
What about environment variables for build-time data fetching?
Set them in the platform dashboard (never commit them). They are available during npm run build as process.env.VAR_NAME.
Is a static site the same as a JAMstack site?
"JAMstack" is the older marketing term. Today the common term is "static site" or "statically exported framework app."
Where to go next