Introduction
High-performance, file-based REST API router for TypeScript. Zero runtime drift, cascading middleware context, and automatic client generation.
Taser.js is a modern, type-safe, file-based router designed for scalable Node.js and edge HTTP services. It bridges the gap between clean filesystem architecture and strict type safety.
Traditional Node.js routing forces you to write manual route registries, perform unsafe type assertions on req.user, and maintain separate client types that drift over time. Taser.js solves these challenges by treating the filesystem as the source of truth, cascading middleware state through directory layouts, and generating a 100% typed client SDK.
Layout Middleware
import { t } from "@taserjs/router";
import { unauthorized } from "@taserjs/router/reply";
// Applies to all routes under /users/*
export default t.layout("/users/*").use(async ({ req, ctx }, next) => {
const token = req.headers.get("authorization")?.replace(/^Bearer\s+/i, "");
const user = token ? await ctx.db.findUserByToken(token) : null;
if (!user) {
return unauthorized({ message: "Unauthorized" });
}
return next({ user });
});Route Handler
import { json, notFound, forbidden } from "@taserjs/router/reply";
import { z } from "zod";
import { t } from "@taserjs/router";
const GET = t
.get("/users/:id")
.params(z.object({ id: z.string().uuid() }))
.query(z.object({ includeProfile: z.coerce.boolean().default(false) }));
export default GET.handler(async ({ req, ctx, state }) => {
// req.params.id is typed as string (UUID)
// req.query.includeProfile is typed as boolean
// state contains data injected by layout middlewares
const isAdmin = await ctx.db.isUserAdmin(state.user.id);
if (!isAdmin) {
return forbidden({ message: "Forbidden" });
}
const user = await ctx.db.findUserById(req.params.id);
if (!user) {
return notFound({ message: "User not found" });
}
return json(user);
});Route Path Strings Are Generated Automatically
The path string passed to t.get(), t.post(), t.layout(), etc. is generated automatically by
the dev watcher (vite dev, next dev) or @taserjs/cli when route files are first created
(e.g. via touch src/routes/...). You do not need to author this string by hand.
Why Taser.js?
Deterministic File Routing
Drop .get.ts, .post.ts, or .put.ts files into your routes directory. Routes, parameters, and splats are discovered automatically with virtual module HMR.
Cascading Context Inference
Middleware state declared in folder layouts flows into the state facet for child routes with zero typecasting or global namespace pollution.
Compile-Time Return Contracts
Declare response schemas with .returns(). The TypeScript compiler verifies that your handler return shapes match your published API contracts.
Standard Schema Validation
Validate query parameters, path params, headers, and request bodies using Zod, ArkType, Valibot, or any Standard Schema library.
Vite Native & Nitro Presets
Vite-native development with virtual routing and instant HMR. Deploy anywhere using Nitro multi-cloud presets, or embed inside Next.js and host apps.
Zero-Drift Typed Client
Export your router type and call your backend using an auto-completing, fully typed client that guarantees 1:1 parity with server endpoints.
How Taser.js Works
Taser.js operates around a deterministic, fully type-safe request lifecycle:
Taser.js Request Execution Pipeline
Click any stage to inspect lifecycle execution, data flow, and type inference
TaserApp Dispatch
@taserjs/plugin and @taserjs/cli emit a static route manifest into routes.gen.ts. createTaserApp() registers composed handlers on a Hono TaserApp once; each request is served via the Web fetch API with no filesystem routing at runtime.
Execution Highlights
// createTaserApp(routeManifest, taser) at build time
export const app = /* Hono TaserApp */
// Per request (any host):
const response = await app.fetch(request)Vite-Powered Virtual Modules
Taser.js integrates with Vite via @taserjs/plugin/vite. Routes are loaded virtually during
development with instant HMR and bundled into optimized production artifacts via Nitro deployment
presets.
Scaffold with create-taserjs
Get up and running in seconds using the official scaffolding CLI. Customize your stack across five modular dimensions:
- Host Framework: Standalone Taser.js (
none),hono,express, orfastify. - Deployment Preset:
node-server,node-cluster,bun,deno-server,deno-deploy,cloudflare-module,vercel,aws-lambda,netlify, or standalone Vite (none). - Runtime Override: Explicit
nodeorbunexecution target for self-hosted presets. - Database & Driver: Drizzle, Prisma, or Kysely with SQLite, PostgreSQL, or MySQL drivers (
--db <odm>:<driver>). - Standard Add-ons: Zod, ArkType, or Valibot for schema validation; Pino or Winston for structured logging.
pnpm create taserjs@latest my-apiFor full flag definitions and project structure options, see the Quickstart Guide.
AI Agent Skill
Equip your AI coding assistant (Cursor, Claude Code, Windsurf, GitHub Copilot, Cline, Codex) with expert knowledge of Taser.js file routing conventions, cascading layouts, Standard Schema validation, and typed client RPC.
Install the official skill using the open agent skills CLI:
npx skills add taserjs/taserjs What the Skill Teaches Your Assistant
- Filesystem Conventions: Eliminates hallucinated routes by strictly adhering to verb suffixes (
.get.ts,.post.ts), dynamic parameters ($id), splats ($), and layout middleware. - Layout and Middleware Inheritance: Guides assistants to declare cascading layouts and middleware that flow into child routes via
statewithout unsafe type assertions. - Validation & Return Contracts: Guides assistants to declare schemas with Zod, ArkType, or Valibot while pairing status codes with standalone reply helpers (
json,created,notFound). - Host Migrations & Client RPC: Guides incremental migrations from Express, Fastify, and Hono using host pass-through adapters and generates typed
@taserjs/clientcalls.
Example Prompts
Once installed, your AI assistant will reference Taser.js rules automatically. Try prompts like:
"Set up Taser.js API routes in my Next.js project with Zod schema validation, an auth layout, and a typed client.""Create a type-safe POST /api/users endpoint in Taser.js with body validation and compile-time return contracts.""Migrate my existing Express routes to Taser.js using host pass-through without breaking current APIs."Quick Navigation
Explore the documentation to start building or migrating your existing server:
Quickstart Guide
Scaffold a complete, production-ready project in seconds using create-taserjs.
Migration Guide
Incrementally migrate existing Express or Fastify APIs with zero downtime using host pass-through.
Manual Installation
Configure Taser.js with Vite, Nitro deployment presets, Next.js, or host frameworks.
File-Based Routing
Master directory conventions, path params ($id), splats ($), and pathless layouts.
Validation & Standard Schema
Validate query, params, body, and state with Zod, ArkType, and Valibot.
Responses & Error Handling
Use reply helpers, stream responses, and catch unexpected errors cleanly.
Typed Client SDK
Consume your API endpoints in React, Vue, Svelte, or mobile apps with full type safety.