I came across The Cloud Resume Challenge by Forrest Brazeal while studying for my AWS CCP exam, and without much thought, I added the website to my bookmarks. I was certain that at some point, I would take on the challenge, as it seemed like a great opportunity to gain hands-on experience with AWS. And… I did. After passing my exam, I started working on the project.
Getting started
At the very beginning, I had to set up my AWS personal development environment to ensure that my account (and my wallet!) was properly protected. To do so, I decided to use AWS Organizations. I created a "root" AWS account and set up an AWS Organization with an Organizational Unit (OU) inside it. Under the OU, a new AWS account was created, and this was the account used to create any resources related to the project.
Finally, I set up SSO (Single Sign-On) in the "root" account to log into the "project" account. This was done via AWS IAM Identity Center. After spending some time browsing the internet to learn how to do it and what I was actually doing, it worked, and I was able to log in to IAM Identity Center via the CLI.
Frontend
At this stage of the project, I used a dummy HTML file, as I planned to build and style the website at the end of the challenge. I already had some experience with creating websites, so this part wasn’t new to me. For styling, I used Tailwind CSS instead of the "vanilla" CSS suggested in the challenge.
After my HTML skeleton was ready, I uploaded it to an S3 bucket as a static website. Then, I created a distribution in Amazon CloudFront, which the S3 bucket was configured to serve through, and connected it to an external domain registrar (Cloudflare). This gave me some trouble with AWS Certificate Manager during DNS validation, but a bit of Googling saved the day, and everything was ready - my website was accessible via my custom domain name and was using HTTPS for security.
Last but not least, I decided to create a GitHub repository for the project right from the beginning, so it would be easier to track changes along the way.
Backend
To track the number of visitors to my website, I built a simple backend using AWS services. I started by creating a DynamoDB table to store the visitor count. Then, I wrote a Python-based Lambda function that increments and retrieves the count from the database. This function was triggered via an API Gateway configured as a REST API.
To make the backend accessible from the frontend, I deployed the Lambda function behind the API Gateway endpoint and enabled CORS. I also added basic validation and error handling to ensure the function responds reliably.
Creating a DynamoDB table was pretty straightforward. I already had some experience writing Python scripts, so the biggest challenge was properly configuring the API Gateway - making sure all the necessary methods were defined and that the Lambda function had permission to invoke the API. However, it wasn’t anything that would make me lose sleep over it.
Integration
Now it was time to tie the frontend and backend together and allow them to communicate. The first step was to write a simple JavaScript script that would make an API call to the backend via API Gateway, retrieve the visitor count, and display it on the website. I had to refresh my memory a bit about async functions in JavaScript, but overall, everything came together smoothly.
This part also involved writing smoke tests for the API. To do that, I chose Cypress. I hadn’t had the opportunity to create automated tests before, so this was completely new to me. After some Googling, I was ready to start. It turned out that Cypress is very user-friendly and only needs to know what output your URL should return in response to a given input.
I managed to prepare the following tests:
- Check if the counter is correctly incremented.
- Check if the API returns a 400 error when an invalid request body is passed.
- Check if the API returns a 405 error when an unsupported HTTP method is used.
- (Additional test, not part of cypress.config.js) Check if the DynamoDB item is initialized correctly. This one was created for experimental/learning purposes. To run it properly, the item with the count must be deleted first. In my Lambda function, I added a snippet that checks whether such an item exists in the database - and if not, it initializes it.
Automation/CI
Up until this point, every AWS resource had been created manually through the AWS Console - but here comes the magic word: automation.
Infrastructure as Code was definitely one of the most challenging parts of the entire project. I decided to use Terraform to manage it, as learning it had been on my to-do list for a while. I had a hard time structuring my .tf files - I wanted the setup to be simple, yet “professional”. In the end, I decided to organize my folder structure into modules, and I think it was a good call. Navigating through them is straightforward and intuitive.
After a couple of hours of Googling, reading documentation, and experimenting, I was finally able to wrap my head around the concept and produce the final version of my Infrastructure as Code setup.
I tried to follow best practices from the very beginning, writing the code to be as reusable as possible by using variables wherever I could. One of the most challenging parts was programmatically creating the required policies to allow the resources to communicate with each other.
This part also involved setting up CI/CD for both the backend and frontend. I decided to do this within a single repository (contrary to what Forrest suggests), using GitHub Actions. It was fairly easy to implement using a push trigger with path-based configuration.
An important part of this stage was setting up a remote backend using a new S3 bucket, which Terraform uses to store its state files.
Final thoughts
Completing the Cloud Resume Challenge was both a technical and personal milestone. It pushed me to explore cloud infrastructure, CI/CD automation and infrastructure as code - all within a real-world, end-to-end project.
I learned a ton, made mistakes, and came out more confident in my DevOps and cloud engineering skills.
If you're thinking about doing the challenge yourself - go for it. It’s one of the most rewarding ways to level up your cloud skills.
Top comments (0)