Your Python code runs a web server — and you already know the frontend
Day 26 of 80
Flask connects your Python skills to your HTML/CSS skills. The backend (Python) handles data and logic. The frontend (HTML/CSS) handles what users see. You already know the frontend. This week you learn how to wire them together.
Nothing you write in HTML/CSS from here on is new — only the Python side is. By the end of this week, your Prompt Vault runs in a browser instead of a terminal.
First, install Flask in your virtual environment. Open the terminal in Cursor and run:
$ pip install flask
Successfully installed flask-3.x.x Werkzeug-3.x.x Jinja2-3.x.x ...
$ python -c "import flask; print(flask.__version__)"
3.0.3
Add flask to your requirements.txt file so you don't forget it's a dependency. Open that file and add a line with just flask.
Flask is a micro web framework. It's a Python library that turns your script into a program that can listen for HTTP requests — just like a real web server. When someone visits http://localhost:5000, Flask calls your Python function and sends back whatever it returns. That's it. The whole model is that simple.
Corey Schafer's Flask series is the gold standard for learning this framework. Both videos together run about 55 minutes. Watch them in a separate practice folder — create a flask-practice/ directory and type along with every line of code he writes.
First route, running the dev server, basic app structure (~25 min)
HTML pages powered by Python data — Jinja2 syntax (~30 min)
Create a flask-practice/ folder. Open it in Cursor. Type every line Corey types. Do not copy-paste — your fingers need to learn the patterns. If he moves fast, pause. These videos form the foundation for everything you build the rest of this week.
These are the three ideas you must understand cold by the end of today. Read them before the videos, then again after.
A route maps a URL to a Python function. When someone visits that URL, Flask runs the function and sends back whatever it returns.
from flask import Flask
app = Flask(__name__)
# This is a route. The decorator @app.route() tells Flask:
# "when someone visits /about, run the about() function"
@app.route("/about")
def about():
return "<h1>About Page</h1>"
@app.route("/")
def home():
return "<h1>Home Page</h1>"
if __name__ == "__main__":
app.run(debug=True)
@app.route("/") — The @ symbol means decorator. It's a function that wraps another function. Here it registers home() with Flask so Flask knows to call it when the URL is / (the root). You don't call these functions yourself — Flask calls them when a request arrives.
if __name__ == "__main__" — This pattern means "only run the server if I run this file directly." If another file imports app.py, the server doesn't start automatically. You'll see this in every Flask app.
A template is an HTML file with special Python-powered slots. Flask uses Jinja2 as its template engine — the same one used by Ansible, Django, and dozens of other tools.
{{ variable }} — prints a value. Like {{ prompt_text }} outputs the prompt.{% for item in list %} — a loop. Repeat HTML for each item.{% if condition %} — conditional. Show HTML only when true.{% endif %} / {% endfor %} — close the block (unlike Python, you need explicit closing tags).<!-- {{ }} outputs a Python value -->
<h1>Hello, {{ username }}</h1>
<!-- {% %} is for control flow -->
{% if prompts %}
<ul>
{% for p in prompts %}
<li>{{ p.platform }} — {{ p.shot }}</li>
{% endfor %}
</ul>
{% else %}
<p>No prompts yet.</p>
{% endif %}
templates/ folder inside your project. Flask knows to look there automatically — you don't configure the path. Notice the dot notation: p.platform accesses the platform key of a dictionary (or attribute of an object). Jinja2 uses dot syntax for both.
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home():
# Python data — could come from a JSON file, API, database, anywhere
my_prompts = [
{"platform": "Kling", "shot": "aerial over coastal cliffs"},
{"platform": "Runway", "shot": "close-up of water droplets"},
]
# Pass the data to the template
return render_template("index.html", prompts=my_prompts, title="My Prompts")
render_template("index.html", prompts=my_prompts) — The first argument is the filename (inside the templates/ folder). Every keyword argument after that becomes a variable available in the template. So {{ prompts }} in the HTML will have access to my_prompts, and {{ title }} will be "My Prompts".
After watching the videos, write this from scratch (no copy-paste). This is your confidence check — if this works, you understand the basics.
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home():
platforms = ["Kling", "Runway", "Veo", "Pika"]
return render_template("home.html", platforms=platforms)
@app.route("/about")
def about():
return "<h1>Python for Creators — Week 6</h1>"
if __name__ == "__main__":
app.run(debug=True)
<!DOCTYPE html>
<html>
<head><title>My Flask App</title></head>
<body>
<h1>AI Video Platforms</h1>
<ul>
{% for platform in platforms %}
<li>{{ platform }}</li>
{% endfor %}
</ul>
</body>
</html>
$ python hello.py
* Running on http://127.0.0.1:5000
* Debug mode: on
* Restarting with stat
Open your browser to http://localhost:5000. You should see a bulleted list of platforms. Visit http://localhost:5000/about and you get the about page. Two routes, both working.
When debug=True, Flask does two things: it shows detailed error messages in the browser (instead of a generic "500 error"), and it auto-reloads when you save a file — no need to restart the server. You will always run with debug=True during development. Never use it in production, but that's a Week 12 problem.
| Term | What it means | JS equivalent |
|---|---|---|
Flask() |
Creates the web application object | express() in Node.js |
@app.route() |
Registers a URL → function mapping | app.get("/path", handler) |
| Route function | The Python function that handles a URL request | Route handler / controller |
render_template() |
Loads an HTML file, fills in Jinja2 slots, returns the result | res.render() in Express |
| Jinja2 | Template language: {{ }} for values, {% %} for logic |
Handlebars / EJS |
| Decorator | The @ syntax that modifies a function without changing its body |
Higher-order functions / middleware |
debug=True |
Auto-reload on save + detailed error pages | nodemon / hot reload |
pip install flask ran without errorshello.py from scratch and it runs at localhost:5000@app.route() does in plain English{{ }} and {% %} in Jinja2Tomorrow you learn GET vs POST — how data moves from a browser form into your Python code. That's the missing piece before you can build the real Prompt Vault web app (Day 28).