Hosting a single page application or website on S3

09 Mar, 2022
Xebia Background Header Wave

In this blog post I will walk you through how to configure a single page application or website. In a previous blog Best practices for S3 web hosting and explaining why. Tibor Hercz explained the best practices for hosting a static website on S3.

As Tibor explained, there are some downsides on using a Origin Access Identity (OAI). But in some Single Page Applications (SPA) you will not experience this downside.

What is a single page application?

A single page application loads a single web document. Based upon your interaction with this page the content is updated.
The pages are rendered on your web browser. And more API calls are performed to fetch extra input. Due to this fact an SPA can be fast!

You can use the framework of your choice: angular, reactjs, vue, etc, etc.

Setting up the infrastructure

For simplicity, I am providing CloudFormation snippets.

First we will need an S3 bucket to host the application in. We need an OAI. And we need to grant it access yo the bucket:

    Type: AWS::S3::Bucket
      AccessControl: Private

    Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
        Comment: Allows CloudFront to reach the bucket

    Type: AWS::S3::BucketPolicy
      Bucket: !Ref MyBucket
        Version: "2012-10-17"
          - Action:
              - s3:GetObject*
              - s3:GetBucket*
              - s3:List*
            Effect: Allow
              CanonicalUser: !GetAtt MyOriginAccessIdentity.S3CanonicalUserId
              - !GetAtt MyBucket.Arn
              - !Sub ${MyBucket.Arn}/*

Next we will need the CloudFront distribution:

    Type: AWS::CloudFront::Distribution
          - ErrorCode: 404
            ResponseCode: 200
            ResponsePagePath: /index.html
            - GET
            - HEAD
            - GET
            - HEAD
          Compress: true
              Forward: none
            QueryString: false
          TargetOriginId: origin
          ViewerProtocolPolicy: redirect-to-https
        DefaultRootObject: index.html
        Enabled: true
        HttpVersion: http2
        IPV6Enabled: true
          - ConnectionAttempts: 3
            ConnectionTimeout: 10
            DomainName: !GetAtt MyBucket.RegionalDomainName
            Id: origin
                  - ""
                  - - origin-access-identity/cloudfront/
                    - Ref: MyOriginAccessIdentity

Once you have set up the infrastructure. You need to build your SPA. And upload the build to the S3 bucket.
My assumption here is that you created an app with various routes/paths.

How does it work?

When you navigate to the hostname of the created CloudFront distribution. The distribution will fall back on the index.html file. This is because we have set the DefaultRootObject to index.html.
When you navigate in the application it looks like the browser is changing paths. But in fact it is only updating the address in the address bar.

Let say you created a /blog route. You navigate to this route. And you do a hard refresh! You expect to get a 404 Not Found error because there is no folder called blog.
But because we configured a CustomErrorResponses. That will redirect all 404 errors to the index.html file with a 200 response code.

This will make sure that the Single Page Application gets loaded again. It will see the location in the address bar and renders the correct content.

This does mean that you will need to handle unknown routes in your application.


When you want to host a Single Page Application you can use CloudFront with private buckets. You will get all the benefits of CloudFront while keeping the bucket private.

Joris Conijn
Joris has been working with the AWS cloud since 2009 and focussing on building event driven architectures. While working with the cloud from (almost) the start he has seen most of the services being launched. Joris strongly believes in automation and infrastructure as code and is open to learn new things and experiment with them, because that is the way to learn and grow. In his spare time he enjoys running and runs a small micro brewery from his home.

Get in touch with us to learn more about the subject and related solutions

Explore related posts