Getting Started
Quick Start (CLI)
Create a server entry:
export default {
fetch(req: Request) {
return Response.json({ hello: "world!" });
},
};
Then, run the server using your favorite runtime:
npx srvx
pnpx srvx
yarn dlx srvx
deno -A npm:srvx
bunx --bun srvx
Quick Start (API)
Instead of using the srvx CLI, you can directly import the serve method to define a self-listening server entry.
Create a server entry:
import { serve } from "srvx";
const server = serve({
fetch(request) {
return Response.json({ hello: "world!" });
},
});
Install srvx as a dependency:
npm i srvx
yarn add srvx
pnpm i srvx
bun i srvx
deno i npm:srvx
Then, run the server using your favorite runtime:
node server.mjs
deno run --allow-env --allow-net server.mjs
bun run server.mjs
TypeScript
Each entry only pulls in the types of the runtime it targets. The ambient type packages below are declared as optional peerDependencies, so nothing is installed unless you ask for it:
| Runtime | Types package | Needed by |
|---|---|---|
| Node.js | @types/node | srvx/node |
| Deno | @types/deno | srvx/deno |
| Bun | @types/bun | srvx/bun |
| Cloudflare Workers | @cloudflare/workers-types | srvx/cloudflare |
| AWS Lambda | @types/aws-lambda | srvx/aws-lambda |
Everything else — srvx/types, srvx/service-worker, srvx/static, srvx/log, srvx/body-limit, srvx/tracing, srvx/mtls and srvx/cli — needs none of them, so a project can type check with skipLibCheck: false:
import { serve } from "srvx/node"; // only needs `@types/node`
import { staticMiddleware } from "srvx/static"; // needs nothing
import type { ServerRequest } from "srvx/types"; // needs nothing
Runtime specific fields such as server.node, request.runtime.deno or the bun option are typed as soon as the types of that runtime are loaded, and stay loosely typed (Record<string, unknown>) otherwise — importing srvx/<runtime> anywhere in your project is enough to type them everywhere.
@types/deno references DOM types, so pair it with lib: ["esnext", "dom"].srvx entry covers every runtime, so it resolves all of the packages above at once. It also references cloudflare:workers, which @cloudflare/workers-types declares ambiently and therefore only resolves when that package is listed in tsconfig types — which in turn conflicts with @types/deno. Declare the module yourself to check that entry with skipLibCheck: false:declare module "cloudflare:workers" {
export const env: Record<string, unknown>;
}
Starter Examples
| Example | Source | Try |
|---|---|---|
aws-lambda | examples/aws-lambda | npx giget gh:h3js/srvx/examples/aws-lambda srvx-aws-lambda |
elysia | examples/elysia | npx giget gh:h3js/srvx/examples/elysia srvx-elysia |
express | examples/express | npx giget gh:h3js/srvx/examples/express srvx-express |
fastify | examples/fastify | npx giget gh:h3js/srvx/examples/fastify srvx-fastify |
h3 | examples/h3 | npx giget gh:h3js/srvx/examples/h3 srvx-h3 |
hello-world | examples/hello-world | npx giget gh:h3js/srvx/examples/hello-world srvx-hello-world |
hono | examples/hono | npx giget gh:h3js/srvx/examples/hono srvx-hono |
jsx | examples/jsx | npx giget gh:h3js/srvx/examples/jsx srvx-jsx |
node-handler | examples/node-handler | npx giget gh:h3js/srvx/examples/node-handler srvx-node-handler |
service-worker | examples/service-worker | npx giget gh:h3js/srvx/examples/service-worker srvx-service-worker |
streaming | examples/streaming | npx giget gh:h3js/srvx/examples/streaming srvx-streaming |
tracing | examples/tracing | npx giget gh:h3js/srvx/examples/tracing srvx-tracing |
websocket | examples/websocket | npx giget gh:h3js/srvx/examples/websocket srvx-websocket |