John: Week 4: Catch Up and Start Your Budget App

You want to build a serious budget tracker for Demo Day (April 29th). Right now your repo mostly has favs.py from Week 1. That is a normal starting point -- we just need project documentation for instructors, then a first Flask version of your app.

Important: A full budget product could include accounts, forecasting, and history. Your first Flask build is an MVP: add expenses and see a summary. It will look simpler than a fancy website on purpose. You are learning routes, forms, and Python lists. This guide uses Tailwind CSS via CDN so the UI still looks intentional. See Tailwind CSS.

Check In: What Are You Working On?

Create TODO.md if you need it. Write one rough sentence -- for example: "Document my budget app idea and build a first Flask MVP." You will replace this with a sharper goal at the end.

Part 1: Essential Project Catch-up

Add v0-prompt.md

Create v0-prompt.md and describe your budget app in plain language (no leftover brackets). Example structure:

You are my MVP build coach.

I am a high school student and a beginner programmer.
Use plain language. Define technical words in one sentence.

Project idea:
[Track spending, see totals, and eventually help me stay under a budget]

Target user:
[Me -- and anyone who wants a simple budget view]

Build me the smallest working MVP with only 3-5 must-have features.

Features:
1. [Add an expense with amount and category]
2. [See a list of expenses and a total]

Do not add extra features yet.

Add vibe-code-report.md

Use this outline (you do not have a v0 link yet -- that is OK):

# Vibe Code Report

## Prototype Link

**No v0 link yet** -- I am building my first version in Flask.

## What I Plan to Build First

- Project idea (1-2 sentences):
- Platform: Flask first
- MVP features (3-5 bullets):

## Reflection

- How do you feel about the direction so far?
- What would you change with more time?
- What would you keep the same?

## Known limitations

- [What is not built yet]

Commit Part 1

  1. Save all files
  2. Source Control -- message: add v0 prompt and vibe code report for budget app
  3. Commit, then Sync Changes

Optional (not required): Update favs.py to use f-strings with {artist} and {song} instead of hardcoded text in the prints -- good practice, but not required for your budget MVP. Optional: add warmup.py with a budget-themed formula.

Part 2: Build Budget Buddy in Flask

Flask connects URLs to Python functions. This MVP stores expenses in a Python list in memory (they reset when the server restarts -- that is fine for Week 4). Styling uses Tailwind. See Flask.

Step 1: Install Flask

Terminal (View > Terminal):

pip install flask

Use pip3 if needed.

Step 2: Create app.py

Create app.py and paste:

from flask import Flask, request

app = Flask(__name__)

expenses = []


@app.route("/")
def home():
    return """
    <html>
    <head>
        <meta charset="utf-8">
        <title>Budget Buddy</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    <body class="min-h-screen bg-slate-950 text-slate-100">
        <div class="mx-auto max-w-2xl px-6 py-12">
            <h1 class="text-3xl font-bold text-emerald-400">Budget Buddy</h1>
            <p class="mt-3 text-slate-300">Track your spending. Know where your money goes.</p>
            <div class="mt-8 flex flex-wrap gap-3">
                <a class="rounded-lg bg-emerald-500 px-5 py-2 font-semibold text-slate-950 hover:bg-emerald-400" href="/add">Add Expense</a>
                <a class="rounded-lg border border-emerald-500 px-5 py-2 font-semibold text-emerald-300 hover:bg-emerald-500/10" href="/summary">View Summary</a>
            </div>
        </div>
    </body>
    </html>
    """


