What is a framework? And why not start from scratch
Lesson 1 of 6
1What is a framework? And why not start from scratch
The big pictureIn the earlier tracks you built everything by hand: a page you redraw with render(), a server where you read the request and check the path with a chain of ifs, and a database you open and close a session for. You noticed the same work repeats in every project, whatever its idea. A framework is that repeated part written once, tested, and shared by millions of developers. You add only what makes your app different.
What the picture shows: What repeats in every app moves into the framework, and you keep what belongs to your app: the café menu, the ordering rules, and the look of the page.
Map of this part
The concepts in order, click any one to jump to it:
Two ways into the same idea
Imagine building a house. You could make every brick by hand, pour the foundation and run the wiring and pipes yourself, and it would take years. Or you start from a ready concrete frame: the columns, the roof and the electricity and water points are in place, and you choose the number of rooms, the colours and the furniture. That frame is the framework. Because it is ready-made, it has rules: you cannot put a room where a column stands. A library is like a toolbox you borrow: a hammer and a drill you use whenever and however you like. The difference in one line: you hold the tools, but the frame decides where you work.
A framework inverts control ("the Hollywood principle": don't call us, we'll call you). The framework owns the main loop and the lifecycle: it receives the event (an HTTP request, a click), picks the function registered for it, passes in the parsed input, then handles the reply or the rendering and the errors. You write extension points: route functions, components, middleware, validation models. A library is the reverse: functions you call, and control returns to you (json.dumps, fetch). The line is not always sharp: React calls itself a library but calls your components the way a framework does, and Next.js is a framework built on top of React.
Before You Start
🖼️The front end
You built a to-do list and redrew it by hand with render().
📨The server and REST
In the REST lesson you saw the same task once with http.server and once with Flask.
🐍Python functions
You know a function is a value you can store in a dictionary and pass around.
The Core Idea
1The problem: code you rewrite in every project
Every web app, whatever its idea, needs the same work: receive the request, know which path was asked for, read the data sent, check it, reply with the right code, and handle errors. Here is a café server written by hand, with no framework. Run it and notice how many lines have nothing to do with coffee:
# a server by hand: every new route is one more "elif", in every project you build
orders = []
def handle(method, path, body=None):
if method == "GET" and path == "/menu":
return 200, ["latte", "mocha", "v60"]
elif method == "POST" and path == "/orders":
if not isinstance(body, dict) or "item" not in body:
return 400, {"error": "item is required"}
orders.append(body["item"])
return 201, {"id": len(orders), "item": body["item"]}
elif method == "GET" and path.startswith("/orders/"):
number = path.split("/")[-1]
if not number.isdigit() or not 1 <= int(number) <= len(orders):
return 404, {"error": "no such order"}
return 200, {"id": int(number), "item": orders[int(number) - 1]}
return 404, {"error": "not found"}
print(handle("GET", "/menu"))
print(handle("POST", "/orders", {"item": "latte"}))
print(handle("POST", "/orders", {}))
print(handle("GET", "/orders/1"))
print(handle("GET", "/orders/9"))It works, but imagine fifty routes: a long elif chain, the same checks repeated in every branch, and numbers parsed by hand. Worse, you will write the same structure in your next project, and the one after.
2The fix: a tiny framework you build yourself
Let's take the repeated part and put it in one place. Here is a whole "framework" in fifteen lines: it stores your functions in a dictionary by verb and path, and when a request arrives it picks the function and calls it, turning any validation error into a 400 reply. The @app.route mark is the same one you saw in Flask: it tells the framework "register this function for this path".
class TinyFramework:
def __init__(self):
self.routes = {}
def route(self, method, path):
def register(fn):
self.routes[(method, path)] = fn # remember your function, do not call it yet
return fn
return register
def handle(self, method, path, body=None):
fn = self.routes.get((method, path))
if fn is None:
return 404, {"error": "not found"}
try:
return 200, (fn(body) if body is not None else fn()) # the framework calls you
except ValueError as error:
return 400, {"error": str(error)}
# ---- everything below is your app; everything above is the framework ----
app = TinyFramework()
@app.route("GET", "/menu")
def menu():
return ["latte", "mocha", "v60"]
@app.route("POST", "/orders")
def create_order(body):
if "item" not in body:
raise ValueError("item is required")
return {"item": body["item"], "status": "brewing"}
print(app.handle("GET", "/menu"))
print(app.handle("POST", "/orders", {"item": "mocha"}))
print(app.handle("POST", "/orders", {}))
print(app.handle("GET", "/tea"))Look at what changed: your app's functions are short and talk only about coffee, and know nothing about 404 and 400 codes. Notice too that you never called menu() yourself: the framework called it when the request arrived. Flask, FastAPI and Express work exactly this way, only with thousands of tested lines instead of fifteen.
3Library or framework? Who calls whom
The two words get mixed up a lot, and the real difference is one question: who calls whom? You call a library whenever you like and control comes back to you, like json.dumps or math.sqrt. A framework holds control and calls your code at the moment it decides.
| Library | Framework | |
|---|---|---|
| Who is in control? | You: you call a function and take the result | The framework: it calls your functions on an event |
| Shape of the code | Your code is the program, the library is a piece inside it | The framework is the program, your code is pieces inside it |
| Rules | Few: use it as you wish | Many: file names, folders and a way of writing |
| Examples | requests, pandas, lodash, json | Express, FastAPI, Django, Next.js |
Some tools sit in between: React calls itself a "library" because it only cares about the interface, but it calls your components the way a framework does, so people call it a framework in everyday talk. Next.js is a full framework built on top of React.
4What you gain and what you pay
What you gain: speed (routing, validation and errors come ready), more safety (the framework closes known holes you would have forgotten), a shared structure (any developer who knows the framework understands your project in a day), documentation and a community that answers your questions, and jobs that ask for the framework by name.
What you pay: time to learn its rules, "magic" that happens out of sight and sometimes makes errors hard to understand, updates that change how you write code between versions, and the difficulty of moving to another framework once the project grows.
5When do you not need a framework?
A framework is a tool, not a requirement. You do not need one for a script that sorts files or builds a report, nor for a static landing page that HTML and CSS handle, nor when you are learning a new idea and want to see every step yourself (which is why you started without one). You need it when the app grows, when more than one person works on it, or when it serves real users who must be protected.
Worked example
What you wrote by hand, and who will write it for you. These are jobs you did in the earlier tracks, and the framework that takes them over in this track:
| The job | Where you wrote it by hand | Who takes it over here |
|---|---|---|
| Reading the request and picking the route | The REST lesson with http.server | Express and FastAPI |
| Checking the data sent | if chains in every route | Pydantic inside FastAPI |
| Documenting the API | You never wrote it | FastAPI's /docs page, automatically |
| Redrawing the list on every change | render() in the DOM lesson | React |
| Pages the server builds | Jinja templates in the SSR lesson | Next.js |
Notice that every row in the table is something you understood before it was automated for you. That is the right order: understand the idea by hand, then hand it to the framework knowing what it does.
Myth vs Reality
| Myth | Reality |
|---|---|
| A framework saves you from learning the language. | The framework is written in the language itself, and every error in it is a language error. Someone who knows JavaScript well learns React in weeks. |
| Using a framework is not "real programming". | Almost every company builds with frameworks. The real skill is knowing what the framework does under the hood, which is what you did by building everything by hand first. |
| The most popular framework is the best for every project. | Most popular means a bigger community and more jobs, but a small script needs no framework, and a team writing Python will not pick a JavaScript one. |
Test your understanding
What is the core difference between a library and a framework?
The question is who holds control. With a library you stay in control; with a framework it decides when your functions run.
In the tiny framework you built, who called the menu() function?
@app.route only registered it, and handle picked it from the dictionary and called it when GET /menu arrived.
In which case do you most likely not need a framework?
A small script receives no requests and draws no interface, so there is no repeated work that needs a ready skeleton.
Quick review cards
@app.route, so the framework calls it later.Check Your Understanding
Explain to a non-technical friend what a framework is in two sentences.
A ready skeleton for a program that holds every part repeated in any app. I add only what is specific to my app, and the skeleton runs it at the right moment.
Why did you learn to build the server and the interface by hand before frameworks?
To understand what the framework automates, so it is not "magic", and so I can understand its errors and change frameworks later without starting over.
Name one thing you gain and one thing you pay when you use a framework.
You gain speed, safety and a shared structure; you pay the time to learn its rules and the difficulty of leaving it later.
Resources for this lesson
Grouped by type. Start with the official docs for precision, or an article or video for the explanation.
Done with this lesson?
Sign in to save your progress.