cloud resume challenge
How It's Built
A full-stack cloud project built on Azure. Serverless backend, CI/CD pipelines, infrastructure as code, and a live visitor counter. Here is how all the pieces connect.
HTML / CSS / JS
Static site hosted in Azure Blob Storage with static website hosting enabled.
Azure Front Door
HTTPS, custom domain routing and global edge delivery to the blob storage origin.
Azure Functions
Python HTTP trigger on Flex Consumption plan. Serverless visitor counter API with Cosmos DB input and output bindings.
Cosmos DB
NoSQL document database storing the visitor counter item. Bindings handle all read and write operations automatically.
ARM Templates
Infrastructure as code defining all backend Azure resources. Reproducible and version controlled in GitHub.
GitHub Actions
Separate pipelines for frontend and backend with path filtering. Auto deploys on every push to main.
Azure DevOps Pipelines
Replicated all GitHub Actions pipelines in Azure DevOps with Dev and Production environments, approval gates and service connections. Added for enterprise deployment experience.
// architecture diagram - Created by Lewis Williams
// challenge completed
01
Certification
AZ-104 Microsoft Azure Administrator Associate (Renewed 2025) and SC-300 Microsoft Identity and Access Administrator Associate (2025).
02
Static Website
CV written in HTML and CSS, hosted as a static website in Azure Blob Storage with the $web container serving files publicly.
03
HTTPS and Custom Domain
Azure Front Door provides HTTPS termination and custom domain routing. DNS points to the Front Door endpoint which forwards traffic to the blob storage origin.
04
Visitor Counter — JavaScript
Async fetch call to the Azure Function API on page load. localStorage caches the last known count to mask cold start delays. Error handling ensures the counter never shows a broken state.
05
Cosmos DB
NoSQL document database storing a single counter document with id 1. The input binding fetches the document before the function runs and the output binding writes it back after. No manual connection code required.
06
Azure Functions API — Python
HTTP triggered Python function on Flex Consumption plan. Decorator pattern wires up the HTTP trigger, Cosmos DB input binding and output binding. CORS headers lock the API to trusted domains only.
07
Infrastructure as Code
ARM template defines the Function App, Cosmos DB account, database and container, Storage Account and App Service Plan. The Cosmos DB connection string is fetched dynamically at deploy time and never stored in the template or any pipeline variable.
08
Source Control
Separate GitHub repositories for frontend and backend. All credentials stored as GitHub Secrets and Azure Environment Variables. No secrets ever committed to source control.
09
CI/CD — Backend
Two separate GitHub Actions workflows with path filtering. The ARM template pipeline triggers only when the infrastructure file changes. The Python code pipeline triggers only when function code changes. Both use the Flex Consumption specific deployment approach via SCM Basic Auth and publish profile.
10
CI/CD — Frontend
GitHub Actions uploads static files to Azure Blob Storage on every push to main using the Azure CLI upload-batch command. Service principal authentication via GitHub Secrets. No manual uploads to the portal required.
11
Python Tests — pytest
Unit tests written using pytest covering core counter logic — increment behaviour, integer validation and JSON response structure. Tests run as Stage 0 in both the GitHub Actions and Azure DevOps pipelines. If any test fails the pipeline stops and nothing deploys.
12
Azure DevOps Pipelines
All GitHub Actions pipelines replicated in Azure DevOps — frontend, backend code and ARM infrastructure. The backend code pipeline introduced a two stage deployment not present in GitHub Actions: code deploys automatically to the Development environment first, then pauses at an approval gate before releasing to Production. This keeps both environments in sync and ensures production only receives code that has already been validated in Development.
13
Blog Post
A write up of the key learnings, architectural decisions and challenges encountered throughout the project. Published to document the journey from initial setup through to a fully automated cloud deployment on Azure.
// future development
01
Cypress End to End Tests
Introduce Cypress to test the frontend in a real browser environment. Tests would verify the visitor counter displays on page load, the API call fires correctly and the counter value updates dynamically. These would run in the CI pipeline before any frontend deployment.
02
Migrate DNS to Cloudflare
Replace Azure Front Door with Cloudflare for DNS, HTTPS and CDN. Cloudflare provides the same functionality at no cost, reducing monthly Azure spend while maintaining custom domain support, global edge caching and DDoS protection.
03
Azure API Management
Introduce Azure API Management as a gateway in front of the Azure Function. This would remove the function key from the JavaScript entirely, implement proper rate limiting, provide a consistent API endpoint independent of the underlying function URL and add enterprise grade access control.