cloudwithshad
๐Ÿ“Š
GROUP PROJECT ยท 1 WEEK ยท MINI-AWARDS

MarketPulse โ€” Customer Feedback for SMEs

A web dashboard where Ghanaian small business owners (chop bars, salons, fintech startups, tailors) get real-time AI insights into what customers actually think. Built in groups. Deployed on EC2. This is the one you could sell after the bootcamp.

3-4
PER TEAM
1 week
TO BUILD
5 services
AWS USED
5
AWARDS
1
The vision โ€” what you're building
10 min

Imagine Auntie Akos at her chop bar in Osu. She sells the best banku in the neighbourhood. But she has no idea what customers actually think โ€” they smile and pay, then go on Twitter and complain. By the time she hears about a bad experience, the customer is gone.

MarketPulse changes this. A QR code on every table. Customers scan, type 30 seconds of feedback, hit submit. Auntie Akos opens her phone:

  • ๐Ÿ“Š Sentiment dashboard โ€” 73% positive this week, up from 61% last week
  • ๐Ÿท๏ธ Top complaints โ€” "slow service" mentioned 12 times, "cold food" mentioned 8 times
  • ๐Ÿšจ Real-time alerts โ€” if someone leaves a strongly negative review, she gets an SMS or email immediately
  • ๐Ÿ“ Recent reviews โ€” scroll through with sentiment colour-coding
๐Ÿ’ฐ Why this is special

This isn't just a portfolio piece โ€” it's a real product you could sell. Local SMEs across West Africa would pay โ‚ต100-300/month for this. Several bootcamp graduates have launched startups from exactly this kind of project. You won't just impress employers โ€” you might walk away with a business.

2
Team roles โ€” who does what
15 min
1. Frontend Lead
"The Product Designer"
  • Owns the customer feedback form (must look beautiful on mobile)
  • Owns the owner-side dashboard (charts, filters, lists)
  • Picks the Streamlit theme + adds custom CSS
  • Designs the QR code page customers see
2. Backend Lead
"The Pipeline Builder"
  • Wires Comprehend (sentiment + entities)
  • Designs DynamoDB schema + indexes
  • Builds the SNS alert flow for negatives
  • Owns query performance for the dashboard
3. AWS Engineer
"The Cloud Operator"
  • Provisions EC2 + IAM role + security groups
  • Sets up CloudWatch monitoring
  • Handles deployment + restart policies
  • Owns cost monitoring (keep it free-tier)
4. Product & Demo Lead
"The Storyteller"
  • Talks to 2-3 real Accra businesses for use case research
  • Writes the marketing copy on the landing page
  • Generates the QR codes + business onboarding flow
  • Owns the demo script + slide deck
Founder mindset

Treat this like you're co-founders of an actual startup, not 4 students doing homework. Have a Slack/WhatsApp channel just for the team. Daily 10-minute standups. A shared Notion/Google Doc with the roadmap. Teams that operate like startups tend to win.

3
Architecture โ€” two apps, one backend
15 min

MarketPulse has TWO front-ends: one for the customer (the feedback form), one for the owner (the dashboard). Both call the same backend.

Customer scans QR EC2: Streamlit /?role=customer feedback form Owner logs in EC2: Streamlit /?role=owner dashboard ๐Ÿง  Comprehend sentiment + entities ๐Ÿ’พ DynamoDB feedback table aggregated stats if NEGATIVE ๐Ÿšจ SNS SMS / Email alert
Customers submit via QR โ†’ Comprehend analyzes โ†’ DynamoDB stores โ†’ Owner sees dashboard. Negatives also trigger SNS alerts in real time.
ComponentWhat it does
EC2 t2.microSingle Streamlit app with two routes (customer form + owner dashboard)
ComprehendDetects sentiment + entities + key phrases on every submission
DynamoDBStores: feedback_id, business_id, message, sentiment, entities, timestamp
SNSSends an email/SMS to the owner if feedback is NEGATIVE with high confidence
CloudWatchLogs from the app + metrics on Comprehend calls
4
Build it locally (two-page Streamlit app)
3 hours

Set up the project:

mkdir marketpulse cd marketpulse python -m venv venv source venv/bin/activate pip install streamlit boto3 pandas plotly qrcode[pil]

