Express Routers & Route Organization

An Express Router is a mini-application of grouped routes that you mount under a shared URL prefix, letting you split a growing API into small, focused files.

Learn Express Routers & Route Organization in our free Node.js course — a beginner-friendly interactive lesson with worked examples, a practice exercise and…

Part of the free Node.js course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll create routers with express.Router() , mount them with app.use('/api', router) , read route params, chain methods with app.route() , split routes into files, and understand why route order matters.

What You'll Learn in This Lesson

1️⃣ Creating & Mounting a Router

Putting every route directly on app gets messy fast. express.Router() creates a mini-app : a self-contained group of routes you define with relative paths. You then mount it with app.use('/api/users', router) , and every route inside it gains that prefix.

Route parameters — the :id in a path — arrive on req.params . Note they're always strings , so convert with Number() when you need a number.

2️⃣ Chaining Methods with app.route()

When several HTTP methods share the same path — say GET , PUT , and DELETE on /books/:id — repeating that string on every line is noisy. app.route(path) lets you declare the path once and chain the method handlers off it.

3️⃣ Route Order & Splitting Into Files

Express checks routes in the order you declare them and stops at the first match. That means a literal path like /users/me must come before a parameter path like /users/:id — otherwise :id matches first with id = "me" and your specific handler never runs.

In real projects you put each feature's router in its own file and mount them all in app.js . Here's the standard structure (shown as code — it spans multiple files, so it isn't run on one page):

Your turn. Fill in the two blanks marked ___ to create and mount a router, then run it and compare with the expected output.

No blanks this time — build the router yourself from the brief. Add a list route, a by-id route with a 404 fallback, and mount it at /api/products . Run it and check your output against the example in the comments.

📋 Quick Reference — Express Routing

Practice quiz

What is an express.Router()?

  • A database table
  • A self-contained mini-app of routes you can mount under a prefix
  • A middleware that parses JSON
  • A logging tool

Answer: A self-contained mini-app of routes you can mount under a prefix. A Router groups related routes into a mountable mini-app with relative paths.

How do you mount a router so its routes live under /api/users?

  • app.get('/api/users', router)
  • app.mount('/api/users', router)
  • router.use('/api/users', app)
  • app.use('/api/users', router)

Answer: app.use('/api/users', router). app.use('/api/users', router) mounts the router; each inner route gains that prefix.

Inside a router mounted at /api/users, what path do you write for the by-id route?

  • '/:id' (relative to the mount point)
  • '/api/users/:id'
  • '/users/:id'
  • 'api/users/:id'

Answer: '/:id' (relative to the mount point). Router paths are relative to the mount point, so you write '/:id', not the full path.

Why does /users/:id declared before /users/me break the /users/me route?

  • Parameter routes are disabled
  • Express sorts routes alphabetically
  • The :id route matches first with id = 'me', so /users/me never runs
  • Routers cannot have literal paths

Answer: The :id route matches first with id = 'me', so /users/me never runs. Express stops at the first match, so the earlier :id route swallows 'me' as the id.

What does app.route('/books/:id') let you do?

  • Mount another app
  • Parse the request body
  • Declare the path once and chain .get(), .delete(), etc.
  • Redirect to a new URL

Answer: Declare the path once and chain .get(), .delete(), etc.. app.route(path) declares the path once and chains multiple method handlers off it.

Values in req.params arrive as what type?

  • Numbers
  • Strings
  • Booleans
  • Objects

Answer: Strings. Route params are always strings; convert with Number() when you need a number.

Which middleware must you add so req.body is populated on a JSON POST?

  • express.static()
  • express.urlencoded() only
  • app.use(express.json())
  • express.router()

Answer: app.use(express.json()). express.json() parses a JSON request body into req.body; without it req.body is undefined.

Your router's routes all return 404. What is the most likely cause?

  • You forgot to mount it with app.use(prefix, router)
  • You used app.route()
  • The port is wrong
  • You forgot express.json()

Answer: You forgot to mount it with app.use(prefix, router). Defining a router doesn't connect it; you must mount it with app.use before its routes respond.

What does a double prefix like /api/users/api/users usually mean?

  • The port is duplicated
  • express.json() is missing
  • Two routers share a prefix
  • You wrote the full path inside the mounted router instead of a relative one

Answer: You wrote the full path inside the mounted router instead of a relative one. Inside a mounted router use relative paths like '/' and '/:id', not the full prefixed path.

What is the recommended structure for a non-trivial Express API?

  • One Router per feature, each in its own file, mounted in app.js
  • All routes in a single giant function
  • One file per route handler with no routers
  • Define routes inside app.listen()

Answer: One Router per feature, each in its own file, mounted in app.js. Create one Router per feature in a routes/ folder and mount them all in app.js.