@app.route("/add", methods=["GET", "POST"])
def add():
    message = ""
    if request.method == "POST":
        description = request.form["description"]
        amount = float(request.form["amount"])
        category = request.form["category"]
        expenses.append({
            "description": description,
            "amount": amount,
            "category": category,
        })
        message = f'<p class="mb-4 rounded-lg bg-emerald-500/20 px-4 py-2 font-semibold text-emerald-300">Added: {description} (${amount:.2f})</p>'

    return f"""
    <html>
    <head>
        <meta charset="utf-8">
        <title>Add Expense - Budget Buddy</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    <body class="min-h-screen bg-slate-950 text-slate-100">
        <div class="mx-auto max-w-2xl px-6 py-12">
            <h1 class="text-2xl font-bold text-emerald-400">Add Expense</h1>
            {message}
            <form method="POST" class="mt-6 space-y-4 rounded-xl border border-slate-700 bg-slate-900/80 p-6">
                <div>
                    <label class="block text-sm font-medium text-sky-300" for="description">What did you spend on?</label>
                    <input class="mt-1 w-full rounded-lg border border-slate-600 bg-slate-900 px-3 py-2 text-white placeholder-slate-500 focus:border-emerald-500 focus:outline-none" type="text" id="description" name="description" placeholder="e.g. Chipotle, gas, Netflix" required>
                </div>
                <div>
                    <label class="block text-sm font-medium text-sky-300" for="amount">How much? ($)</label>
                    <input class="mt-1 w-full rounded-lg border border-slate-600 bg-slate-900 px-3 py-2 text-white focus:border-emerald-500 focus:outline-none" type="number" id="amount" name="amount" step="0.01" min="0" placeholder="0.00" required>
                </div>
                <div>
                    <label class="block text-sm font-medium text-sky-300" for="category">Category</label>
                    <select class="mt-1 w-full rounded-lg border border-slate-600 bg-slate-900 px-3 py-2 text-white focus:border-emerald-500 focus:outline-none" id="category" name="category">
                        <option value="food">Food</option>
                        <option value="transport">Transport</option>
                        <option value="entertainment">Entertainment</option>
                        <option value="other">Other</option>
                    </select>
                </div>
                <button class="w-full rounded-lg bg-emerald-500 py-3 font-semibold text-slate-950 hover:bg-emerald-400" type="submit">Add Expense</button>
            </form>
            <p class="mt-8 text-sky-300"><a class="underline hover:text-white" href="/">Home</a> &middot; <a class="underline hover:text-white" href="/summary">View Summary</a></p>
        </div>
    </body>
    </html>
    """


@app.route("/summary")
def summary():
    total = 0
    rows = ""
    for expense in expenses:
        total = total + expense["amount"]
        rows += f"""
            <tr class="border-b border-slate-700">
                <td class="px-4 py-3">{expense["description"]}</td>
                <td class="px-4 py-3">${expense["amount"]:.2f}</td>
                <td class="px-4 py-3 capitalize">{expense["category"]}</td>
            </tr>
        """

    if len(expenses) == 0:
        rows = '<tr><td colspan="3" class="px-4 py-6 text-center text-slate-400">No expenses yet. <a class="text-sky-400 underline" href="/add">Add one.</a></td></tr>'

    return f"""
    <html>
    <head>
        <meta charset="utf-8">
        <title>Summary - Budget Buddy</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    <body class="min-h-screen bg-slate-950 text-slate-100">
        <div class="mx-auto max-w-3xl px-6 py-12">
            <h1 class="text-2xl font-bold text-emerald-400">Spending Summary</h1>
            <div class="mt-6 overflow-hidden rounded-xl border border-slate-700">
                <table class="w-full border-collapse text-left text-sm">
                    <thead class="bg-slate-900 text-sky-300">
                        <tr>
                            <th class="px-4 py-3">Description</th>
                            <th class="px-4 py-3">Amount</th>
                            <th class="px-4 py-3">Category</th>
                        </tr>
                    </thead>
                    <tbody class="divide-y divide-slate-700">
                        {rows}
                    </tbody>
                </table>
            </div>
            <p class="mt-6 text-xl font-bold text-emerald-400">Total: ${total:.2f}</p>
            <p class="mt-8 text-sky-300"><a class="underline hover:text-white" href="/add">Add Expense</a> &middot; <a class="underline hover:text-white" href="/">Home</a></p>
        </div>
    </body>
    </html>
    """


if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=5000)

Notes:

  • expenses is a list of dictionaries -- your app's memory for now.

  • /add needs methods=["GET", "POST"] so the form can submit.

  • Tailwind -- keep the script tag in every page <head>.

Step 3: Run and test

  1. Save app.py, click the play button
  2. Open http://localhost:5000 (Codespaces: Ports tab)

Add a few expenses, then open View Summary.

Stop: terminal focus, Ctrl+C.

Step 4 (optional): Budget limit

Add a variable like budget_limit = 500 near expenses = [] and show remaining budget on the summary page using the total you already calculate.

Part 3: Save to GitHub

Source Control -- message: add budget buddy flask app with tailwind

Set Your Goal for Next Week

Open TODO.md and replace your rough line with one specific next step. Examples:

  • "Show remaining budget against a set limit on the summary page."

  • "Add a simple breakdown by category."

  • "Save expenses to a file so they survive a server restart."

Troubleshooting

"No module named flask"

pip install flask or pip3 install flask.

Form submits but summary is empty

Check expenses = [] is at the top of the file (not inside a function). Check /add includes methods=["GET", "POST"].

Page looks unstyled

Missing Tailwind <script> in <head>, or need to restart Flask and refresh.

"Address already in use"

Ctrl+C in the terminal, then run again.

Get Help From Your AI Agent

I'm building a budget tracker Flask app for Demo Day. This week I'm working on: [e.g. first run / form POST / summary total / Tailwind].

Here's my code:

[paste app.py or one function]

Problem: [describe. Paste terminal errors].

Do not rewrite my whole project. Tell me what to check first, then small edits. Define new terms in one sentence.