The final project. A real production system you'll show employers. Customers submit feedback through a web form โ AI analyzes it โ you see the dashboard. This combines everything from weeks 1-4 into one portfolio piece.
5
PHASES
3-5 hours
DURATION
FREE
TIER OK
6 services
CHAINED
๐
This is YOUR capstone
The capstone has one rule: it must work end-to-end. How you get there is up to you. We provide the architecture, the success criteria, and the starter code. The implementation details are your portfolio piece. Stuck? Use the hints (๐ก). Beat the lab? Submit a deployed URL.
1
What you're building
A real production system with three parts:
A public web form where anyone can submit feedback (name, email, message)
An AI backend that analyzes every submission for sentiment and named entities
A dashboard showing aggregate stats: sentiment breakdown, top entities, recent submissions
Two front-ends (form + dashboard). One backend pipeline. Everything is serverless.
Why this is a great portfolio piece:
It's a complete app โ frontend, backend, database, AI, all wired together
It uses 6+ AWS services in a real-world pattern
Solo developers can build it in a weekend
It demonstrates the most-demanded skill in cloud: service integration
2
Phase 1 โ The submission form (Frontend)
Build a simple HTML form. Single file, vanilla JS, no frameworks needed. Host it on S3 like Week 1.
1
Create a new S3 bucket named cloudwithshad-capstone-form-<yourname>
The starter is intentionally plain. Customize the design, the colors, the copy โ make it feel like your brand. This is a portfolio piece. Employers notice taste.
3
Phase 2 โ DynamoDB table
1
DynamoDB โ Create table
2
Table name: cloudwithshad-feedback
3
Partition key: feedback_id (String)
4
Defaults: on-demand, no sort key
5
Create table
Items will store: id, name, email, message, sentiment, entities, timestamp.
4
Phase 3 โ The Lambda + IAM role
First, the IAM role. Lambda needs to call Comprehend and write to DynamoDB.
Configure routes: Method = POST, Resource path = /feedback
5
Stage: $default (auto-deploy)
6
Create. Copy the Invoke URL at the top of your API page
7
Add CORS: API โ CORS โ Allow origin: *, Allow methods: POST, OPTIONS, Allow headers: Content-Type
8
Paste the full URL (Invoke URL + /feedback) into your index.html at the API_URL placeholder
9
Re-upload index.html to your S3 form bucket
Hint: testing if your API endpoint works
From your laptop terminal:
curl -X POST https://YOUR-API-URL/feedback -H "Content-Type: application/json" -d '{"name":"Test","email":"a@b.c","message":"Great service!"}'
If you get back {"success": true, "sentiment": "POSITIVE", ...} โ the API works. Check your DynamoDB table for the new item.
Test it live
Open your S3 form URL in a browser. Submit some feedback. Check DynamoDB. You just built a real production AI app. Take a screenshot of the form + the DynamoDB item that appeared.
6
Phase 5 โ Build the admin dashboard
The final piece. A separate webpage (also hosted on S3) that fetches the data and shows aggregate stats.
Two ways to do this:
Easy: Add a GET route to your existing API that scans DynamoDB and returns all feedback. The dashboard calls it.
Harder (better!): Use Amazon Athena to run SQL queries over DynamoDB-exported S3 data. More work, more impressive.
For the bootcamp, go with option 1. Add a second Lambda function:
import boto3
import json
from collections import Counter
from decimal import Decimal
dynamo = boto3.resource('dynamodb')
table = dynamo.Table('cloudwithshad-feedback')
classDecimalEncoder(json.JSONEncoder):
defdefault(self, obj):
ifisinstance(obj, Decimal):
returnfloat(obj)
returnsuper().default(obj)
deflambda_handler(event, context):
# Scan all feedback (fine for small datasets)
response = table.scan()
items = response['Items']
# Aggregate sentiment counts
sentiment_counts = Counter(item['sentiment'] for item in items)
# Top entities
entity_counts = Counter()
for item in items:
for e in item.get('entities', []):
entity_counts[e['text']] += 1
top_entities = entity_counts.most_common(10)
return {
'statusCode': 200,
'headers': {'Access-Control-Allow-Origin': '*'},
'body': json.dumps({
'total': len(items),
'sentiment_breakdown': dict(sentiment_counts),
'top_entities': top_entities,
'recent': sorted(items, key=lambda x: x.get('submitted_at', ''), reverse=True)[:10]
}, cls=DecimalEncoder)
}
Add a new route in API Gateway (GET /stats โ this Lambda), then create a dashboard.html that fetches and renders the data. Get creative with charts โ use Chart.js (one CDN link, beautiful results).
Hint: simple Chart.js dashboard structure
Add <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> to your HTML. Then call your /stats endpoint with fetch(), and render a doughnut chart for sentiment plus a horizontal bar chart for top entities. The Chart.js docs have copy-paste examples for every chart type.
๐ฆ Portfolio submission requirements
This is your capstone deliverable. Submit a single message in the cohort WhatsApp group with:
The S3 URL of your live form (someone in the group will test it!)
The S3 URL of your dashboard
A GitHub repo link with all your HTML, Lambda code, and a README explaining the architecture
One screenshot of the dashboard showing real data after a few submissions
Bonus points for: custom design, a README that's well-written, a deployed CloudFront distribution in front of S3, and a brief architecture diagram.
๐ Make it employer-impressive
Want to really stand out? Try one or more:
SNS notifications: Send yourself an email every time NEGATIVE feedback comes in
Multi-language: Detect language with Comprehend first, then call Translate to convert to English before analysis
Auth: Protect the dashboard behind Cognito so only you can see the data
CI/CD pipeline: Hook up GitHub Actions (like Week 3 Lab 6) so pushes auto-deploy
CloudFront + custom domain: Hook up a real domain name (Route 53 + ACM cert)
Custom Comprehend classifier: Train a model to categorize feedback by topic (billing, support, product, etc.)
7
Clean up (or keep it running!)
This setup is genuinely cheap to keep running. Lambda + API Gateway + S3 + DynamoDB at zero traffic costs basically nothing. Many students choose to leave it up as their portfolio.
If you want to keep it running:
Set a billing alarm at $1 so you'll know if anything spikes
Rotate the IAM keys every 90 days
Add basic auth to the dashboard so it isn't world-readable
If you want to delete everything:
API Gateway โ APIs โ delete the API
Lambda โ delete both functions
DynamoDB โ delete the table
S3 โ empty + delete both buckets (form + dashboard)
IAM โ delete the role
๐
You did it.
You started 4 weeks ago โ possibly never having touched AWS. Today you finished a real production AI application. That is genuinely rare.
Take a screenshot of your live form. Save your GitHub link. Add it to your LinkedIn under "Projects". Apply for cloud roles with confidence โ because you've already built what they're asking about.