Elizabeth: Week 4: Build Your Decision Helper

You already know more Python than you think. This week you are going to build a real, working web app -- a Decision Helper that picks options for indecisive people. By the end of this guide, you will have a live app running in your browser.

Your v0 prototype: https://v0.app/chat/decision-helper-mvp-oPEppfafBOp?ref=GIDR2J

Important: v0 can look very polished because it uses tools built for fast UI. Your first Flask version will be simpler on purpose. You are rebuilding the core flow (pages, form, random pick) in Python so you control how it works. We will keep improving the look week by week. For styling, this guide uses Tailwind CSS from a CDN so the app still looks clean without huge blocks of custom CSS.

Check In: What Are You Working On?

Open your todo file (todo.md or TODO.md). Read what is there. Does it describe what you are actually working on today? If not, update it now with a quick sentence -- even something rough like "Start building the Decision Helper in Flask." You will refine this at the end.

Optional (not required for your project): If you want extra Python practice, you can open warmup.py or favs.py and experiment -- but that is not part of this week's required path.

Part 2: Build Your Decision Helper

Flask is a Python library that turns your code into a website. You write Python functions, connect each one to a page, and Flask sends HTML to the browser. For now, the HTML lives in app.py as strings so you can see how each route returns a page. Styling uses Tailwind classes (see Tailwind CSS).

Step 1: Create app.py

  1. In the file explorer, right-click in an empty area -- New File
  2. Name it app.py

Paste this into app.py:

from flask import Flask, request
import random

app = Flask(__name__)


@app.route("/")
def home():
    return """
    <html>
    <head>
        <meta charset="utf-8">
        <title>Decision Helper</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    <body class="min-h-screen bg-gradient-to-br from-violet-200 via-fuchsia-100 to-sky-200">
        <div class="mx-auto max-w-xl px-6 py-16">
            <h1 class="text-3xl font-bold text-violet-900">Decision Helper</h1>
            <p class="mt-3 text-slate-700">Can't decide? Let us help.</p>
            <p class="mt-2 text-slate-600">Type in your options and we'll pick one for you.</p>
            <a class="mt-6 inline-block rounded-xl bg-violet-600 px-6 py-3 text-lg font-semibold text-white shadow hover:bg-violet-700" href="/decide">Let's Go &rarr;</a>
        </div>
    </body>
    </html>
    """


@app.route("/decide")
def decide():
    return """
    <html>
    <head>
        <meta charset="utf-8">
        <title>Make a Decision</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    <body class="min-h-screen bg-gradient-to-br from-violet-200 via-fuchsia-100 to-sky-200">
        <div class="mx-auto max-w-xl px-6 py-12">
            <h1 class="text-2xl font-bold text-violet-900">What are you deciding?</h1>
            <form class="mt-6 space-y-4" action="/result" method="post">
                <div>
                    <label class="block text-sm font-medium text-slate-700">The question</label>
                    <input class="mt-1 w-full rounded-lg border-2 border-violet-200 px-3 py-2 focus:border-violet-500 focus:outline-none" type="text" name="question" placeholder="e.g. What should I eat for lunch?">
                </div>
                <div>
                    <label class="block text-sm font-medium text-slate-700">Option 1</label>
                    <input class="mt-1 w-full rounded-lg border-2 border-violet-200 px-3 py-2 focus:border-violet-500 focus:outline-none" type="text" name="option1" placeholder="e.g. Pizza">
                </div>
                <div>
                    <label class="block text-sm font-medium text-slate-700">Option 2</label>
                    <input class="mt-1 w-full rounded-lg border-2 border-violet-200 px-3 py-2 focus:border-violet-500 focus:outline-none" type="text" name="option2" placeholder="e.g. Sushi">
                </div>
                <div>
                    <label class="block text-sm font-medium text-slate-700">Option 3</label>
                    <input class="mt-1 w-full rounded-lg border-2 border-violet-200 px-3 py-2 focus:border-violet-500 focus:outline-none" type="text" name="option3" placeholder="e.g. Tacos">
                </div>
                <div>
                    <label class="block text-sm font-medium text-slate-700">Option 4 (optional)</label>
                    <input class="mt-1 w-full rounded-lg border-2 border-violet-200 px-3 py-2 focus:border-violet-500 focus:outline-none" type="text" name="option4" placeholder="Leave blank if you only have 3">
                </div>
                <p class="text-sm text-slate-500">Fill in at least 2 options.</p>
                <button class="rounded-xl bg-violet-600 px-6 py-3 font-semibold text-white shadow hover:bg-violet-700" type="submit">Choose For Me!</button>
            </form>
            <p class="mt-8"><a class="text-violet-700 underline" href="/">&larr; Back to home</a></p>
        </div>
    </body>
    </html>
    """


