How to Host a Static Resume Website on AWS S3 with Custom Domain & Visitor Counter (Step-by-Step)


What You'll Learn:
Hosting a static website using AWS S3
Connecting a custom domain via Route 53
Adding a visitor counter with Lambda + DynamoDB
Full DevOps-style setup with minimal cost
Prerequisites:
AWS Free Tier account
Basic HTML understanding
A registered domain (e.g., Namecheap, GoDaddy)
Key AWS Services Used:
S3: to store and serve your resume
Lambda: to run code that counts visitors
DynamoDB: to store the counter data
API Gateway: to expose your Lambda function
Route 53: to connect your custom domain to the setup
🧾 Step 1: Create Your Resume Page (index.html)
Here’s a simple HTML file:
<!-- index.html --> <!DOCTYPE html> <html> <head> <title>Sai Krishna | Resume</title> </head> <body> <h1>Hello, I’m Sai Krishna</h1> <p>Aspiring DevOps Engineer</p> <p>Visitor Count: <span id="count">Loading...</span></p> <script> fetch('https://your-api-endpoint.amazonaws.com/prod') .then(response => response.json()) .then(data => document.getElementById('count').textContent = data.count); </script> </body> </html>
🧠 Explanation: This script fetches the visitor count from your AWS API and displays it.
📂 Step 2: Host the Website on AWS S3
Go to S3 > Create Bucket
Use your domain name as bucket name (e.g.,
saikrishnaresu.com
)Uncheck “Block all public access”
Enable Static Website Hosting
Upload
index.html
and set it as default root document
🌐 Step 3: Connect Domain via Route 53
Go to Route 53 > Hosted Zones > Create
Enter your domain (e.g.,
yourdomain.com
)AWS gives NS (nameserver) records. Update your domain provider to use these.
Add a new Record (A):
Type: A
Alias: Yes
Target: Your S3 static site endpoint
🧠 Note: DNS changes may take up to 24 hours.
📊 Step 4: Add a Visitor Counter
1. Create DynamoDB Table
Table name:
visitorCount
Partition key:
id
(String)Add one item manually:
{ "id": "homepage", "count": 0 }
2. Create Lambda Function
Use this code:
const AWS = require("aws-sdk");
const docClient = new AWS.DynamoDB.DocumentClient();
exports.handler = async (event) => {
const params = {
TableName: "visitorCount",
Key: { id: "homepage" },
UpdateExpression: "SET #count = if_not_exists(#count, :start) + :incr",
ExpressionAttributeNames: { "#count": "count" },
ExpressionAttributeValues: { ":start": 0, :incr: 1 },
ReturnValues: "UPDATED_NEW"
};
const result = await docClient.update(params).promise();
return {
statusCode: 200,
headers: { "Access-Control-Allow-Origin": "*" },
body: JSON.stringify({ count: result.Attributes.count }),
};
};
🧠 Explanation: This function updates the
count
for IDhomepage
and returns the updated count.
3. Expose Lambda with API Gateway
Create an HTTP API
Link it to your Lambda
Enable CORS
Deploy it → copy your public API endpoint URL
Update your index.html
to use this API URL.
✅ Step 5: Test the Setup
Visit your domain (
https://yourdomain.com
)You should see your resume and the visitor count increasing on every refresh
💰 Cost Breakdown (Free Tier)
Service | Usage | Cost |
S3 | Static Hosting | Free < 5GB |
Lambda | 1M requests/month | Free |
DynamoDB | 25GB/month, 25 RCU/WCU | Free |
Route 53 | Domain + Hosted Zone | ~$0.50/month |
💡 Bonus Tips
Add Google Analytics for traffic monitoring
Use GitHub Actions to auto-deploy your resume site
Customize with Tailwind CSS for styling
🔗 My Setup
GitHub Repo: Sai-krishna-Resu
Live Site: (Add your URL here once hosted)
🎯 Final Thoughts
This project helped me not only learn DevOps basics but also gave me something real to show on my resume and LinkedIn. If you’re switching careers or learning DevOps — try building and posting something like this.
If you found this useful, consider giving a 🌟 to my GitHub repo or connecting with me on LinkedIn.
Happy deploying 🚀
Subscribe to my newsletter
Read articles from Sai Krishna Resu directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
