TomoeJS — The Art of Perfect Balance.
Ultra-Fast · Contract-Driven · Compile-Time Type Safety · Universal Web Standards Core
Tomoe (巴) is a next-generation, high-performance web framework designed with a single goal: bridging the gap between strict backend correctness and supreme developer experience.
Embracing native Web Standard APIs (Request, Response, Headers, Cookies), TomoeJS is universally portable across Bun, Cloudflare Workers, Node.js, Deno, and Vercel. It eliminates the single largest flaw in modern web frameworks: unsafe, untyped middleware side-effects.
Important
TomoeJS is currently a release candidate. Review the production readiness checklist, deployment guide, release checklist, and security policy before production use.
- 🛡️ Contract-Driven Design: The first framework introducing Relics & Guards to enforce typed preconditions at boot time instead of throwing unexpected runtime errors in production.
- ⚡ Supreme Performance: Features a pre-compiled radix tree router and cached middleware onion runners to achieve maximum throughput.
- 🌐 Web Standards First: Zero-dependency wrapper that interacts directly with native Web standard objects like
RequestandResponse. - 🔌 Native WebSockets: Out-of-the-box WebSocket support with custom handshake header hooks and path parameter support.
- 🧰 End-to-End Type Safety: Generate a fully typed client SDK directly from your server type signature without codegen or build scripts.
- 🔮 Graph Compilation & Validation: Pre-compile routing tables, run validations, and audit middleware onion chains at startup.
Install TomoeJS using your preferred package manager:
# npm
npm install tomoejs@rc
# pnpm
pnpm add tomoejs@rc
# bun
bun add tomoejs@rc
# yarn
yarn add tomoejs@rcCreate an index.ts file to see TomoeJS in action:
import{Tomoe}from"tomoejs"constapp=newTomoe()// 1. Static responseapp.get("/",(c)=>c.text("Welcome to TomoeJS!"))// 2. Dynamic path parameters (automatically URL-decoded)app.get("/hello/:name",(c)=>{constname=c.param("name")// Automatically handles URL decoding (e.g. "%20" to " ")returnc.json({message: `Hello, ${name}!`})})exportdefaultappbun index.tsTo use standard Node.js environments, use the built-in HTTP server adapter:
import{Tomoe,createServer}from"tomoejs"constapp=newTomoe()app.get("/",(c)=>c.text("Hello from Node.js!"))constserver=createServer(app)server.listen(3000,()=>{console.log("Server listening at http://localhost:3000")})In traditional frameworks (Express, Fastify, Hono, Elysia), middleware injects values into the request context implicitly, leaving route handlers to blindly assume the values exist:
// ❌ Traditional (Unsafe): Will compile, but throws runtime errors if the auth middleware is missed or ordered incorrectly!app.use(authMiddleware)app.get("/me",(c)=>{constuser=c.get("user")// Typeless! Could be undefined if middleware failed or was skipped.returnc.json(user)})TomoeJS replaces implicit context manipulation with explicit dependency contracts called Relics & Guards. If a route handler depends on state (like a database connection or verified user), that dependency must be declared.
// 👑 TomoeJS (Contract-Driven): Fully typed at compile time. // If authRelic isn't mounted, TS compiler blocks it, and app.compile() throws at startup.app.get("/me",authRelic,(ctx)=>{// ctx.user is fully typed and guaranteed to exist!returnctx.json(ctx.user)})By resolving dependencies before invoking the route handler, TomoeJS guarantees compile-time safety and prevents runtime crashes caused by misordered middleware.
Benchmarks are run using Autocannon with 100 concurrent connections in an isolated environment. The socket ports and server processes are cleared programmatically between runs to ensure accuracy.
- Operating System: Windows 11
- Node.js version:
v24.13.0| Bun version:v1.3.3 - Frameworks Tested: TomoeJS
v1.0.0-rc.3, Honov4.12.23, Elysiav1.4.28
| Framework | Requests / Sec (Throughput) | Avg Latency | P99 Latency |
|---|---|---|---|
| TomoeJS (Bun) | 45,131 req/s | 1.58 ms | 5 ms |
| Hono (Bun) | 42,691 req/s | 1.91 ms | 4 ms |
| Elysia (Bun) | 41,987 req/s | 1.96 ms | 4 ms |
| Hono (Node) | 29,480 req/s | 2.92 ms | 7 ms |
| TomoeJS (Node) | 20,369 req/s | 4.41 ms | 11 ms |
| Framework | Requests / Sec (Throughput) | Avg Latency | P99 Latency |
|---|---|---|---|
| TomoeJS (Bun) | 45,853 req/s | 1.54 ms | 4 ms |
| Elysia (Bun) | 39,043 req/s | 2.21 ms | 4 ms |
| Hono (Bun) | 36,856 req/s | 2.30 ms | 4 ms |
| Hono (Node) | 29,067 req/s | 3.00 ms | 6 ms |
| TomoeJS (Node) | 22,600 req/s | 3.95 ms | 8 ms |
| Framework | Requests / Sec (Throughput) | Avg Latency | P99 Latency |
|---|---|---|---|
| Elysia (Bun) | 37,878 req/s | 2.29 ms | 4 ms |
| TomoeJS (Bun) | 33,573 req/s | 2.41 ms | 6 ms |
| Hono (Bun) | 31,886 req/s | 2.54 ms | 6 ms |
| Hono (Node) | 23,374 req/s | 3.76 ms | 8 ms |
| TomoeJS (Node) | 20,616 req/s | 4.37 ms | 9 ms |
| Framework | Messages / Sec (Throughput) | Avg Latency | P99 Latency |
|---|---|---|---|
| Elysia (Bun) | 45,535 msg/s | 0.43 ms | N/A |
| 👑 TomoeJS (Node) | 45,448 msg/s | 0.42 ms | N/A |
| Hono (Bun) | 44,159 msg/s | 0.44 ms | N/A |
| Hono (Node) | 43,964 msg/s | 0.45 ms | N/A |
| TomoeJS (Bun) | 27,759 msg/s | 0.69 ms | N/A |
- Native WebSocket API
- End-to-End Type-Safe Client SDK
- OpenAPI Specs & Swagger UI
- Graph Compilation & Inspection
- Runtimes & Deployment Matrix
- Error Handling (Functional & Thrown)
TomoeJS implements a high-performance radix tree router featuring dynamic path parameters, wildcard support, and fast paths for static routes.
constapp=newTomoe()// Static routeapp.get("/api/v1/status",(ctx)=>ctx.json({ok: true}))// Path parameters (inferred in types, URL-decoded automatically)app.get("/api/users/:userId/posts/:postId",(ctx)=>{const{ userId, postId }=ctx.paramsreturnctx.json({ userId, postId })})// Wildcard routesapp.get("/assets/*",(ctx)=>{constfilepath=ctx.param("*")returnctx.text(`Requested asset: ${filepath}`)})Organize large projects cleanly using either standalone sub-routers or inline protected scope routes.
Perfect for separating business domains into modular files:
import{Tomoe}from"tomoejs"constanimeRouter=newTomoe()animeRouter.get("/list",(c)=>c.json(["FMA","Hunter x Hunter"]))animeRouter.get("/:id",(c)=>c.json({id: c.param("id")}))constapp=newTomoe()app.route("/api/anime",animeRouter)// Mounted at `/api/anime/list` and `/api/anime/:id`Enforce contract middleware on a group of nested routes:
app.scope("/admin",adminAccessRelics,(scoped)=>{scoped.get("/dashboard",(ctx)=>{// Access typed properties inherited from scope relicsreturnctx.json({user: ctx.user,org: ctx.org})})})Middlewares intercept incoming requests to manipulate context, handle telemetry, or manage CORS headers.
importtype{Middleware}from"tomoejs"constresponseTime=(): Middleware=>{returnasync(ctx,next)=>{conststart=performance.now()constresponse=awaitnext()constduration=(performance.now()-start).toFixed(2)response.headers.set("X-Response-Time",`${duration}ms`)returnresponse}}app.use(responseTime())import{cors,logger,csrf,rateLimit}from"tomoejs"// Cross-Origin Resource Sharingapp.use(cors({origin: ["https://example.com"]}))// Console Request Loggerapp.use(logger())// Cross-Site Request Forgery Protectionapp.use(csrf({origin: ["https://trusted.com"]}))// In-Memory Rate Limitingapp.use(rateLimit({windowMs: 60000,max: 100}))Handlers receive a unified Context object, providing helpers to parse inputs and construct Web Standard responses.
ctx.req: The native WebRequestinstance.ctx.query(key): Read a query string parameter.ctx.queries: Get all query parameters as a key-value object.ctx.header(name): Read a request header (case-insensitive).ctx.header(name, value): Queue a header to be written to the response.ctx.json(data, init?): Return a JSON response with matching content-type.ctx.text(body, init?): Return a plain text response.ctx.html(markup, init?): Return an HTML response.ctx.redirect(url, status?): Perform a redirection response.
TomoeJS provides an RFC 6265 secure, lazy-parsed cookie API:
app.get("/auth",(ctx)=>{// Read request cookieconsttoken=ctx.cookie("session_token")// Queue response cookiectx.setCookie("user_id","12345",{httpOnly: true,secure: true,sameSite: "Strict",maxAge: 3600})returnctx.json({loggedIn: !!token})})You can read payloads standardly or use Zod validations to safely parse incoming data.
Ideal for stream-friendly handlers with zero allocations:
app.post("/upload",async(ctx)=>{constjsonBody=awaitctx.req.json()consttextBody=awaitctx.req.text()constformData=awaitctx.req.formData()// parses multipart uploadsconstarrayBuffer=awaitctx.req.arrayBuffer()returnctx.json({received: true})})Injects pre-validated bodies directly into ctx.body:
import{relic}from"tomoejs"import{z}from"zod"constuserSchema=z.object({username: z.string().min(3),email: z.string().email()})app.post("/register",relic.body(userSchema),(ctx)=>{// Autocomplete-ready and validated at runtimeconst{ username, email }=ctx.bodyreturnctx.json({status: "created", username })})Create modular, chainable components to manage authentication, session state, or database connections.
- Relics (
relic): Compute values asynchronously and inject them intoctx. - Guards (
guard): Enforce security rules. Cannot inject variables but can depend on other relics. - Unite (
unite): Merge multiple Relics and Guards into a single cohesive route contract.
import{relic,guard,err,Unauthorized,Forbidden,unite}from"tomoejs"// 1. Create a relic that injects a verified 'user'constauthenticateUser=relic("user",async(ctx)=>{consttoken=ctx.header("Authorization")if(!token)returnerr(Unauthorized)// Returns a structured functional errorconstuser=awaitdb.verifyToken(token)if(!user)returnerr(Unauthorized)returnuser})// 2. Create a guard that checks role requirementsconstcheckAdminRole=guard(async(ctx,use)=>{constuser=use(authenticateUser)// Resolve user dependency safelyif(!user.isAdmin)returnerr(Forbidden)})// 3. Chain them using unite()constadminAccess=unite(authenticateUser,checkAdminRole)// 4. Protect a scoped routing pathapp.scope("/admin",adminAccess,(router)=>{router.get("/metrics",(ctx)=>{// Both user validation and role authorization are guaranteed herereturnctx.json({activeUser: ctx.user.username,systemHealth: "ok"})})})TomoeJS supports schema validation out of the box using Zod, Valibot, ArkType, or TypeBox.
import{z}from"zod"import{unite,relic}from"tomoejs"constitemBody=z.object({name: z.string()})constqueryPage=z.object({page: z.coerce.number().default(1)})app.post("/items",unite(relic.body(itemBody),relic.query(queryPage)),(ctx)=>{const{ name }=ctx.bodyconst{ page }=ctx.queryreturnctx.json({ name, page })})Supported natively on Node.js (via the createServer adapter) and other runtimes. WebSocket handlers are integrated directly into the core router gateway, supporting relics and parameters.
import{Tomoe,createServer}from"tomoejs"constapp=newTomoe()app.ws("/chat/:roomId",{// Protocol Handshake Hookhandshake(ctx){constrequestedProtocol=ctx.header("Sec-WebSocket-Protocol")if(requestedProtocol){ctx.header("Sec-WebSocket-Protocol",requestedProtocol)}},// Connection openedopen(ws,socketCtx){console.log(`Connected to room: ${socketCtx.params.roomId}`)ws.send(JSON.stringify({status: "connected"}))},// Message receivedmessage(ws,data,socketCtx){ws.send(JSON.stringify({echo: data}))},// Connection closedclose(ws,socketCtx){console.log(`Disconnected from room: ${socketCtx.params.roomId}`)}})// Secure WebSocket routes using Relicsapp.ws("/secure-feed",authRelic,{open(ws,socketCtx){constuser=socketCtx.relics.userws.send(`Hello secure user, ${user.name}!`)}})constserver=createServer(app)server.listen(3000)Share type definitions directly from your backend instance to your frontend to generate a type-safe client SDK without external code generation.
constapp=newTomoe().post("/posts",relic.body(postSchema),(ctx)=>{returnctx.json({id: "100"})})exporttypeAppRouter=typeofappimport{createClient}from"tomoejs"importtype{AppRouter}from"./server"constclient=createClient<AppRouter>("http://localhost:3000")// Inputs (body, params, headers, query) are validated at compile-time!const{ data, error, status }=awaitclient("/posts").post({body: {title: "Next-Gen Web Frameworks",content: "..."}})TomoeJS automatically parses Zod/Valibot/TypeBox schema dependencies registered in route relics to generate full OpenAPI v3 specs and serve Swagger UI.
import{swagger}from"tomoejs"constapp=newTomoe()// Setup docs endpointswagger(app,{title: "TomoeJS Core Services",version: "1.0.0",path: "/docs",// Swagger UI endpointspecPath: "/openapi.json"// OpenAPI Spec endpoint})Compile the route radix tree, validate relic dependency chains, and cache middleware onion pipelines at startup to eliminate runtime cold starts.
constapp=newTomoe()// Compiles the routing tree. Called automatically on first request.app.compile()// Audit the registered routing structureconst{ routes, stats }=app.graph()console.log(`Audit complete: registered ${routes.length} active endpoints.`)TomoeJS interacts with standard request/response models directly, making it universally compatible across JS runtimes.
exportdefaultappLaunch with bun index.ts.
exportdefault{fetch: app.fetch}Deno.serve((req)=>app.fetch(req))import{createServer}from"tomoejs"constserver=createServer(app)server.listen(3000)TomoeJS utilizes functional result mapping to minimize V8 call-stack serialization overhead, but fully supports standard throw-catch exceptions.
Includes BadRequest, Unauthorized, Forbidden, NotFound, MethodNotAllowed, Conflict, TooManyRequests, ServerError, and more.
import{HttpError,httpError}from"tomoejs"// Simple helperconstTeapotError=httpError(418,"I'm a teapot")// Rich Custom Error DetailsconstpaymentErr=newHttpError(402,"Payment Failed",{reason: "INSUFFICIENT_FUNDS"})// Local scope overrideapp.scope("/api",authRelic,(scoped)=>{scoped.onError(401,(ctx)=>{returnctx.json({error: "Access Denied: Please authenticate"},{status: 401})})})// Global application fallbackapp.onError((error,ctx)=>{console.error("Critical Exception:",error)returnctx?.json({error: "Internal Server Error"},{status: 500})??newResponse("Internal Server Error",{status: 500})})Distributed under the MIT License. Built with 🌸 and perfect balance.
