Official guide for deploying a static site or SPA to S3 with CloudFront. Read →
For static sites (HTML/CSS/JS, React/Next.js/Vue builds), you don't need an EC2 server at all. S3 stores files. CloudFront serves them from 300+ edge locations globally — your users get sub-50ms response times regardless of where they are.
# Create an S3 bucket
aws s3 mb s3://your-app-bucket --region us-east-1
# Build your app (React/Next.js/Vue)
npm run build
# Sync build output to S3
aws s3 sync ./dist s3://your-app-bucket --delete --cache-control "public, max-age=31536000, immutable"
# HTML files should not be cached aggressively
aws s3 cp dist/index.html s3://your-app-bucket/index.html --cache-control "no-cache"
# Make bucket private (CloudFront will access it via OAC)
# Don't enable "public access" — use Origin Access Control instead
# Key CloudFront settings:
# - Origin: your S3 bucket (use Origin Access Control, not public)
# - Origin Access Control (OAC): CloudFront-only access to S3
# - Default root object: index.html
# - Price class: Use only North America and Europe (cheaper)
# - Alternate domain: yourapp.com
# - SSL certificate: from ACM (must be in us-east-1!)
# - Error pages: 404 → /index.html (for SPAs with client-side routing)
# Invalidate cache after deploy (forces CloudFront to fetch fresh files)
aws cloudfront create-invalidation --distribution-id E1234567890ABC --paths "/*"
# Check distribution status
aws cloudfront get-distribution --id E1234567890ABC --query 'Distribution.Status'
CloudFront only supports ACM certificates from the us-east-1 (N. Virginia) region, regardless of where your other resources are. Always request the cert there.
React/Vue SPAs handle routing client-side. CloudFront doesn't know about /about — it looks for an S3 object at that path and returns 403/404. Fix this in CloudFront error pages:
# CloudFront → Error pages → Create custom error response:
# HTTP error code: 403
# Response page path: /index.html
# HTTP response code: 200
# Same for 404 → /index.html → 200
# Your SPA's router will then handle the URL