Charlie: Week 4: Start Building Your Rating App
You are in good shape on earlier weeks: favs.py, v0-prompt.md, vibe-code-report.md, warmup.py, and TODO.md are in your repo. This week you start your real app in Flask so you own every line of code.
Your v0 prototype (React/Next.js) is a great reference: https://v0.app/chat/movie-and-album-ratings-gHlvwCzKPL5?ref=WBY3CM
Important: v0 can look very polished. Your first Flask version will be simpler on purpose. You are rebuilding the core idea (home, rate, see ratings) with Python. Styling uses Tailwind CSS via CDN -- see Tailwind CSS.
Check In: What Are You Working On?
Open TODO.md. Does it match what you are doing today? If not, add a rough line like "Build my Media Rater Flask app." You will refine this at the end.
Part 1: Essential Project Catch-up
Fill in Known Limitations in vibe-code-report.md
Scroll to ## Known Limitations and add 2-3 honest bullets -- for example:
-
"Ratings do not save yet -- refresh clears them"
-
"No edit screen for old ratings"
-
"No poster images hooked up in Flask yet"
Optional: Your warmup.py may be missing a closing ) on the print line. If the file does not run, fix that when you have time -- it is not required for your Flask path this week.
Part 2: Build Your Flask App
Flask maps URLs to Python functions. Each returns HTML as a string. Use Tailwind classes instead of giant <style> blocks.
Step 1: Create app.py
New File -- app.py. Paste:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return """
<html>
<head>
<meta charset="utf-8">
<title>Media Rater</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="min-h-screen bg-violet-950 text-violet-50">
<div class="mx-auto max-w-2xl px-6 py-12">
<h1 class="text-3xl font-bold text-amber-300">Media Rater</h1>
<p class="mt-2 text-violet-300">By Charlie M.</p>
<p class="mt-6 text-violet-100">Rate movies and albums. Keep notes. Track everything.</p>
<div class="mt-8 flex flex-wrap gap-3">
<a class="rounded-lg bg-amber-400 px-5 py-2 font-semibold text-violet-950 hover:bg-amber-300" href="/rate">Rate Something</a>
<a class="rounded-lg border border-amber-400 px-5 py-2 font-semibold text-amber-200 hover:bg-amber-400/10" href="/ratings">My Ratings</a>
</div>
</div>
</body>
</html>
"""
@app.route("/rate")
def rate():
return """
<html>
<head>
<meta charset="utf-8">
<title>Rate Something</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="min-h-screen bg-violet-950 text-violet-50">
<div class="mx-auto max-w-2xl px-6 py-12">
<h1 class="text-2xl font-bold text-amber-300">Rate Something</h1>
<form class="mt-8 space-y-4">
<div>
<label class="block text-sm font-medium text-amber-200" for="title">Title</label>
<input class="mt-1 w-full rounded-lg border border-violet-700 bg-violet-900 px-3 py-2 text-white placeholder-violet-400 focus:border-amber-400 focus:outline-none" type="text" id="title" name="title" placeholder="e.g. Forrest Gump, After Hours">
</div>
<div>
<label class="block text-sm font-medium text-amber-200" for="media_type">Type</label>
<select class="mt-1 w-full rounded-lg border border-violet-700 bg-violet-900 px-3 py-2 text-white focus:border-amber-400 focus:outline-none" id="media_type" name="media_type">
<option value="movie">Movie</option>
<option value="album">Album</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-amber-200" for="rating">Rating (1-10)</label>
<input class="mt-1 w-full rounded-lg border border-violet-700 bg-violet-900 px-3 py-2 text-white focus:border-amber-400 focus:outline-none" type="number" id="rating" name="rating" min="1" max="10" step="0.5">
</div>
<div>
<label class="block text-sm font-medium text-amber-200" for="notes">Notes</label>
<textarea class="mt-1 min-h-[100px] w-full rounded-lg border border-violet-700 bg-violet-900 px-3 py-2 text-white placeholder-violet-400 focus:border-amber-400 focus:outline-none" id="notes" name="notes" placeholder="What did you think?"></textarea>
</div>
<button class="rounded-lg bg-amber-400 px-6 py-2 font-semibold text-violet-950 hover:bg-amber-300" type="button">Submit Rating (UI only for now)</button>
</form>
<p class="mt-10"><a class="text-amber-300 underline hover:text-amber-200" href="/">← Back to Home</a></p>
</div>
</body>
</html>
"""
@app.route("/ratings")
def ratings():
return """
<html>
<head>
<meta charset="utf-8">
<title>My Ratings</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="min-h-screen bg-violet-950 text-violet-50">
<div class="mx-auto max-w-2xl px-6 py-12">
<h1 class="text-2xl font-bold text-amber-300">My Ratings</h1>
<div class="mt-8 space-y-4">
<div class="rounded-xl border border-violet-700 bg-violet-900/80 p-4">
<h3 class="text-lg font-semibold text-amber-300">Forrest Gump</h3>
<p class="text-xs uppercase tracking-wide text-fuchsia-300">Movie</p>
<p class="mt-2 text-2xl font-bold text-amber-300">8.5 / 10</p>
<p class="mt-2 italic text-violet-200">"Classic. Tom Hanks is goated."</p>
</div>
<div class="rounded-xl border border-violet-700 bg-violet-900/80 p-4">
<h3 class="text-lg font-semibold text-amber-300">After Hours</h3>
<p class="text-xs uppercase tracking-wide text-fuchsia-300">Album</p>
<p class="mt-2 text-2xl font-bold text-amber-300">9 / 10</p>
<p class="mt-2 italic text-violet-200">"The Weeknd at his best."</p>
</div>
<div class="rounded-xl border border-violet-700 bg-violet-900/80 p-4">
<h3 class="text-lg font-semibold text-amber-300">Get Out</h3>
<p class="text-xs uppercase tracking-wide text-fuchsia-300">Movie</p>
<p class="mt-2 text-2xl font-bold text-amber-300">7.5 / 10</p>
<p class="mt-2 italic text-violet-200">"Creepy but good."</p>
</div>
</div>
<p class="mt-10"><a class="text-amber-300 underline hover:text-amber-200" href="/">← Back to Home</a></p>
</div>
</body>
</html>
"""
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=5000)
The form is UI only for now (button type button) so you are not stuck on saving data until you are ready.
Step 2: Install Flask
pip install flask
Step 3: Run the app
Save app.py, play button, open it in the browser (Codespaces: use the port popup or Ports tab for port 5000 -- Cursor / local: http://localhost:5000).
Step 4: Make it yours
Replace the three example cards with your movies and albums.
Challenge: Use a Python list
Add this below app = Flask(__name__):
my_ratings = [
{"title": "Forrest Gump", "type": "Movie", "rating": 8.5,
"notes": "Classic. Tom Hanks is goated."},
{"title": "After Hours", "type": "Album", "rating": 9,
"notes": "The Weeknd at his best."},
]
Replace ratings() with a version that loops over my_ratings and builds HTML cards. Use an f-string return f""" ... """ and build a string cards in a for loop. Use Tailwind classes like rounded-xl border border-violet-700 bg-violet-900/80 p-4 for each card.
Tip: inside f""" ... """, use {{ and }} if you ever need literal curly braces -- for Tailwind you mostly do not need braces in the HTML.
Set Your Goal for Next Week
Open TODO.md again and set one specific goal. Examples:
-
"Save new ratings into my_ratings using a form POST"
-
"Add search or filter on
/ratings" -
"Add poster image URLs to each card"
Troubleshooting
"No module named flask"
pip install flask or pip3 install flask.
Page looks plain
Missing Tailwind <script> in <head>. Restart Flask, hard-refresh.
Route "Not Found"
Keep routes above if __name__ == "__main__":.
Get Help From Your AI Agent
I'm building a Media Rater Flask app for Demo Day. This week I'm working on: [e.g. list loop / Tailwind cards / an error].
[paste app.py or one function]Stuck because: [describe]. Paste terminal errors.
Please coach me -- no full-file rewrite. Small steps first.