Register Routes and Mount the Router on Your App
Using "@koa/router"
Create a `Router` instance, register GET and POST handlers, then mount the router on your Koa app with `router.routes()` and `router.allowedMethods()`.
What you'll learn
- Create a Router instance and register routes
- Mount the router correctly on a Koa app
- Build a working GET/POST users example
With @koa/router installed (npm install @koa/router), you can
register routes declaratively and mount the whole router as Koa
middleware in two lines.
Creating a Router
import Router from "@koa/router";
const router = new Router(); Each router instance keeps its own route table. You can create as many routers as you need and compose them later.
Registering Routes
The router exposes a method for every HTTP verb:
router.get("/users", async (ctx) => {
ctx.body = { users: [] };
});
router.post("/users", async (ctx) => {
// ctx.request.body available after body-parser middleware
ctx.status = 201;
ctx.body = { created: true };
});
router.delete("/users/:id", async (ctx) => {
ctx.body = { deleted: ctx.params.id };
}); Handlers are async (ctx) => {} functions. Set ctx.body to send
a response; set ctx.status when you need a non-200 code.
Mounting the Router
This step is where many beginners trip up. You must call both
router.routes() and router.allowedMethods():
app.use(router.routes()).use(router.allowedMethods()); router.routes()— returns a middleware that matches the incoming request and calls the right handler.router.allowedMethods()— returns a middleware that sends a proper405 Method Not Allowed(or501 Not Implemented) when a path exists but the HTTP method is not registered.
Full Working Example
import Koa from "koa";
import Router from "@koa/router";
const app = new Koa();
const router = new Router();
const users = [
{ id: "1", name: "Alice" },
{ id: "2", name: "Bob" },
];
router.get("/users", async (ctx) => {
ctx.body = users;
});
router.post("/users", async (ctx) => {
const newUser = { id: String(users.length + 1), name: "New User" };
users.push(newUser);
ctx.status = 201;
ctx.body = newUser;
});
app.use(router.routes()).use(router.allowedMethods());
app.listen(3000, () => console.log("Listening on :3000")); Run this and GET /users returns the array while POST /users
appends to it.
Route Handler Signature
| Parameter | Type | Purpose |
|---|---|---|
ctx | Koa.Context | Merged request + response API |
next | () => Promise | Call next matching middleware |
Most handlers do not need next. Pass it when you want to chain
handlers or run shared middleware before a specific route.
Up Next
Paths often carry dynamic segments like /users/42. The next
lesson covers route parameters.