Streamlit can serve multiple pages via the pages/ folder. Project structure:

marketpulse/ โ”œโ”€โ”€ app.py # landing page / role picker โ”œโ”€โ”€ pages/ โ”‚ โ”œโ”€โ”€ 1_๐Ÿ“_Customer_Form.py # customer side โ”‚ โ””โ”€โ”€ 2_๐Ÿ“Š_Owner_Dashboard.py # owner side โ”œโ”€โ”€ aws_helpers.py # boto3 wrappers โ””โ”€โ”€ requirements.txt

The customer form is simple โ€” get name, rating, message, business name (for multi-tenancy):

# pages/1_๐Ÿ“_Customer_Form.py import streamlit as st from aws_helpers import save_feedback st.set_page_config(page_title="Share your feedback", page_icon="๐Ÿ“") st.title("๐Ÿ“ Tell us how we did") st.markdown("_Your feedback helps small businesses grow._") with st.form("feedback"): business = st.text_input("Business name", placeholder="e.g., Auntie Akos's Chop Bar") name = st.text_input("Your name (optional)") rating = st.slider("Rating", 1, 5, 3) message = st.text_area("Tell us more", height=130, placeholder="What did you love? What could be better?") submitted = st.form_submit_button("Send feedback โœจ", use_container_width=True) if submitted: if not message: st.error("Please share what you thought!") else: with st.spinner("Saving..."): result = save_feedback(business, name, rating, message) st.success(f"๐ŸŽ‰ Thanks! Your sentiment was: {result['sentiment']}") st.balloons()

The owner dashboard pulls everything from DynamoDB and renders charts using Plotly:

# pages/2_๐Ÿ“Š_Owner_Dashboard.py โ€” overview only import streamlit as st import plotly.express as px import pandas as pd from aws_helpers import get_all_feedback st.set_page_config(page_title="MarketPulse Dashboard", page_icon="๐Ÿ“Š", layout="wide") st.title("๐Ÿ“Š MarketPulse Dashboard") business = st.text_input("Your business name", value="Auntie Akos's Chop Bar") if business: data = get_all_feedback(business) df = pd.DataFrame(data) if df.empty: st.info("No feedback yet. Share your QR code!") else: col1, col2, col3, col4 = st.columns(4) col1.metric("Total feedback", len(df)) col2.metric("Avg rating", f"{df['rating'].mean():.1f} โญ") positive_pct = (df['sentiment'] == 'POSITIVE').mean() * 100 col3.metric("Positive %", f"{positive_pct:.0f}%") col4.metric("This week", len(df[df['timestamp'] > (pd.Timestamp.now() - pd.Timedelta(days=7))])) st.divider() col_a, col_b = st.columns(2) with col_a: st.subheader("๐Ÿ˜Š Sentiment breakdown") sentiment_counts = df['sentiment'].value_counts().reset_index() fig = px.pie(sentiment_counts, names='sentiment', values='count', color_discrete_map={'POSITIVE': '#2EA043', 'NEGATIVE': '#C62828', 'NEUTRAL': '#64748B'}) st.plotly_chart(fig, use_container_width=True) with col_b: st.subheader("๐Ÿท๏ธ Top entities mentioned") # Flatten entities from all feedback all_entities = [] for e_list in df['entities']: all_entities.extend([e['text'] for e in e_list]) top = pd.Series(all_entities).value_counts().head(10).reset_index() top.columns = ['entity', 'count'] fig2 = px.bar(top, x='count', y='entity', orientation='h') st.plotly_chart(fig2, use_container_width=True) st.divider() st.subheader("๐Ÿ’ฌ Recent feedback") for _, row in df.sort_values('timestamp', ascending=False).head(10).iterrows(): color = {'POSITIVE': '๐ŸŸข', 'NEGATIVE': '๐Ÿ”ด', 'NEUTRAL': 'โšช'}.get(row['sentiment'], 'โšช') st.markdown(f"{color} **{row['name']}** ({row['rating']}โญ) โ€” {row['message']}")

Run it locally with streamlit run app.py and visit http://localhost:8501. You'll see the customer form + dashboard as separate pages in the sidebar.

