The first steps
Ever since I started exploring cloud computing, I’ve been amazed by its power to transform how we build and deploy applications. When I stumbled upon the Cloud Resume Challenge, I knew it was the perfect opportunity to deepen my skills while creating something tangible for my portfolio. This blog will document my journey as I tackle this challenge, and hopefully, it will inspire others to do the same.
Overview
The Cloud Resume Challenge involves creating a personal resume hosted in the cloud, and I chose to use Azure to bring this project to life. The key services I used are Azure Storage for hosting the static website, Azure Functions for backend logic, and Azure API Management to handle dynamic features.
Progress
Log 1
This weekend has been a whole lot of fun. I've never written a website before. I understand HTML, CSS, and JavaScript and their roles in web development, but I had never had a reason to build a website.
Props to the developers who create websites full-time! I started this challenge by building my website from scratch—everything was manually typed out in VS Code. After learning about HTML and CSS best practices and spending many hours watching YouTube tutorials, I already want to redesign my website from the ground up.
I can see the mistakes I've made so far, but overall, I don’t think the end result is great.
I didn’t use any modern web development tools for the site, mostly relying on Chrome’s "Inspect" element to analyse how certain things are done. Again, this website and all its contents are 100% built from scratch.
Next up: Choosing a Domain Name.
Log 2
I chose the domain name cloudthings.xyz from a registrar and purchased the domain. The first step was to move it to an Azure DNS Zone by pointing the nameservers from the registrar to Azure and changing the default domain for my tenant to cloudthings.xyz. After setting up the DNS Zone, I built the rest of the infrastructure.
First, I created a blob storage account, where I used the static website feature and uploaded my website files to a container. Next, I enabled HTTPS for the website using a CDN endpoint that I created within my blob storage. I added a CNAME record to my DNS Zone but ran into my first issue—cloudthings.xyz wouldn’t resolve, and only www.cloudthings.xyz would work.
I quickly learned that apex domains are not supported unless I purchased a wildcard certificate, which I didn’t want to do.
Next, I created a CosmosDB Table API to store data from my website. One of the challenge requirements was to implement a visitor counter that tracks unique visitors. I decided to take it a step further—my visitor tracker updates based on the number of unique visitors stored in the database, rather than simply incrementing on each page refresh.
I built a JavaScript script that sends data from the browser session to a Python API, which then writes it to CosmosDB using a unique string. The JavaScript also queries CosmosDB to fetch the visitor count and display it on the website. The Python code was deployed in an Azure Function App.
I learned a lot about JavaScript and Python during this phase of the challenge. Additionally, I gained experience with APIs, testing, and tools like Postman, along with further functionality in VS Code.
Some of the issues I encountered were frustrating but solvable. Notable challenges included:
To address security, I added data validation in my Python code and explored options for traffic throttling. I found that API Management within Azure could help, but it comes at an additional cost. Instead, I set the correct IAM access so that only my Function App could communicate with CosmosDB.
Overall, this portion of the challenge took a significant amount of time, but I’m happy with the end result.
Log 3
After building the infrastructure, writing the necessary code, and thoroughly testing everything locally and through repeated deployments from VS Code into Azure, I was ready to wrap up the challenge… or so I thought.
The next step was to set up CI/CD pipelines from GitHub to Azure. This wasn’t too challenging, as Azure Function Apps have a Deployment Center that connects to a GitHub account, selects a repository, and sets up the pipeline. It automatically generates the required .yaml files for the Function App, and all that’s needed is to add the publish profile to GitHub.
The blob storage deployment was a bit more challenging. I had to create an App Registration in Entra ID and manually write a .yaml file for GitHub Actions to deploy files to Azure. I also had to add additional secrets to GitHub.
I ran into an issue where I couldn’t upload files from GitHub to an existing blob storage container. A quick Google search for Az CLI syntax led me to the solution—adding --overwrite true to my command.
Both repositories now contain the necessary files, and I successfully created a test branch, made changes, and pushed them to the main branch, which then deployed to Azure.
The next step was Infrastructure as Code (IaC). I really enjoyed this part and built my Function App and CosmosDB infrastructure using Bicep files in VS Code. I reviewed a lot of GitHub reference code and learned a great deal about structuring .bicep files and their capabilities. I also examined raw JSON outputs from Azure to better understand the configuration.
After finalizing my Bicep templates, I deleted the GUI-built services and tested deploying my infrastructure using Bicep files from VS Code. Everything worked as expected—except for a missing CosmosDB connection string, which had to be manually configured in the Function App.
I then set up billing alerts for the subscription and double-checked IAM permissions.
Final Thoughts
Finishing this challenge has been an incredible experience. I’ve enjoyed the learning process and the skills I’ve gained along the way. I now have several new ideas I want to explore within my Azure tenant to further develop my knowledge. If I were to redo this challenge, I would: