Deploying a Next.js Static Site on AWS S3 + CloudFront (Beginner-Friendly Guide)

If you’re building a Next.js blog or marketing site and want fast global delivery at the lowest possible cost, hosting it on AWS S3 with CloudFront is one of the best setups you can choose.
In this guide, we’ll walk through why this setup works, how it’s structured, and common mistakes to avoid—especially if you’re doing this for the first time.
Why Use S3 + CloudFront?
Let’s keep it simple:
- S3 → stores your static files (HTML, CSS, JS, images)
- CloudFront → delivers them quickly via a global CDN
- Route 53 → connects your custom domain
Benefits
- ⚡ Extremely fast worldwide
- 💸 Very cheap (often ₹50–₹300/month for small sites)
- 🔒 Secure with HTTPS
- 📈 Scales automatically (no servers to manage)
Perfect for blogs, portfolios, landing pages, and documentation sites.
Step 1: Build Your Next.js App
For static hosting, you’ll need a static export.
npm run build
npm run exportThis creates an out/ folder containing plain HTML and assets.
⚠️ If you use App Router, make sure pages are static or use generateStaticParams.
Step 2: Create an S3 Bucket
Key points while creating the bucket:
- Bucket name = your domain name
- Example: dailydrifthub.com
- Disable Block all public access
- Enable Static website hosting
Set:
- Index document → index.html
- Error document → index.html (important for routing)
Bucket Policy (Public Read)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::dailydrifthub.com/*"
}
]
}Step 3: Upload Files to S3
Upload everything inside out/, not the folder itself.
Your bucket root should look like:
index.html
/_next
/assets
/postsStep 4: Set Up CloudFront
Create a new distribution:
- Origin domain → S3 website endpoint (not the bucket ARN)
- Viewer protocol policy → Redirect HTTP to HTTPS
- Default root object → index.html
Fix 404 Errors for Routes (Very Important)
Add Custom Error Responses:
Error Code | Response Page | HTTP Code |
|---|---|---|
403 | /index.html | 200 |
404 | /index.html | 200 |
This fixes errors when users refresh /posts/some-article.
Step 5: Connect Your Domain (Route 53)
- Create an A Record
- Alias → CloudFront distribution
- TTL → Auto
Wait a few minutes and your site should load on your domain 🎉
Do You Need CloudFront Invalidation?
Short answer: usually no.
- New files → update automatically
- Changed files → cached for TTL duration
Free tier gives 1,000 invalidation paths/month, so occasional invalidations won’t cost you.
Common Mistakes to Avoid
❌ Uploading the out folder instead of its contents
❌ Using S3 REST endpoint instead of website endpoint
❌ Forgetting error page routing
❌ Blocking public access accidentally
❌ Expecting SSR features on static hosting
Final Thoughts
This setup is:
- Production-grade
- Low maintenance
- Cost-effective
- Perfect for tech blogs like Daily Drift Hub
If you don’t need real-time server logic, S3 + CloudFront beats most hosting platforms on price and performance.
Related Posts
Useful Tools For This Topic
Explore all toolsJSON Formatter
Format, validate, and beautify JSON instantly.
JWT Decoder / Encoder
Decode payloads, verify signatures, test secrets, and generate JWT tokens.
Timestamp Converter
Convert between Unix timestamps and dates.
UUID Generator
Generate unique UUIDs for your applications.
