ExpressAPI

Your server type is the contract.

Stop maintaining OpenAPI files, generators, and hand-written clients. Chain routes on Deno, export the type, call them from anywhere. Fully typed.

Deno nativeWeb StandardsExpress-like DXMITJSR @webtools/expressapiv0.9.3
The problem

Two sources of truth always drift.

Most stacks treat types as an afterthought. You ship routes, then a second contract, then a generated client, and hope they stay in sync.

Express / Fastify

Familiar and fast to ship. Typed clients mean OpenAPI, codegen, or manual duplication. The contract lives outside the code that actually runs.

Hono

Excellent Web Standards story. End-to-end types usually mean RPC helpers or parallel schemas, still a second layer to maintain.

tRPC

Great types, different paradigm. Procedure-based RPC, tighter coupling, and a jump away from plain HTTP routing many teams already know.

What you actually want

Write HTTP routes once. Keep Express-shaped DX. Get a client that already knows every URL, param, body, and response, without generating a single file.

Why teams pick it

More than types.

Type safety is the headline. Day to day you also get a familiar API, composable routers, and batteries that usually mean extra packages.

Express muscle memory

get/post/use, params, middleware. Your team already knows the shape. Deno and Web Standards underneath.

One type, zero generators

Export typeof server. HttpClient checks URLs, methods, bodies, and responses at compile time. No OpenAPI sync job.

Typed composition

Middleware declares what it adds to req.data. Nested routers declare what they need. Wrong order fails in the editor.

Batteries included

Built-in CORS, schema validation, modular routers, custom 404/errors, and server.fetch for portless tests.

Features

The pieces you reach for every day.

Not a kitchen sink. The surface that makes Express-shaped APIs feel complete on Deno.

Routing

Modular routers

Mount Router trees with prefixes. Parent context requirements are checked when you mount. Paths normalize so matching stays consistent.

Middleware

Typed middleware chain

.use() or per-route. Each step can add context or short-circuit. Registration order matches at runtime and in the type system.

Schemas

Validation that narrows

Built-in z schemas on body, query, and params. Invalid requests return 400 before your handler. Types update with the schema.

Client

HttpClient from import type

No runtime link to the server module. Separate packages work. Wrong routes and bodies fail before you hit the network.

CORS

CORS without a plugin

Defaults that work, per-router rules, OPTIONS preflight. Override with .cors() when you need credentials or dynamic origins.

Testing

server.fetch

Call your app as a standard fetch handler. No port, no process. Pair with Deno.test for fast route checks.

The bet

One type. Zero generators.

ExpressAPI makes the router type the contract. Inference does the rest at compile time. Nothing extra ships at runtime.

01

Chain routes, export the type

Every chained call widens the server type. Export typeof server and that is your API surface.

02

Call it from any package

HttpClient only needs an import type. No server starts. No runtime dependency on your route module.

03

Stay on Web Standards

Request, Response, fetch, Deno. Express-inspired syntax without inventing a parallel HTTP universe.

Why not X

Where ExpressAPI wins.

Pick the tool that matches the job. ExpressAPI is for Deno APIs that want Express-shaped routing and a typed client without codegen.

ExpressHonoFastifytRPCExpressAPI
Primary runtimeNodeMultiNodeNode / TSDeno
FeelRoutes + MWUltra-light WSPerf + pluginsRPC proceduresExpress-like
Typed HTTP clientManual / OpenAPIRPC / schemasManual / schemaYesYes, no codegen
Contract sourceOften externalSchemas / RPCJSON SchemaProceduresRouter type
Typed middleware contextNoPartialDecorators / typesContextTAdds / TNeeds

“I already use Hono.”

Stay on Hono if multi-runtime is the priority. Choose ExpressAPI when you want Deno + Express muscle memory + a typed client with zero generation step.

“tRPC already gives me types.”

tRPC wins for procedure RPC. ExpressAPI wins when you want real HTTP routes, status codes, CORS, and a client that still feels like REST, fully typed.

“OpenAPI is fine.”

Until it drifts. Here the running router is the source of truth. No second file to keep honest.

“Is this only for Deno?”

Yes, by design. Built on Deno and Web Standards. If you need Node-first, Express or Fastify remain the better fit.

Convert

Try it on your next Deno API.

Add the package, chain a few routes, export the type. If the editor catches a bad client call before you run anything, that is the point.

deno add jsr:@webtools/expressapi