5
Wire up Comprehend + DynamoDB + SNS
4 hours

The Backend Lead's main work happens here. Create aws_helpers.py:

import boto3 import uuid from datetime import datetime from decimal import Decimal comprehend = boto3.client('comprehend') ddb = boto3.resource('dynamodb') sns = boto3.client('sns') table = ddb.Table('marketpulse-feedback') SNS_TOPIC_ARN = 'arn:aws:sns:us-east-1:YOUR-ACCOUNT-ID:marketpulse-alerts' def save_feedback(business, name, rating, message): """Process + save a single feedback entry.""" # 1. Sentiment analysis s_resp = comprehend.detect_sentiment(Text=message[:5000], LanguageCode='en') sentiment = s_resp['Sentiment'] # 2. Entity extraction e_resp = comprehend.detect_entities(Text=message[:5000], LanguageCode='en') entities = [{'text': e['Text'], 'type': e['Type']} for e in e_resp['Entities'][:10]] # 3. Save to DynamoDB feedback_id = str(uuid.uuid4()) table.put_item(Item={ 'feedback_id': feedback_id, 'business': business, 'name': name or 'Anonymous', 'rating': rating, 'message': message, 'sentiment': sentiment, 'entities': entities, 'timestamp': datetime.utcnow().isoformat() }) # 4. Alert on negatives if sentiment == 'NEGATIVE': sns.publish( TopicArn=SNS_TOPIC_ARN, Subject=f'โš ๏ธ Negative feedback at {business}', Message=f'A customer just left negative feedback:\n\n"{message}"\n\nRating: {rating}/5' ) return {'sentiment': sentiment, 'feedback_id': feedback_id} def get_all_feedback(business): """Fetch all feedback for one business.""" response = table.scan( FilterExpression='business = :b', ExpressionAttributeValues={':b': business} ) items = response.get('Items', []) # Convert Decimal to int/float for charts for item in items: if 'rating' in item: item['rating'] = int(item['rating']) return items

Then in the AWS Console:

  1. DynamoDB table: Create marketpulse-feedback with partition key feedback_id (String). On-demand capacity. Done.
  2. SNS topic: Create marketpulse-alerts. Subscribe your team's email address (and confirm it). Optionally subscribe a phone number for SMS.
  3. IAM role for EC2: Create role with these policies attached:
    • ComprehendFullAccess
    • AmazonDynamoDBFullAccess
    • AmazonSNSFullAccess
    • CloudWatchLogsFullAccess
DynamoDB Scan vs Query

