# Choosing Your First Framework

> A decisive, practical answer to 'given I know language X, which framework should I actually start with' - one recommendation per language, plus when to skip a framework entirely.


---

# Choosing Your First Framework

You know a language. You need to build something with it - an API, a web app, a backend for a
project. And now you're stuck at a different wall: which framework do you actually open first?

This guide skips the survey and gives you an answer. If you haven't already read
[What a Framework Even Is](/guides/what-a-framework-even-is), start there - it covers the concept
and a general method for learning any framework. This one assumes that and answers the narrower,
more urgent question: given the language you already know, where do you start today.

## The phases

1. **[You Don't Need to Learn Ten Frameworks](01-you-dont-need-to-learn-ten-frameworks.md)** - why the anxiety is normal, and why the real question is narrower than it feels.
2. **[A Starting Point, Language by Language](02-a-starting-point-language-by-language.md)** - one opinionated recommendation per language, with why.
3. **[When You Don't Need a Framework Yet](03-when-you-dont-need-a-framework-yet.md)** - the straight alternative: sometimes the standard library is enough.


---

# You Don't Need to Learn Ten Frameworks

Open any job board, any "learn to code" roadmap, any programming subreddit, and you'll see a wall
of framework names. React, Vue, Svelte, Django, Flask, FastAPI, Express, Nest, Spring, Gin, Axum,
Rails, Laravel, ASP.NET - dropped side by side as if you're supposed to know all of them, or at
least know which is "winning" this year.

You don't need any of that. You need one framework, in the language you already know, for the
thing you're building right now.

## The question is narrower than it feels

"Which framework should I learn" sounds like a research project. It isn't. It collapses into two
much smaller questions:

- **What language do I already know?** Not "want to learn eventually" - know, right now, well
  enough to write a function and read an error message.
- **What am I building?** A JSON API, a full server-rendered site, a quick script that needs a
  couple of HTTP routes - these point at different starting frameworks even within the same
  language.

Answer those two, and the field of "ten frameworks" shrinks to one obvious starting pick per
language. Phase 2 gives you that pick directly.

## Framework noise is not a gap in your skills

Feeling behind because you've never touched a framework everyone online is discussing isn't a
skills gap. It's a sign the industry produces frameworks faster than any one person can track -
ten teams solved the same problem ten different ways, all of them shipped, and all of them now
have fans posting about them.

New frameworks show up every year. Most developers, including senior ones, have used a handful in
their career and read *about* the rest. The confident answer to "have you used X?" is usually "no,
but I could pick it up" - and that's the real bar to aim for, not universal familiarity.

## Depth in one beats a shallow tour of many

A framework rewards time spent in it: knowing its footguns, its idioms, how it structures a real
project past the tutorial stage. That knowledge doesn't come from reading feature comparisons. It
comes from building something and hitting the parts the docs didn't mention.

[What a Framework Even Is](/guides/what-a-framework-even-is) makes the case that every framework
shares the same handful of parts - a router, a data layer, middleware, config. Once you've built
something real in one framework, the next one is mostly relabeling parts you already understand.
That's why picking *a* framework and finishing something in it teaches you more, faster, than
reading about five.

## What "starting" actually means

Starting with one framework is not a permanent vow. It's the fastest way to get moving:

- You'll build things and ship them, instead of stalling on a decision with no wrong answer.
- You'll learn the *shape* of frameworks in general, which transfers to the next one.
- You'll have a real basis for comparison later, instead of guessing from marketing pages.

Switching later, if you need to, costs far less than it feels like from here - especially once you
already know one framework's anatomy.

```quiz
[
  {
    "q": "What does the real question collapse into when choosing a first framework?",
    "choices": [
      "Which framework has the most GitHub stars this year",
      "What language you already know and what you're building right now",
      "Which framework every company is hiring for globally",
      "Whichever framework has zero learning curve"
    ],
    "answer": 1,
    "explain": "The huge list of frameworks narrows fast once you fix the language you know and the kind of thing you're building - that combination points at one obvious starting pick."
  },
  {
    "q": "Why does feeling behind on unfamiliar framework names not mean you have a skill gap?",
    "choices": [
      "Because frameworks are all identical under the hood",
      "Because the industry produces frameworks faster than anyone can track them all, and most developers know a handful, not all of them",
      "Because frameworks are being phased out entirely",
      "Because only junior developers ever feel this way"
    ],
    "answer": 1,
    "explain": "Ten teams solve the same problem ten different ways and all of them ship. Nobody, including senior developers, is fluent in every framework in circulation - and that's normal, not a deficiency."
  },
  {
    "q": "Why does finishing something in one framework teach more than reading about five?",
    "choices": [
      "Because reading documentation is always a waste of time",
      "Because frameworks share the same handful of parts, so real depth in one transfers to the next one faster than shallow familiarity with many",
      "Because only one framework per language is ever worth learning",
      "Because comparison articles are always inaccurate"
    ],
    "answer": 1,
    "explain": "Every framework is built from the same anatomy - router, data layer, middleware, config. Depth in one framework means the next framework is mostly relabeling parts you already understand."
  }
]
```


---

# A Starting Point, Language by Language

Find your language below. Each one gets a direct recommendation, the reason it beats the more
hyped alternative for a *first* framework, and links to both the framework and the language guide
it assumes.

## Python: start with Flask

[Flask](/guides/flask-from-zero) before [FastAPI](/guides/fastapi-from-zero) or
[Django](/guides/django-from-zero). Flask hands you a handful of decorators and gets out of the
way - you see every request and response with nothing hidden. FastAPI adds type hints, async, and
automatic docs generation, all useful, but they're a second layer of concepts stacked on
top of "how does a web framework work" - learn that first, in Flask, then FastAPI's extra features
read as additions instead of a wall. Django is a different animal entirely: an ORM, an admin
panel, a templating engine, and a project structure it insists on, all before you've written your
first route. That's real power for a full application, and overkill for learning what a web
framework even does.

Needs [Python](/guides/python-from-zero) first.

## JavaScript / Node: start with Express

[Express](/guides/express-from-zero) before [NestJS](/guides/nestjs-from-zero). Express is close
to raw Node - you define a route, you get a request and response object, you send something back.
Nest wraps that in decorators, dependency injection, and an Angular-style module system, which pays
off on a large team codebase but adds an architecture to learn before you've learned what the
underlying requests even look like. Start with Express, feel the raw shape of a request-response
cycle, then Nest's structure makes sense as a solution to a problem you've actually felt.

Needs [JavaScript](/guides/javascript-from-zero) (or [TypeScript](/guides/typescript-from-zero))
first.

## Go: start with Gin

[Gin](/guides/gin-from-zero) is the default choice in Go's web space - a thin, fast router with
middleware support and clean error handling, without reinventing how Go itself works. Go's standard
library already handles HTTP well (`net/http` is usable on its own - see Phase 3), so Go
frameworks stay intentionally light. Gin is the least ceremony you can add on top while still
getting route params, grouping, and middleware for free.

Needs [Go](/guides/go-from-zero) first.

## Rust: start with Axum

[Axum](/guides/axum-from-zero) is the natural first pick because it's built by the same team behind
Tokio, Rust's async runtime, so it fits the rest of the async ecosystem without fighting it.
Extractors (pulling a JSON body or a path param into a typed argument) map directly onto ideas
you'll already have from Rust's type system, instead of introducing a parallel mental model. It's
also the framework most new Rust web content assumes, so tutorials and examples line up with what
you're using.

Needs [Rust](/guides/rust-from-zero) first.

## Java: start with Spring Boot

[Spring Boot](/guides/spring-boot-from-zero) isn't the minimal choice, but it's the standard one -
the framework the majority of Java backend jobs actually run on. Fighting that and hand-rolling
servlets first buys you little: Java's ecosystem has settled on Spring so thoroughly that "learning
Java web development" and "learning Spring Boot" are close to the same task in practice. Boot's
auto-configuration removes most of classic Spring's XML-and-ceremony reputation - you annotate a
class and it wires itself up.

Needs [Java](/guides/java-from-zero) first.

## C#: start with ASP.NET Core

[ASP.NET Core](/guides/aspnet-core-from-zero) is the only serious option and that's a feature, not
a gap - Microsoft ships it as part of the .NET platform itself, so there's no "which framework"
debate to have. It covers minimal APIs (a few lines to a working JSON endpoint) up through full
MVC apps, so you can start as small as you want and grow into more structure only when you need it.

Needs [C#](/guides/csharp-from-zero) first.

## The pattern across all of them

Every recommendation above follows the same logic: start with the option that shows you the most
of what's actually happening, not the one with the most features bolted on. Fewer moving parts
means fewer things standing between you and understanding your own code. Add DI containers, ORMs,
and code generation once you've felt the problem they solve - not before.

```quiz
[
  {
    "q": "Why start with Flask instead of Django for a first Python web framework?",
    "choices": [
      "Django doesn't support REST APIs",
      "Flask has a simpler mental model with fewer moving parts, while Django bundles an ORM, admin panel, and enforced project structure before you've written a route",
      "Flask is faster at runtime than Django",
      "Django is no longer maintained"
    ],
    "answer": 1,
    "explain": "Django is real power for a full application, but that power arrives before you've learned what a web framework does at all. Flask shows you the request/response cycle directly."
  },
  {
    "q": "Why is Axum a natural first pick for Rust specifically?",
    "choices": [
      "It has no dependencies at all",
      "It's built by the Tokio team, so it fits Rust's async ecosystem, and its extractors map onto Rust's type system you already know",
      "It doesn't require an async runtime",
      "It is the only web framework available in Rust"
    ],
    "answer": 1,
    "explain": "Axum lines up with Tokio (Rust's async runtime) rather than fighting it, and its typed extractors build on ideas already familiar from Rust's type system."
  },
  {
    "q": "Why is ASP.NET Core recommended for C# without much debate?",
    "choices": [
      "It's the only web framework that supports HTTPS",
      "It ships as part of the .NET platform itself, covering everything from minimal APIs to full MVC apps, so there's no competing ecosystem choice to make",
      "It requires no knowledge of C#",
      "It was only released this year"
    ],
    "answer": 1,
    "explain": "Unlike Python or JavaScript, C# doesn't have a fragmented web framework landscape - ASP.NET Core is shipped by Microsoft as part of .NET and scales from a few lines to a full app."
  }
]
```


---

# When You Don't Need a Framework Yet

Phase 2 gave a starting framework for every major language. Here's the plain exception: for some
of what you're building, you don't need any of them yet.

## The standard library already does a lot

Most languages ship an HTTP server in the box. Python has `http.server`, Go and C# both have
production-usable HTTP stacks in their standard libraries, Node has the `http` module underneath
every framework built on it. None of these are toys - they can route a request, read a body, and
send a response with no framework at all.

Two guides in this library build a real server directly on the standard library, no framework in
sight: [Build a Server with Node's http Module](/guides/build-a-server-with-node-http) and
[Web Services with Only net/http](/guides/web-services-with-only-net-http). Both are worth doing
even if you already picked a framework in Phase 2 - they show you what the framework is actually
doing underneath.

## Where the line actually sits

A framework earns its cost when the app is big enough, long-lived enough, or team-shaped enough
that its conventions save more time than they take to learn. Below that line, the standard library
alone is the better call:

- **A single-endpoint tool** - a webhook receiver, a health-check ping, a small script that needs
  one route. A framework's routing, middleware stack, and config system solve a problem you don't
  have yet.
- **Learning what's underneath a framework you already use.** Building the same small server twice
  - once raw, once in your Phase 2 framework - is the fastest way to see exactly what the framework
  buys you, instead of taking it on faith.
- **A throwaway or short-lived project.** If it won't outlive the afternoon, the framework's setup
  cost outweighs anything it would have saved you.

Outside those cases, a framework usually wins - once real routes, real middleware needs, and a real
team show up, hand-rolling the same things a framework gives you for free stops being a good trade.

## Why the boundary matters more than the pick

[What a Framework Even Is](/guides/what-a-framework-even-is) covers this cost directly in its
["Price of Magic"](/guides/what-a-framework-even-is/5) material - every convenience a framework
adds is also a thing you now depend on and don't fully see. That's a fair trade for a real
application. It's a bad trade for a script that needed ten lines.

Knowing when to skip a framework is not a lesser skill than knowing which one to pick. It's the
same judgment pointed the other way - it separates someone who reaches for a framework by reflex
from someone who reaches for the right tool for the job.

## Where this leaves you

Pick your language, pick the framework from Phase 2, build something real in it, and finish it.
If what you're building is small enough that a framework feels like more setup than the problem
deserves, reach for the standard library instead. Either way, the roots guide for your stack shows
you what the code is actually doing when nobody's watching.

```quiz
[
  {
    "q": "What do the 'roots' guides in this library (build-a-server-with-node-http, web-services-with-only-net-http) demonstrate?",
    "choices": [
      "That standard libraries can't handle real HTTP traffic",
      "That a real server can be built directly on the standard library, with no framework at all",
      "That every framework is built on Node specifically",
      "That frameworks are always faster than the standard library"
    ],
    "answer": 1,
    "explain": "Both guides build a working server using only the language's standard library - proof that a framework is a choice, not a requirement, for getting an HTTP server running."
  },
  {
    "q": "According to this phase, when does skipping a framework make the most sense?",
    "choices": [
      "Never - always use a framework regardless of project size",
      "For a single-endpoint tool, a throwaway script, or when you want to see what a framework is doing underneath",
      "Only when the language has no framework ecosystem at all",
      "Only for enterprise-scale applications"
    ],
    "answer": 1,
    "explain": "Small, short-lived, or single-route projects rarely earn back a framework's setup cost. The standard library also makes a good teaching tool for seeing what a framework abstracts away."
  },
  {
    "q": "Why does this guide say knowing when to SKIP a framework matters as much as knowing which one to pick?",
    "choices": [
      "Because frameworks are being deprecated industry-wide",
      "Because it's the same judgment about cost versus benefit, just pointed the other way - reaching for the right tool instead of reaching by reflex",
      "Because standard libraries are always faster than frameworks",
      "Because most professional applications are built without frameworks"
    ],
    "answer": 1,
    "explain": "Every framework convenience is also a dependency you don't fully see (the 'Price of Magic'). That's worth it for a real, long-lived app and not worth it for a ten-line script - recognizing which situation you're in is the actual skill."
  }
]
```
