Core Concepts
The mental models that make NextRush predictable and composable
Before you write code, understand how NextRush thinks.
These are the core abstractions that determine how your application processes requests, composes behavior, and handles failure.
The Four Pillars
NextRush is built on four core abstractions. Everything else builds on top of these.
Application
Your entry point. Orchestrates middleware, plugins, and error handling.
Context
The ctx object. Your unified interface to request and response.
Middleware
Functions that process requests. The onion model for composable logic.
Routing
Radix tree routing. O(k) lookup regardless of route count.
How They Work Together
When a request arrives, it flows through a predictable pipeline:
HTTP Request
↓
┌─────────────────────────────┐
│ Application │
│ ┌───────────────────────┐ │
│ │ Middleware Pipeline │ │
│ │ ┌─────────────────┐ │ │
│ │ │ cors → auth │ │ │
│ │ │ ↓ │ │ │
│ │ │ body-parser │ │ │
│ │ │ ↓ │ │ │
│ │ │ router │ │ │
│ │ └─────────────────┘ │ │
│ └───────────────────────┘ │
│ ↓ │
│ ┌───────────────────────┐ │
│ │ Router │ │
│ │ Match path → Handler │ │
│ └───────────────────────┘ │
└─────────────────────────────┘
↓
HTTP ResponseThe flow is always the same:
- Request arrives at the adapter
- Adapter creates a fresh Context object
- Application passes context through Middleware
- Router matches the path and extracts params
- Handler executes and writes to context
- Response flows back through middleware
- Adapter sends the HTTP response
Context is Per-Request
Every request gets a new ctx object. There's no shared state between requests unless you
explicitly create it.
Two Programming Styles
NextRush supports both functional and class-based programming. Choose based on your project's needs.
Simple, direct, minimal abstraction. Often fits small services and APIs.
import { createApp } from '@nextrush/core';
import { createRouter } from '@nextrush/router';
const app = createApp();
const router = createRouter();
router.get('/users/:id', async (ctx) => {
const user = await db.users.findById(ctx.params.id);
ctx.json({ user });
});
app.route('/api', router);Structured, with dependency injection. Often fits larger applications and shared codebases.
import { createRouter } from 'nextrush';
import { Controller, Get, Param, Service, controllersPlugin } from 'nextrush/class';
@Service()
class UserService {
async findById(id: string) {
return db.users.findById(id);
}
}
const router = createRouter();
@Controller('/users')
class UserController {
constructor(private users: UserService) {}
@Get('/:id')
async getUser(@Param('id') id: string) {
return { user: await this.users.findById(id) };
}
}
await app.plugin(controllersPlugin({ router, root: './src' }));You Can Mix Styles
Both styles work together. Start with functions, add classes when you need structure. There's no forced migration.
Extension Points
Beyond the four pillars, NextRush provides two ways to extend functionality:
Plugins
Add capabilities without modifying core:
import { eventsPlugin } from '@nextrush/events';
import { controllersPlugin } from '@nextrush/controllers';
app.plugin(eventsPlugin());
app.plugin(controllersPlugin({ router, root: './src' }));Guards
Control access to routes declaratively:
@UseGuard(AuthGuard)
@UseGuard(RoleGuard('admin'))
@Controller('/admin')
class AdminController {
@Get('/dashboard')
dashboard() {
return { admin: true };
}
}What You Should Learn First
Context API
Understand the ctx object—it's your primary interface for everything. Read Context →
Middleware
Learn the onion model. It determines execution order and error handling. Read Middleware →
Routing
Map URLs to handlers efficiently with radix tree routing. Read Routing →
Mental Model Summary
| Concept | Responsibility | Key Insight |
|---|---|---|
| Application | Orchestration | Holds everything together, manages lifecycle |
| Context | Request/Response | Fresh per-request, mutable state for sharing |
| Middleware | Transformation | Onion model—before, next(), after |
| Routing | URL Matching | O(k) radix tree, params and wildcards |
| Plugins | Extension | Add features without modifying core |
| Guards | Access Control | Boolean gatekeepers for routes |
Common Misconception
Middleware order matters. Error handlers must come first. Body parsers must run before you access
ctx.body. If something isn't working, check your registration order.