@app.route("/result", methods=["POST"])
def result():
    question = request.form.get("question", "your decision")
    options = []
    for key in ["option1", "option2", "option3", "option4"]:
        value = request.form.get(key, "").strip()
        if value:
            options.append(value)

    if len(options) < 2:
        return """
        <html>
        <head>
            <meta charset="utf-8">
            <title>Oops</title>
            <script src="https://cdn.tailwindcss.com"></script>
        </head>
        <body class="min-h-screen bg-gradient-to-br from-violet-200 via-fuchsia-100 to-sky-200">
            <div class="mx-auto max-w-xl px-6 py-16">
                <h1 class="text-2xl font-bold text-violet-900">Oops!</h1>
                <p class="mt-3 text-slate-700">You need at least 2 options to decide between.</p>
                <a class="mt-6 inline-block text-violet-700 underline" href="/decide">&larr; Try again</a>
            </div>
        </body>
        </html>
        """

    winner = random.choice(options)

    reasons = [
        "The universe says so. Don't question it.",
        "A very wise penguin recommended this one.",
        "This option has the best vibes today.",
        "We asked a magic 8-ball and it agreed.",
        "Statistically, this is the most fun choice.",
        "Your future self already picked this one.",
        "Mercury is in retrograde, so trust us on this.",
        "We flipped a cosmic coin. This won.",
    ]
    reason = random.choice(reasons)

    return f"""
    <html>
    <head>
        <meta charset="utf-8">
        <title>Your Decision</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    <body class="min-h-screen bg-gradient-to-br from-violet-200 via-fuchsia-100 to-sky-200">
        <div class="mx-auto max-w-xl px-6 py-16 text-center">
            <h1 class="text-xl font-semibold text-violet-900">You asked: {question}</h1>
            <p class="mt-8 text-4xl font-bold text-violet-700">{winner}</p>
            <p class="mt-4 italic text-slate-600">{reason}</p>
            <div class="mt-10 flex flex-wrap justify-center gap-3">
                <a class="rounded-xl bg-violet-600 px-5 py-2 font-semibold text-white hover:bg-violet-700" href="/decide">Decide Again</a>
                <a class="rounded-xl border-2 border-violet-300 px-5 py-2 font-semibold text-violet-800 hover:bg-violet-100" href="/">Home</a>
            </div>
        </div>
    </body>
    </html>
    """


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

What is new here:

  • from flask import Flask, request -- Flask plus request to read form fields.

  • import random -- for random.choice.

  • @app.route(...) -- ties a URL to a Python function.

  • @app.route("/result", methods=["POST"]) -- this page receives the form submit.

  • request.form.get("option1") -- reads what the user typed.

  • random.choice(options) -- picks the winning option.

  • Tailwind: the <script src="https://cdn.tailwindcss.com"></script> line enables the class="..." styling. If that script is missing, the page will look mostly unstyled.

Step 2: Install Flask

Open the terminal (View > Terminal) and run:

pip install flask

If that fails, try pip3 install flask.

Step 3: Run it

  1. Open app.py and save (Cmd+S)
  2. Click the play button (top-right triangle)
  3. In the terminal you should see Running on http://0.0.0.0:5000 (or similar)
  4. Open it in a browser:
    • Codespaces: use the port popup or the Ports tab to open port 5000
    • Cursor (local): go to http://localhost:5000

Click Let's Go, enter a question and at least two options, then Choose For Me!

To stop: click in the terminal and press Ctrl+C.

Step 4: Make it yours

Pick at least one:

  • Add more lines to the reasons list -- make them funnier.

  • Change the look with Tailwind -- edit classes on <body> (for example try from-emerald-200 instead of from-violet-200). See Tailwind CSS for ideas.

  • Add option 5 and 6 -- copy the pattern for option4 in the HTML and add "option5" and "option6" to the for loop in result().

Part 3: Save to GitHub

  1. Save all files: Cmd+S
  2. Source Control -- message: add decision helper flask app with tailwind
  3. Commit, then Sync Changes

Set Your Goal for Next Week

Now that you have built something, open your todo file (todo.md or TODO.md) again and replace whatever is there with one specific thing you will work on before next class. You have a better idea now than you did at the start. Examples:

  • "Add a mood dropdown that changes the fun reason on the result page."
  • "Add a /history page that lists the last few decisions."
  • "Polish the home page layout and button text."

Write one clear sentence, not "finish my app", or "work on stuff."

Troubleshooting

"No module named flask"

Run pip install flask or pip3 install flask in the terminal.

The play button does not show

Make sure app.py is the active tab and saved (Cmd+S).

"Address already in use"

Stop the old server: click the terminal, Ctrl+C, then run again.

Page looks plain (no colors, tiny text)

Check that <script src="https://cdn.tailwindcss.com"></script> is inside the <head> of each page. Save, restart the app, hard-refresh the browser.

Form errors or "Method Not Allowed"

Your /result route needs methods=["POST"] and the form needs method="post" and action="/result".

Source Control shows no changes

Save each file you edited (Cmd+S).

Get Help From Your AI Agent

Copy this prompt into the AI chat and fill in the brackets. Ask it to coach you, not do the whole project for you.

I'm building a Decision Helper Flask app for Demo Day. This week I'm working on: [what you are doing right now -- e.g. first running app.py / adding a mood dropdown / fixing an error].

Here's my current code (or the part that matters):

[paste your app.py or one function]

Here's what goes wrong (or what I'm trying to figure out): [describe it. Paste the terminal error if there is one].

Please do not rewrite my whole file. Walk me through what to check first, then suggest small steps I can try. Explain any new words in one sentence.

You can also select code in the editor and ask: "Explain what this line does" or "Why might this error happen?"