# Deploying Your Frontend with AWS S3 and CloudFront: A Step-by-Step Guide.

Developing an aesthetically pleasing frontend that attracts a significant number of users is the initial step in the development process. Equally important is ensuring that it is accessible, allowing users to enjoy the application fully.

There are many platforms available for deploying applications, such as AWS, Azure, and GCP. Each platform comes with its own set of advantages, disadvantages, and learning curve. For this blog post, I'll focus on AWS.

In particular, I'll be demonstrating how to deploy a React application using AWS S3 (Simple Storage Service) and AWS CloudFront.

If you would like to follow along with this blog, ensure that you build your React project and keep it handy. If you are not familiar with creating a build for React, simply use the commands below in your React project.

```bash
npm run build
# or
yarn build
# or
pnpm build
```

If you don't have a React project, don't worry—I've got you covered. You can pull the repository I'm demonstrating in this blog.

```bash
#clone the repo
git clone https://github.com/giripatel/deployment-frontend.git
#point your terminal
cd deployment-frontend
```

Before diving into the process, let's first understand what **Object Storage** and **CDN** are.

### Object Storage

An **Object Storage** is a type of data storage architecture designed to manage and store data as objects, rather than as files in a hierarchical file system or as blocks in a block storage system. Object storage is often used in cloud computing environments and is particularly suited for storing large amounts of unstructured data, such as images, videos, documents, backups, and log files.

### CDN (Content Delivery Network)

A content delivery network (CDN) is **a geographically distributed group of servers that caches content close to end users**. A CDN allows for the quick transfer of assets needed for loading Internet content, including HTML pages, JavaScript files, stylesheets, images, and videos.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Each step includes a screenshot, which may make the blog appear longer and more image-heavy.</div>
</div>

## Deployment Process

1. Object Store Setup
    
2. CDN Configuration
    

### Object Store Setup

1. Log in to your AWS account.
    
2. Search for 'S3' in the search box and select it from the results.
    
3. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727009451026/a228be7d-60e7-418c-ac76-b2d031d94f3a.png align="center")
    
    Click on ‘Create bucket’.
    
4. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727009600720/24fde38f-e2b7-4c9e-810e-18eda1d27ba0.png align="center")
    
    Select 'General Purpose' and provide a name for the bucket.
    
5. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727009812040/b462285c-9130-4516-9a21-e251af9bbd61.png align="center")
    
    Scroll to the bottom and click ‘Create Bucket’.
    
6. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727009887081/6788c55e-7934-4aef-8b9a-ea441c4ac696.png align="center")
    
    Choose the zone closest to you to ensure low latency.
    
7. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727010295706/edb94c57-649d-4f32-85f6-4d7ea429af48.png align="center")
    
    Select the newly created bucket to proceed with further configurations.
    
8. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727010684772/5a758e05-49ac-4728-b1a5-38e9e22c41b7.png align="center")
    
    You will be redirected to the Upload page. Make sure to have your build folder ready.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727011947435/6837c14b-943c-49f4-9028-b23257a3d780.png align="center")
    
9. Drag and drop the build you created earlier in the blog. Alternatively, you can push the build to S3 programmatically. AWS provides an S3 package that simplifies this process.
    
10. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727010748093/a3dd4628-d5a1-45c2-817b-d60eb6b4c740.png align="center")
    
    Scroll to the bottom of the page and click Upload.
    
11. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733655457103/982908ca-85d9-4ece-8bad-6fa738d0e850.png align="right")
    

### CloudFront Setup

1. Type 'CloudFront' in the search box and select the highlighted option shown in the screenshot.
    
2. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727010865331/bff96955-b9d0-4843-b40f-f3d562183bb4.png align="center")
    
    Click on ‘Create a CloudFront distribution’.
    
3. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727010945822/558bdecb-921b-4bb2-8cb6-867718ffd0ce.png align="center")
    
    Select the recently created S3 bucket in the 'Origin Domain' field.
    
4. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727011027449/597f5344-3a94-4842-9a48-55e342f2658a.png align="center")
    
    Choose 'Origin Access Control Settings,' then click on 'Create New OAC.'
    
    ### What is OAC?
    
    Origin Access Control (OAC) is a feature in CloudFront that allows you to restrict direct access to content stored in your origin, such as an Amazon S3 bucket or a web server. This ensures that users can only access the content through the CDN distribution, preventing direct access via the origin URL.
    
5. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727011179654/dc2be1ba-22a9-4e12-b01a-4c718784a0eb.png align="center")
    
    Select the S3 bucket you created earlier, if it is not already selected. Choose 'Sign Requests' and click 'Create'.
    
6. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727011236222/8f0e1891-b0d0-40d8-aff3-4b36f3c80975.png align="center")
    
    Scroll down a bit and choose ‘Enable security protections’.
    
7. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727011338241/88bc9422-b2aa-4704-8e17-39fd8d0d7eea.png align="center")
    
    Type 'index.html' in the 'Default Root Object' field. This file will be returned to users who visit the website at the '/' path.
    
8. Click on “Create distribution” to complete the creation of CloudFront.
    
9. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727011535801/1cf8c191-0866-4977-8e54-59ee22ddc868.png align="center")
    
    Click on 'Copy Policy' in the third popup. This will copy a policy to be used for S3 bucket permissions. Make sure to keep it safe and easily accessible.
    
10. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733640195112/b6253427-7240-4305-b89e-1b6eef13169f.png align="right")
    
11. The CloudFront distribution has been successfully created. The 'Distribution Domain Name' is the URL used to access the website you have created.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733643075359/77788fcf-1c41-42ea-aff0-31e8ac3e67f5.png align="center")
    
12. If you attempt to access the website, the browser will respond as shown below.
    
13. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733642105659/9b72c25a-4b54-41c0-abf0-ffcb429b0b30.png align="center")
    
    To resolve this, open the S3 bucket configuration mentioned in the above “Object Store Setup” (Step 7) and select 'Permissions.'
    
14. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727012488211/3255420a-e3fc-4e08-8bcf-3dceb69e14e4.png align="center")
    
    Click on 'Edit.' This will open a text area where you can paste the policy copied in the previous step.
    
15. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733640573912/ec09055a-c3b7-401f-adc7-91483bbd46f1.png align="center")
    
    Paste the Policy in the text area and click ‘Save’.
    
16. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733640440217/b4b26551-7b62-4a07-b236-a8b6b80d4866.png align="center")
    
    Try to access the same URL that we tried before, You should now be able to access the webpage.
    
    Congratulations 🎉 we are almost there.
    
17. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727012395946/973ba30b-69cd-45ec-a940-0ddc29e550a4.png align="center")
    
    Now, try accessing another page of your application.
    
    If you are following the same React project used in this blog post, navigate to `<Your URL>/info` in your browser.
    
    If you encounter the same error as shown below, we'll need to make some changes to the CloudFront configurations.
    
18. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733642552888/973528b4-6522-4d9d-862b-ea670ca9e185.png align="center")
    
    Open the CloudFront distribution and click on ‘Error pages’.
    
19. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733642941334/75c85293-ee10-4293-b04e-0372c9d7c8c1.png align="center")
    
    Select the HTTP error code as ‘403: Forbidden’ and choose the ‘Customize error response’ as ‘Yes’.
    
    In the ‘Response page path’ type ‘/index.html’ and the response code as ‘200 OK’.
    
    The reason for the error is that CloudFront is attempting to locate the **'/info'** file in S3, which does not exist.
    
    To make sure all requests are routed to ‘index.html’ we have to configure it in ‘Error pages’.
    
20. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727011824541/57f81871-83e4-4791-8f7f-f16cc8b6c821.png align="center")
    
    If you try accessing the route or page (in my case, **'/info'**) in the URL, you'll see the response below. This confirms that we are successfully redirecting all requests to **'/index.html'**.
    

* ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733642447068/20b2fed9-9966-449e-9c82-ed0eaffa8539.png align="center")
    

![](https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExbmpzbXRienlocHZsNGp5MDk1NHJhemo2Mzg2cXk0bmQ1ZG5zOTAxOSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/4HBrbkrFh7Lla1JFwF/giphy.gif align="center")

**What more can you do?**

* Add a custom domain.
