How to host a Single Page Application (SPA) on AWS S3 and serve it via CloudFront
Hosting modern web applications efficiently and securely is a common challenge in DevOps. In this post, we’ll walk through how to host a…
How to host a Single Page Application (SPA) on AWS S3 and serve it via CloudFront
Hosting modern web applications efficiently and securely is a common challenge in DevOps. In this post, we’ll walk through how to host a Single Page Application (SPA) on AWS S3 and serve it via CloudFront.
We’re sharing this guide based on how we’ve deployed SPAs in production for real teams — minimal fluff, just practical steps.
This post is ideal for DevOps/Cloud engineers or developers looking to set up reliable, scalable static hosting on AWS.
🎯 Goal
In this post, we’ll set up a production-ready static site hosting architecture using AWS S3 + CloudFront to serve a Single Page Application (SPA). For this we will use React simple template.
We’ll configure AWS side with terraform:
- CloudFront distribution and function
- S3 Bucket
First question before we start is, maybe, why do we need CloudFront (and CloudFront Function), and what are the benefits of this architecture?
- Why S3 Alone Doesn’t Work for SPAs Like React?
S3 is an object storage, not a web server like NGINX or Apache. It serves files exactly as they exist — no routing logic.
In SPAs (e.g., built with React, Angular, Vue), routing is handled on the client side. So when a user visits example.com/home, they’re not loading a file at /home. Instead, the browser loads index.html, and JavaScript takes over from there.
- What Happens with S3 Alone:
When you host a SPA on S3 and someone opens example.com/home. S3 tries to find an object at /home, which doesn’t exist, so it returns a 403 error. It doesn't know that /home is a client-side route and should load /index.html.
- Why We Need a CloudFront Function?
To make this architecture work like a proper web server, we attach a CloudFront Function to the Viewer Request phase. This function inspects the requested path and rewrites it to /index.html if it's a SPA route.

How request work with CloudFront and CloudFront function
- Rewriting Logic
We apply a simple rule:
If the path starts with / and doesn't contain a . (dot), then it's not a file request — it’s most likely a page route like /home or /blog.
So instead of looking for /home on S3 (which doesn’t exist), we rewrite the request to serve /index.html.
function handler(event) {
var request = event.request;
var uri = request.uri;
if (uri.startsWith("/") && !uri.includes(".")) {
request.uri = "/index.html";
}
return request;
}
- **Benefits:
- **Serverless architecture
- Fewer layers to load the first content for the client
- Global availability with low latency
- Low cost compared to server-side hosting
AWS Infrastructure with Terraform
- **S3 Bucket Setup
- S3 Bucket Creation**
- Block public access, we need to not access without CloudFront
- Server-Side Encryption. This enforces encryption at rest for all objects stored in the bucket.
[embed]
Before CloudFront distribution creation we need CloudFront function and CloudFront Origin Access Control (OAC)
- **CloudFront Function
- **Save file the above mentioned single_page_application_handler.js
- Create CloudFront function
[embed]
- CloudFront Origin Access Control (OAC)
OAC provides a secure way to access S3 origins to CloudFront
[embed]
Now everything is ready for CloudFront
- CloudFront Distribution
[embed]
At this moment CloudFront does not have access to s3 files, we have to add bucket policy
- S3 Bucket Policy
[embed]
AWS infrastructure is done — now it’s time to create the React application and upload the built files to the S3 bucket.
npx create-react-app spa-example
cd spa-example
npm install
npm run build
This will generate a production-ready build of your app in the build/ directory.
We can upload files to s3 which client can render after visit our site
aws s3 sync build/ s3://single-page-application/
Your SPA is now hosted on S3 and delivered globally through CloudFront, with proper support for client-side routing using a lightweight CloudFront Function.
You can view the full source code and infrastructure setup in our GitHub project: 🔗 GitHub Repo — SPA Hosting with S3 + CloudFront
🔗 Useful Links
We hope this guide saved you some time or gave you ideas for improving your setup.
메타데이터
- post_id
- 77a9d69e9ea5
- slug
- how-to-host-a-single-page-application-spa-on-aws-s3-and-serve-it-via-cloudfront-77a9d69e9ea5
- url
- https://medium.com/@mategogiberidze_14538/how-to-host-a-single-page-application-spa-on-aws-s3-and-serve-it-via-cloudfront-77a9d69e9ea5
- canonical_url
- https://medium.com/@mategogiberidze_14538/how-to-host-a-single-page-application-spa-on-aws-s3-and-serve-it-via-cloudfront-77a9d69e9ea5
- author_url
- https://medium.com/@mategogiberidze_14538
- status
- ok
- fetched_at
- 2026-07-10 00:10:16