Introduction
ExisJS is an opinionated web framework for building TypeScript backends on Node.js. It brings convention-over-configuration and automatic file-system routing to backend API development.
Rather than manually assembling, wiring, and maintaining separate third-party libraries for routing, input validation, dependency injection, OpenAPI documentation, rate limiting, and background task scheduling, ExisJS provides an integrated standard library in a lightweight, pure TypeScript core with no native add-ons.
Why ExisJS?
TypeScript backend development often faces two approaches:
- Micro-frameworks (Express, Fastify): Require developers to manually select, wire, and maintain middleware packages for validation, OpenAPI schemas, dependency injection, and security headers. Over time, projects diverge in structure and maintenance overhead increases.
- Heavy enterprise frameworks: Introduce deep class hierarchies, verbose configuration modules, and steep learning curves.
ExisJS combines convention-based file routing, built-in standard modules, and a lean runtime with support for both functional and object-oriented paradigms.
Architectural Pillars
┌─────────────────────────────────────────────────────────────────────────────┐│ ExisJS Application ││ Functional Paradigm │ Class-Based (OOP) Paradigm ││ controller(), route.get(), tex │ @Controller(), @Get(), @Injectable │└──────────────────────────────────────┬──────────────────────────────────────┘ │┌──────────────────────────────────────▼──────────────────────────────────────┐│ TypeScript HTTP Pipeline ││ Request Context (ExisRequest/Response) · Hierarchical Boundaries · Swagger ││ Rate Limiting · Helmet Headers · CSRF · Idempotency · Telemetry │└──────────────────────────────────────┬──────────────────────────────────────┘ │┌──────────────────────────────────────▼──────────────────────────────────────┐│ Runtime Core ││ Radix-Tree Router │ Compiled tex Validators │ CIDR IP Filter ││ Secure Body Parser │ Bounded In-Memory Caches │└─────────────────────────────────────────────────────────────────────────────┘1. File-System Routing
The file-system routing engine scans the src/http directory and compiles route paths into a radix tree at startup. Purely static paths resolve through an exact-match table; parameterized paths walk the tree with no per-request parsing of the route definitions.
2. Dual-Paradigm Parity
ExisJS supports a functional and a class-based (OOP) paradigm. Both share the router, validation, boundaries, error handling, response handling and route authorization; a project uses one of them throughout (exisjs dev and exisjs build stop with the file names if they are mixed). Class-based controllers add decorator and dependency-injection work per request, so functional routes are somewhat faster.
- Functional:
controller(),route.get(),route.post(),defineBoundary(),inject(). - Class-Based (OOP):
@Controller(),@Get(),@Post(),@Boundary(),@Injectable().
3. Integrated Schema Validation & OpenAPI 3.1
The built-in tex schema builder provides runtime type validation, parameter coercion, and automated OpenAPI 3.1 schema generation. Every schema defined on a route automatically surfaces in the interactive Swagger UI (/docs) and exports types for compile-time frontend client generation.
4. Hierarchical Security & Error Boundaries
Directory-based boundary.ts files allow you to declare scoped authentication guards, rate limits, CORS configurations, and error handlers that cascade down folder trees without manual middleware repetition.
5. No Native Dependencies
The core is pure TypeScript. There are no platform binaries to download or compile, so ExisJS installs the same way on every OS and CPU architecture that Node.js supports.
Feature Matrix
| Feature Area | ExisJS Built-In Capability | Benefit |
|---|---|---|
| Routing | File-system route discovery (src/http/**/route.ts) | No manual router mounting or path strings |
| Validation | tex Schema Validator (compiled once per schema) | Fast parsing, zero-crash sanitization, automatic OpenAPI types |
| Documentation | Automatic Swagger / OpenAPI 3.1 at /docs | Self-updating interactive documentation with zero manual sync |
| Traffic Control | Native Token Bucket Rate Limiting & CIDR Filtering | Fast DoS prevention and client throttling |
| Security | Security headers (helmet), CSRF, HPP, Body Sanitization | Secure defaults without installing separate packages |
| Dependency Injection | Type-safe IoC container with circular ref resolution | Clean service decoupling with @Injectable() and inject() |
| Background Tasks | In-process cron scheduler with drift correction | Scheduled jobs without external cron infrastructure |
| Observability | Native OpenTelemetry integration (exisjs/telemetry) | Standardized traces, metrics, and structured Pino logging |
Quickstart Comparison
ExisJS allows you to choose the paradigm that best matches your team's conventions.
Functional Paradigm
import { controller, route } from 'exisjs/router'import { tex } from 'exisjs/validator'
// 1. Define runtime validation schemaconst CreateUserSchema = tex.object({ name: tex.string().min(2), email: tex.string().email(), role: tex.enum(['admin', 'member']).default('member'),})
// 2. Export functional controllerexport default controller({ // GET /users listUsers: route.get('/', { summary: 'List all active users', handle: async () => { return [ { id: 1, name: 'Alice', role: 'admin' }, { id: 2, name: 'Bob', role: 'member' }, ] }, }),
// POST /users createUser: route.post('/', { summary: 'Create a new user', body: CreateUserSchema, handle: async ({ body }) => { return { id: Date.now(), name: body.name, email: body.email, role: body.role, } }, }),})Class-Based (OOP) Paradigm
import { Controller, Get, Post, Body, ApiOperation } from 'exisjs/decorators'import { tex } from 'exisjs/validator'
// 1. Define runtime validation schema & inferred typeconst CreateUserSchema = tex.object({ name: tex.string().min(2), email: tex.string().email(), role: tex.enum(['admin', 'member']).default('member'),})
type CreateUserDto = typeof CreateUserSchema.infer
// 2. Export class controller@Controller()export default class UsersController { @Get('/') @ApiOperation({ summary: 'List all active users' }) async listUsers() { return [ { id: 1, name: 'Alice', role: 'admin' }, { id: 2, name: 'Bob', role: 'member' }, ] }
@Post('/') @ApiOperation({ summary: 'Create a new user' }) async createUser(@Body(CreateUserSchema) body: CreateUserDto) { return { id: Date.now(), name: body.name, email: body.email, role: body.role, } }}The Request Lifecycle
Every HTTP request dispatched through ExisJS follows a predictable, high-performance execution lifecycle:
Incoming Request │ ▼1. Radix Path Match │ ▼2. CIDR IP Filter & Rate Limit Check │ ▼3. Root Boundary (Global Middleware & CORS) │ ▼4. Nested Folder Boundaries (Scoped Guards & Interceptors) │ ▼5. Request Body Parsing & TexValidation │ ▼6. Controller Handler Execution (Functional or Class Method) │ ▼7. Response Envelope / Stream Serialization │ ▼Client ResponseGetting Started
Option 1: Create a New Project (Recommended)
Use the interactive scaffolding CLI to create a configured ExisJS project:
npm create exisjs@latest my-backendcd my-backendnpm run devThe CLI configures TypeScript, builds the initial directory structure, and starts the development server at http://localhost:4000.
Option 2: Add to an Existing Project
Install the framework into an existing Node.js project:
npm install exisjsnpm install -D @exisjs/cli typescriptexisjs is the runtime your server needs in production; @exisjs/cli is the exisjs command (dev server, build, tests), a development tool.
Create an application configuration file:
import type { ExisConfig } from 'exisjs/config'
const config: ExisConfig = { port: Number(process.env.PORT) || 4000, cors: { origin: '*', methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], },}
export default configAdd your first endpoint in src/http/health/route.ts:
import { controller, route } from 'exisjs/router'
export default controller({ check: route.get('/', { summary: 'Health check endpoint', handle: () => ({ status: 'ok', uptime: process.uptime() }), }),})Next Steps
Explore the documentation to learn more about developing with ExisJS:
- Installation Guide: CLI flags, system prerequisites, and TypeScript setup.
- Project Structure: Directory layout and architectural conventions.
- Routing & Endpoints: Dynamic parameters, catch-alls, and nested route groups.
- Validation Guide: Complete schema reference, data coercion, and custom rules.
- Boundaries & Middleware: Hierarchical middleware cascading and error boundaries.