Quick Start
Manual REST API walkthrough — routers, middleware, JSON bodies, and where to go next
This guide is the manual path. You create the project yourself so the routing and middleware order stay visible.
Before you start
Use Node.js 22+ and a package manager. The steps use pnpm; npm and yarn work with the same
commands where equivalents exist. Use the tsconfig.json shape from
Installation so module resolution matches
the scaffolder. For a generated app, use Installation and
create-nextrush for scaffold commands and flags.
Create a new project
mkdir my-nextrush-api
cd my-nextrush-api
pnpm initAdd "type": "module" to package.json so Node runs ESM entrypoints the same way as the scaffolder.
Install dependencies
$ pnpm add nextrush$ pnpm add -D tsx typescript @types/node
Create the entry point
Create src/index.ts:
import { createApp, createRouter, listen } from 'nextrush';
// Create the application
const app = createApp();
// Create feature routers
const health = createRouter();
health.get('/', (ctx) => {
ctx.json({
name: 'My API',
version: '1.0.0',
status: 'healthy',
});
});
const users = createRouter();
users.get('/', (ctx) => {
ctx.json([
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
]);
});
users.get('/:id', (ctx) => {
const { id } = ctx.params;
ctx.json({
id: Number(id),
name: 'Alice',
email: 'alice@example.com',
});
});
// Mount routers
app.route('/', health);
app.route('/users', users);
// Start the server
await listen(app, 3000);Run the server
npx tsx src/index.tsYou should see a line like:
🚀 NextRush listening on http://localhost:3000Test your API
Open another terminal and test the endpoints:
# Root endpoint
curl http://localhost:3000/
# → {"name":"My API","version":"1.0.0","status":"healthy"}
# List users
curl http://localhost:3000/users
# → [{"id":1,"name":"Alice",...},{"id":2,"name":"Bob",...}]
# Get user by ID
curl http://localhost:3000/users/1
# → {"id":1,"name":"Alice","email":"alice@example.com"}Adding Middleware
Middleware runs before your route handlers. Register it before app.route() so it wraps mounted
routers.
Add a timer that prints to stdout (fine for local dev; in production, send timings to your logger):
import { createApp, createRouter, listen } from 'nextrush';
const app = createApp();
app.use(async (ctx) => {
const start = Date.now();
await ctx.next();
const ms = Date.now() - start;
// Example only — use structured logging in production
console.log(`${ctx.method} ${ctx.path} - ${ms}ms`);
});
const health = createRouter();
health.get('/', (ctx) => {
ctx.json({
name: 'My API',
version: '1.0.0',
status: 'healthy',
});
});
const users = createRouter();
users.get('/', (ctx) => {
ctx.json([
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
]);
});
users.get('/:id', (ctx) => {
const { id } = ctx.params;
ctx.json({
id: Number(id),
name: 'Alice',
email: 'alice@example.com',
});
});
app.route('/', health);
app.route('/users', users);
await listen(app, 3000);Middleware order
Middleware runs in registration order. The logger runs first because it is registered before the routers are mounted.
Security headers, JSON bodies, and POST
Add CORS, security headers, and JSON parsing. Register helmet → cors → json before your
logger so bodies are parsed before timing runs:
$ pnpm add @nextrush/cors @nextrush/helmet @nextrush/body-parser
import { createApp, createRouter, listen } from 'nextrush';
import { cors } from '@nextrush/cors';
import { helmet } from '@nextrush/helmet';
import { json } from '@nextrush/body-parser';
const app = createApp();
app.use(helmet());
app.use(cors());
app.use(json());
app.use(async (ctx) => {
const start = Date.now();
await ctx.next();
const ms = Date.now() - start;
console.log(`${ctx.method} ${ctx.path} - ${ms}ms`);
});
const health = createRouter();
health.get('/', (ctx) => {
ctx.json({
name: 'My API',
version: '1.0.0',
status: 'healthy',
});
});
const users = createRouter();
users.get('/', (ctx) => {
ctx.json([
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
]);
});
users.get('/:id', (ctx) => {
const { id } = ctx.params;
ctx.json({
id: Number(id),
name: 'Alice',
email: 'alice@example.com',
});
});
users.post('/', (ctx) => {
const { name, email } = ctx.body as { name: string; email: string };
ctx.status = 201;
ctx.json({
id: Date.now(),
name,
email,
});
});
app.route('/', health);
app.route('/users', users);
await listen(app, 3000);Test it:
curl -X POST http://localhost:3000/users \
-H "Content-Type: application/json" \
-d '{"name":"Charlie","email":"charlie@example.com"}'Complete example
The block below matches the POST section above — one file you can paste into src/index.ts:
Full application code with routing, middleware, and POST handling
import { createApp, createRouter, listen } from 'nextrush';
import { cors } from '@nextrush/cors';
import { helmet } from '@nextrush/helmet';
import { json } from '@nextrush/body-parser';
const app = createApp();
// Middleware
app.use(helmet());
app.use(cors());
app.use(json());
// Logger
app.use(async (ctx) => {
const start = Date.now();
await ctx.next();
console.log(`${ctx.method} ${ctx.path} - ${Date.now() - start}ms`);
});
// Feature routers
const health = createRouter();
health.get('/', (ctx) => {
ctx.json({ name: 'My API', version: '1.0.0' });
});
const users = createRouter();
users.get('/', (ctx) => {
ctx.json([
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
]);
});
users.get('/:id', (ctx) => {
ctx.json({ id: Number(ctx.params.id), name: 'Alice' });
});
users.post('/', (ctx) => {
const { name, email } = ctx.body as { name: string; email: string };
ctx.status = 201;
ctx.json({ id: Date.now(), name, email });
});
// Mount routers
app.route('/', health);
app.route('/users', users);
// Start
await listen(app, 3000);Common mistakes
Forgetting ctx.next()
If your middleware doesn't call await ctx.next(), the request will hang. Always call
ctx.next() unless you're intentionally ending the response.
Middleware registered after app.route() calls won't run for those routes. Register middleware before mounting routers.