table.scan() reads the WHOLE table every time. Fine for the demo (you'll have ~50 entries). For real production, add a Global Secondary Index on business so you can table.query() for one business's data only. Mention this in your demo โ€” it shows production thinking.

6
Deploy to EC2 (the AWS Engineer's stage)
3 hours

Same EC2 setup as Project 1, but ensure the IAM role attached at launch has the right policies. Process:

  1. Launch EC2 (Amazon Linux 2023, t2.micro, key pair from Week 1)
  2. Security group: SSH 22 (your IP) + HTTP 80 (anywhere) + TCP 8501 (anywhere)
  3. Attach the IAM role you built in Step 5 (Advanced โ†’ IAM instance profile)
  4. SSH in and install:
sudo yum update -y sudo yum install -y git python3-pip pip3 install streamlit boto3 pandas plotly qrcode[pil] git clone https://github.com/YOUR-TEAM/marketpulse.git cd marketpulse streamlit run app.py --server.port 8501 --server.address 0.0.0.0

Visit http://<EC2-IP>:8501 โ€” you should see your app live.

Run it as a systemd service so it survives SSH disconnect (same pattern as Project 1). Once live:

  • Submit some test feedback as a "customer"
  • Switch to the dashboard view as the "owner"
  • Verify the chart populates
  • Submit something deliberately negative ("food was terrible, won't return") and check your email โ€” SNS should fire
7
QR code, polish & what wins awards
3-4 hours

Now the project becomes irresistible. This is where MarketPulse goes from "yet another dashboard" to "I'd actually pay for this".

QR code generator (in the dashboard)

Add a section in the owner dashboard that generates a QR code pointing to http://<your-EC2>:8501/Customer_Form?business=Auntie+Akos:

import qrcode import io def generate_qr(business_name, base_url): from urllib.parse import quote qr_url = f"{base_url}/Customer_Form?business={quote(business_name)}" img = qrcode.make(qr_url) buf = io.BytesIO() img.save(buf, format='PNG') return buf.getvalue(), qr_url # In your dashboard: if st.button("Generate QR code for table tents"): qr_img, qr_url = generate_qr(business, "http://YOUR-EC2-IP:8501") st.image(qr_img, width=280) st.caption(f"Print this. Stick it on tables. Customers scan & submit feedback.") st.download_button("๐Ÿ“ฅ Download QR", qr_img, file_name="qr.png")

Polish checklist

  • Frontend Lead: Add a beautiful "Welcome to [Business]" header on the customer form. Use the business name dynamically.
  • Frontend Lead: Custom Streamlit theme via .streamlit/config.toml โ€” purple-to-cyan gradient feels modern SaaS.
  • Backend Lead: Add a "key phrases" Comprehend call โ†’ show top 5 phrases customers actually use ("slow service", "great food", "friendly staff").
  • Backend Lead: Filter the dashboard by date range (last 7/30/90 days).
  • Product Lead: Onboard 1-2 real Accra businesses for demo day. Their real names + real feedback = 10x credibility.
  • AWS Engineer: Set up daily DynamoDB backups + a CloudWatch dashboard showing app metrics.
The 80/20 of demo wins

Don't add 10 new features. Pick 2 polish improvements and finish them perfectly. A beautifully filtered dashboard with real customer names beats a half-built "AI insights" tab. Judges reward depth over surface area.

8
Demo day โ€” sell the dream
2 hours rehearsal

๐ŸŽฌ Your 5-minute demo flow

  • 00:00 โ€” 00:30 ยท The problem. "Small businesses in Accra serve thousands of customers but never know what they think. Today's feedback options are Google Reviews (slow), Twitter complaints (too late), or asking face-to-face (people lie to be polite)."
  • 00:30 โ€” 01:00 ยท The team + product name. Quick intros + show your branded landing page.
  • 01:00 โ€” 02:30 ยท The customer flow โ€” LIVE. Pull up the QR code on your dashboard. Have someone scan it with their phone (or fake-scan it on a second tab). Submit a positive review. Then submit a negative review. Watch as the SNS email arrives in your inbox in real time. This is the moment that wins.
  • 02:30 โ€” 03:30 ยท The dashboard. Switch to the owner view. Show the sentiment pie chart, top entities, recent reviews. "Auntie Akos now knows in real time what customers think."
  • 03:30 โ€” 04:15 ยท The architecture. Brief mention. "We chose DynamoDB over RDS because feedback is flexible JSON. We use Comprehend for sentiment, SNS for real-time alerts." Show your diagram.
  • 04:15 โ€” 05:00 ยท The business model. "We've spoken to 2 real Osu businesses who said they'd pay โ‚ต150/month for this. There are 50,000+ SMEs in Accra alone." End strong.
The cheat code

Bring a real customer to the demo. Auntie Akos, Mr Mensah, anyone. Have them speak for 30 seconds about why they'd use this. Nobody beats authentic customer voice.

๐Ÿ†
The 5 awards
๐ŸŽจ
Most Polished

Looks and feels like a $50/month SaaS product. Beautiful charts, mobile-perfect customer form, clean dashboard.

๐Ÿ’ก
Most Innovative

Adds something nobody asked for but everyone wants: voice feedback transcription, multi-language, AI-suggested responses.

๐ŸŽค
Best Demo

The pitch that made judges nod. Clear problem statement, live demo that worked perfectly, strong closing.

๐Ÿ“š
Best Documentation

The README, architecture diagram, and setup instructions a hiring manager would clone and run.

โค๏ธ
People's Choice

The cohort's pick. The team they'd want to work with โ€” and the product they'd most likely become a customer of.

๐Ÿ“Š

You're building a real SaaS.

This is the project most likely to turn into your first startup. Several past graduates have launched ventures from exactly this. Build it for one real business in Accra. Win the cohort awards. Then keep building after the bootcamp ends.

Ship it. Sell it. Scale it.