Static websites with S3 and CloudFront with default root object for multiple subdirectories

TL;DR

You can use url-rewrite-single-page-apps CloudFront function to append index.html to the end of URLs that don't include a filename or extension. This is particularly useful for single page applications or statically-generated websites using frameworks like 11ty, Gatsby, or Hugo.



To understand this issue we must first understand the concept of hosting static html sites on S3. If we want to use S3 as a static site after enabling Static website hosting you specify an index document. Usually this is the index.html file. When you specify this document, it applies for all subdirectories in your website structure.

So if you have your S3 website: http://your-static-html-site.s3-website.us-east-2.amazonaws.com, the default page will be index.html in the root.

Now if we want to use CloudFront, we also need to specify a default root object and usually set it to index.html. However this time, the default root object setting works differently as it applies only for the root directory.

To learn more about this you can visit the relevant AWS CloudFront whitepaper

Basically, for our same example abouts the cats website, if we create a CloudFront distribution https://x11123abcddfg8.cloudfront.net/ and set the default root object to index.html we can observe the following behavior:

To fix this formerly we had to implement a Lambda function and use the Lambda@Edge functionality to append index.html to our pages.

CloudFront Functions

The new approach is to use the newly introduced CloudFront Functions to append index.html to the end of URLs that don't include a filename or extension.

You can use url-rewrite-single-page-apps for this and is particularly useful for single page applications or statically-generated websites using frameworks like 11ty, Gatsby, or Hugo.