Published on JSR · @codexa/core

The plugin-first framework
for building Deno APIs

A plugin-first HTTP framework for Deno. Every route, middleware, and service is a plugin with its own lifecycle, and the same app runs unchanged on Bun, Cloudflare Workers, and Node.js.

16
focused subpaths
4
runtimes supported
100%
JSR score
$ deno add jsr:@codexa/core
Runs wherever the Fetch API runs
DenoBunCloudflare WorkersNode.js

A plugin owns everything it needs

A route, a middleware, a background job, all of it lives inside setup(scope). Another plugin can only reach it through dependsOn and exposeService, so a large application stays predictable as more plugins are added.

Read about plugins
main.ts
import { createApp, definePlugin } from '@codexa/core/http'

const healthPlugin = definePlugin({
  name: 'health',
  setup(scope) {
    scope.route({
      method: 'GET',
      path: '/health',
      handler: (ctx) => ctx.json({ ok: true }),
    });
  },
});

const app = createApp('api').install(healthPlugin);

// runs the same way on Deno, Bun, and Workers
Deno.serve(app.dispatch);

One package, sixteen focused subpaths

@codexa/core/http@codexa/core/openapi@codexa/core/config@codexa/core/bus@codexa/core/store@codexa/core/cache@codexa/core/storage@codexa/core/providers@codexa/core/logger@codexa/core/crypto@codexa/core/hash@codexa/core/device@codexa/core/ttl@codexa/core/response@codexa/core/query@codexa/core/cli

Import only what a project uses. A route-only service never loads the MongoDB driver or the Redis client.

Built as small, composable pieces

Every part of the framework is designed to be used on its own or combined into a full backend.

Plugin-first architecture

Every route, middleware, and background job is owned by a plugin with its own name, lifecycle hooks, and metadata.

Typed service exposure

A plugin only reaches another through dependsOn and exposeService, so a growing app stays predictable instead of tangled.

Runtime-neutral dispatch

app.dispatch is a plain (Request) => Promise<Response> function. The same app runs on Deno, Bun, Cloudflare Workers, and Node.js.

Real OpenAPI 3.1 documents

Generate a spec straight from your route metadata, no separate annotation layer or schema duplication.

One storage interface, four providers

Local disk, S3, Cloudinary, and ImageKit behind the same upload, delete, and signed-URL API.

Local or distributed event bus

Start in-process with zero setup, then hand it a Redis client to make emit cross-process without changing call sites.

Powered by JetRouter

JetRouter matches static, parameterized, and wildcard routes, while Codexa adds versioned routes and per-route middleware.

A CLI for plugin distribution

Pull a plugin’s source from a pinned Git ref into your project, with full rollback if any step fails.

HTTP benchmarks with JetRouter

The local JetRouter-based build measured alongside Express, Oak, Fastify, Hono, NestJS, and Thunder. See every workload, the raw Deno baseline, and measured variation in the benchmark docs.

Client CPU crossed the warning threshold in 68/108 samples. Treat these as local stack measurements; close differences may be noise.

Median completed responses per second across 3 rounds. Each row includes the run range, median per-run p99, and throughput variation (CV). Rates include framework and runtime overhead.

Hono / Deno
30,064 req/sp99 3.0 ms · CV 6.1%26,393–30,255
Thunder / Deno
27,891 req/sp99 3.0 ms · CV 8.0%23,564–28,230
Raw Deno.serve (manual routes)
27,682 req/sp99 4.0 ms · CV 4.5%27,351–30,207
Fastify / Node
22,975 req/sp99 4.0 ms · CV 6.2%21,823–25,313
Codexa Core + JetRouter / Deno
22,469 req/sp99 9.0 ms · CV 26.8%11,795–22,677
NestJS (Express adapter) / Node
16,580 req/sp99 4.0 ms · CV 8.6%14,218–17,489
Express / Node
16,396 req/sp99 6.0 ms · CV 28.5%8,693–18,131
Oak / Deno
14,263 req/sp99 10.0 ms · CV 14.2%11,596–16,506

Three steps to a running server

01

Define a plugin

A plugin registers everything it owns, routes, middleware, services, in one setup function.

definePlugin
02

Install it into an app

createApp takes as many plugins as your app needs, each isolated behind its own name.

createApp().install(plugin)
03

Ship app.dispatch anywhere

Hand dispatch to Deno.serve, Bun.serve, a Cloudflare Worker, or call it directly in a test.

Deno.serve(app.dispatch)

Build your first plugin in three minutes

Published on JSR at @codexa/core, with a JSR score of 100 percent and support confirmed for Deno, Node.js, Bun, and browsers.