Routes
Static routes, index files, and how file names map to HTTP URLs in Nooh.
Every .ts file inside your routes directory is a route. The file’s path relative to the routes root becomes the URL; the file’s name suffix — the part before .ts — encodes the HTTP method.
File naming convention
A route filename follows this pattern:
<name>.<method>.ts
Where <name> is the last segment of the URL path and <method> is a lowercase HTTP method. Some examples:
| File | URL | Method |
|---|---|---|
routes/index.get.ts |
/ |
GET |
routes/health.get.ts |
/health |
GET |
routes/users/index.get.ts |
/users |
GET |
routes/users/index.post.ts |
/users |
POST |
routes/products/index.delete.ts |
/products |
DELETE |
A minimal route
// src/routes/health.get.ts
import { get } from "@router/health";
export default get((c) => c.json({ status: "ok" }));
That is the entire file. The get factory is generated by Nooh for this exact route path; importing it from anywhere else is a type error.
Multiple methods on the same path
You can have multiple files for the same path as long as the method suffix is different:
- routes/
- users/
- index.get.ts
- index.post.ts
- users/
Both produce routes on /users — GET /users and POST /users — and each is a separate file with its own handler, middleware, and dependencies.
Nested paths
Directories map directly to URL segments. Nesting directories nests the path:
- routes/
- api/
- v1/
- users/
- index.get.ts
- users/
- v1/
- api/
This produces GET /api/v1/users. There is no special configuration needed — the filesystem layout is the routing table.
Route handler shape
The generated factory accepts either a plain Hono handler or an options object:
// Plain handler — fastest, fewest moving parts
export default get((c) => c.text("Hello"));
// Options object — middleware, validation, DI, error handling
export default get({
middleware: [authMiddleware],
handler: ({ c }) => c.text("Hello"),
});
The options object is documented fully in the relevant sections (Dependency Injection, Validation, Error Handling). The plain handler is valid any time you do not need those features.