Introduction: What Makes a Framework a Framework?
Web Framework Internals
Chapter 1 · Introduction: What Makes a Framework a Framework?
Django looks nothing like Express, which looks nothing like Rails, which looks nothing like Laravel. Different languages, different syntax, different philosophies loudly advertised on their own homepages. And yet underneath all of that, nearly every one of them is solving the same small handful of real problems — the same problems every single time, regardless of which language or company built the framework in question. This course looks at those problems directly, one at a time: what each one actually is, and then how genuinely differently (or similarly) real frameworks choose to solve it.
Library vs. Framework: A Real, Precise Distinction
"Framework" gets used loosely enough in casual conversation that it's worth pinning down exactly what separates it from a library — not as a vague feeling, but as a genuine, testable property: who calls whom.
A library is a collection of code your code calls, on your own schedule, in whatever order you decide. A framework inverts that relationship — it provides the outer structure and the actual control flow, and it calls your code, at moments and in an order the framework itself decides. This is genuinely old, well-established terminology: Martin Fowler's real 2004 article, "Inversion of Control Containers and the Dependency Injection Pattern," was written specifically to clarify a term that was already, even then, being used loosely and inconsistently across the industry. The informal shorthand many developers reach for — "don't call us, we'll call you," sometimes nicknamed the Hollywood Principle — captures the same real idea: the framework is in charge of the flow, not your own code.
| Property | Library | Framework |
|---|---|---|
| Who calls whom | Your code calls the library | The framework calls your code |
| Control flow | Owned by your own application | Owned by the framework itself |
| A concrete example | requests.get(url) — you decide exactly when this runs | A Django view function, only ever invoked by Django itself, only once a matching URL arrives |
| What you actually write | Calls into the library, wherever you choose to put them | Pieces the framework's own lifecycle expects to find and call — a route handler, a middleware function, a model class |
This distinction genuinely matters for the rest of this course, because every one of the four capabilities below is, at its core, a specific place where a framework has decided to take control away from you and call your code itself — a route handler only runs when the framework's own router decides a URL matches it; a template only renders when the framework's own view-rendering machinery reaches that point in a request.
Four Real, Load-Bearing Capabilities
Real frameworks vary enormously in scope — some try to do almost everything, others deliberately do very little — but a genuinely useful, real-world starting definition keeps narrowing down to the same short list. This course picks four to go deep on, one chapter of "how it actually works" followed by one chapter of "how real frameworks differ" for each:
| Capability | The real problem it solves |
|---|---|
| Routing | Matching an incoming URL (and HTTP method) to the specific piece of your own code that should handle it |
| Templating | Turning data into an actual HTML response, without hand-concatenating strings and without a raw injection vulnerability |
| Data access | Getting data in and out of a real database without hand-writing every SQL statement for every table by hand |
| Middleware | Running shared logic — auth checks, logging, error handling — around every request, without repeating it in every single handler |
This isn't an arbitrary list — it's grounded directly in why one of the most widely used frameworks on this entire list was built in the first place. TJ Holowaychuk built Express specifically because, in his own real, documented words, Node.js itself "lacked key features like routing, templating, middleware, and robust error handling" — three of this course's own four chosen capabilities named explicitly, by the person who built a framework specifically to provide them.
Frameworks Are (Almost Always) Extracted From a Real Application
A recurring, genuinely verifiable pattern across framework history: the framework wasn't designed first, in the abstract, and then used to build something. It was pulled out of something real that had already been built, once its own author noticed the same problem recurring inside it.
| Framework | The real, verified origin story |
|---|---|
| Ruby on Rails | Created by David Heinemeier Hansson in 2003 while building Basecamp, 37signals' own real project-management tool — Rails was extracted directly from Basecamp's own codebase and released as open source in July 2004, introducing "convention over configuration" as its own defining philosophy |
| Django | Built starting in 2003 by Adrian Holovaty and Simon Willison (with Jacob Kaplan-Moss joining early) at the Lawrence Journal-World newspaper, to meet the real, fast-turnaround demands of a working newsroom — publicly released as version 0.90 on July 21, 2005 |
| Laravel | Created by Taylor Otwell and first released in June 2011, built specifically as a real alternative to CodeIgniter, a then-popular PHP framework Otwell found genuinely lacking in built-in authentication and routing support |
Frameworks This Course Draws On
Every comparison chapter in this course draws on real, working frameworks this site already has dedicated courses for — this course cross-references that material directly rather than re-teaching any single framework from scratch:
| Framework | Language | This site's own dedicated coverage |
|---|---|---|
| Django | Python | django1/django2, plus catalog-django1 and plpredict-django1 as full real-project builds |
| Express | JavaScript (Node.js) | express1/express2, plus react-food-tracker-1 and catalog-express1 |
| Ruby on Rails | Ruby | rails1/rails2, plus website-rebuild-with-rails1 |
| Laravel | PHP | laravel1/laravel2, plus website-rebuild-with-laravel1 |
| FastAPI | Python | fastapi1, fastapi-food-tracker-1, and plpredict-fastapi1 |
| Astro | JavaScript/TypeScript | astro1, plus website-rebuild-with-astro1 |
Where This Course Is Headed
Routing — how it actually works (Chapter 2), then compared across Django, Express, Rails, Laravel, and FastAPI (Chapter 3); templating — how it actually works (Chapter 4), then compared across Django Templates/Jinja2, ERB, Blade, EJS/Pug, and JSX (Chapter 5); data access and the ORM layer — how it actually works (Chapter 6), then compared across the Django ORM, SQLAlchemy, ActiveRecord, Eloquent, and Prisma (Chapter 7); middleware and the request/response lifecycle — how it actually works (Chapter 8), then compared across Express, Django, Rails, and FastAPI (Chapter 9); and a closing capstone applying every prior chapter to a real, worked framework-selection decision (Chapter 10).
Hands-On Exercises
Explain the real "who calls whom" distinction between a library and a framework, using one concrete example each from a framework this course will cover in later chapters (e.g. a Django view function vs. Python's own requests library).
📄 View solutionUsing TJ Holowaychuk's own real, quoted reason for building Express, explain why Express is still genuinely considered a framework rather than just a library, despite not shipping a built-in ORM or a mandated template engine.
📄 View solutionPick one of the three real framework origin stories from this chapter (Rails, Django, or Laravel) and identify, in your own words, the specific real problem its own author was trying to solve at the moment the framework was actually created.
📄 View solutionChapter 1 Quick Reference
- The real test — who calls whom: a library is called by your code, a framework calls your code (inversion of control)
- Four core capabilities this course covers — routing, templating, data access, middleware, directly named in TJ Holowaychuk's own real reason for building Express
- Micro vs. full-stack — really just a label for how many of these four a framework ships built in, versus leaves as a deliberate integration point
- A real, recurring pattern — Rails (2004), Django (2005), and Laravel (2011) were each extracted from a real working application, not designed in the abstract first
- Next chapter: Routing & URL Dispatch — how it actually works