🚀 Stage 0 of 13
→
Why this project? The 5-layer motive
Pick a project where every layer (Python, ML, FastAPI, Jinja, HTML) has an obvious reason to exist. Meet the Student Performance Predictor.
🧠 The intuition
Most courses fail because the project is decorative — you train a model and then 'also build a frontend' that nobody uses. Here, every layer exists because the previous one couldn't do the job alone.
Python alone can train a model, but it can't serve it to 100 users at once. FastAPI alone can serve a JSON number, but a student can't type into JSON. Jinja alone can render a form, but the form needs a server to receive it. HTML alone can show a number, but it can't compute it.
So the chain is forced: each layer solves a real gap.
✏️ Tiny task — write this yourself
On a piece of paper (or in a comment), write the 5 layers in order and one sentence each on WHY it is needed. Don't write code yet.
✅ Check — what you should see
Expected answer shape:
Python -> train the model, do the math
ML -> turn habits into a predicted score
FastAPI -> accept the form POST, call the model, return the result
Jinja -> render the form and the result with the same shell
HTML -> the actual page the student sees in the browser
🧮 Code files for this stage
📄
folder-structure.txt
text
student_predictor/
app/
main.py # FastAPI app + routes
ml/
train.py # trains model.pkl from CSV
predict.py # loads model.pkl, exposes predict_score()
model.pkl # the trained model (created by train.py)
templates/
base.html # shared shell (nav, footer)
home.html # the form page
result.html # the result page
static/
style.css # one small stylesheet
data/
students.csv # the dataset
requirements.txt
run.sh
12 files total. That's the whole project.
How it works
The folder structure mirrors the 5-layer motive. app/ml/ is the ML layer, app/main.py is the FastAPI layer, app/templates/ is the Jinja layer, app/static/ is the HTML/CSS layer. data/ holds the dataset. The split isn't decoration — it's how you keep 'training time' (offline, slow, writes model.pkl) separate from 'serving time' (online, fast, reads model.pkl).
🚧 Routes — what's wired up at this stage
No routes yet. This stage is about understanding the WHY. The routes will be: GET / (home + form), POST /predict (submit form), GET /result (show prediction). 3 routes total for the whole project.
🧮 Is a response model necessary here?
NO — use response_class=HTMLResponse
At this stage there's no FastAPI yet, so no response model is needed. We will introduce a Pydantic response model only at Stage 8 — once the form is working in plain HTML. Don't add it earlier; it would just be ceremony with no benefit.
⚠️ Common mistakes to avoid
- Putting the model training inside the FastAPI route — train once offline, serve many times online.
- Skipping the folder structure and dumping everything in main.py — works for 50 lines, breaks at 200.
- Picking a dataset with 50 features you don't understand — you'll spend the project fighting the data, not learning the stack.
Next — Stage 1
Meet the dataset — 4 questions you always ask