Server Entry File
What is UserServerEntry?
UserServerEntry is the type for the object you export from your server entry file. It combines:
- Routing configuration (
routes,fetch,middleware,error) - Server options (including runtime-specific options like
bun,deno,node)
export type UserServerEntry = ServerOptions & RoutingOptions
Basic Example
// server.ts
export default {
port: 3000,
routes: {
"/": () => new Response("Hello World"),
"/api/users": {
GET: () => new Response("List users"),
POST: () => new Response("Create user"),
},
},
fetch: () => new Response("Not Found", { status: 404 }),
};
Export Formats
The CLI supports two main export formats:
1. Default Export (Object)
Export all configuration as a single default object:
// server.ts
export default {
port: 3000,
routes: {
"/": () => new Response("Hello"),
},
fetch: () => new Response("Not Found", { status: 404 }),
middleware: [],
};
2. Named Exports
Export each configuration field separately:
// server.ts
export const port = 3000;
export const routes = {
"/": () => new Response("Hello"),
};
export const fetch = () => new Response("Not Found", { status: 404 });
export const middleware = [];
Both formats are equivalent. The CLI automatically detects and normalizes them.
Available Fields
Routing Configuration
routes
Declarative route table matched before the fallback fetch handler.
export default {
routes: {
"/": () => new Response("Home"),
"/about": () => new Response("About"),
"/api/*": () => new Response("API"),
},
};
fetch
Fallback request handler for unmatched routes.
export default {
routes: {
"/": () => new Response("Home"),
},
fetch: () => new Response("Not Found", { status: 404 }),
};
middleware
Global middleware array executed before handlers.
import { log } from "sevok/log";
export default {
middleware: [log()],
fetch: () => new Response("ok"),
};
middlewareResolver
Resolver for named middleware entries.
export default {
middleware: ["auth", "cache"],
middlewareResolver: (name) => {
if (name === "auth") return async (ctx, next) => next(ctx);
if (name === "cache") return async (ctx, next) => next(ctx);
},
fetch: () => new Response("ok"),
};
error
Error handler for request processing failures.
export default {
error: (error) => {
console.error(error);
return new Response("Internal Server Error", { status: 500 });
},
fetch: () => new Response("ok"),
};
Server Options
port
Listening port (default: PORT env or 3000).
export default {
port: 8080,
fetch: () => new Response("ok"),
};
hostname
Listening host (default: HOST env or all interfaces).
export default {
hostname: "127.0.0.1",
fetch: () => new Response("ok"),
};
reusePort
Allow multiple processes to bind the same port.
export default {
reusePort: true,
fetch: () => new Response("ok"),
};
protocol
Use "http" or "https".
export default {
protocol: "https",
tls: {
cert: "./cert.pem",
key: "./key.pem",
},
fetch: () => new Response("ok"),
};
tls
TLS certificate configuration.
export default {
tls: {
cert: "./certs/cert.pem",
key: "./certs/key.pem",
passphrase: "secret",
},
fetch: () => new Response("ok"),
};
silent
Disable startup logging.
export default {
silent: true,
fetch: () => new Response("ok"),
};
gracefulShutdown
Enable graceful shutdown on SIGINT/SIGTERM.
export default {
gracefulShutdown: true,
fetch: () => new Response("ok"),
};
Or with custom timeouts:
export default {
gracefulShutdown: {
gracefulTimeout: 10,
forceTimeout: 5,
},
fetch: () => new Response("ok"),
};
manual
Prevent automatic server start (useful for testing).
export default {
manual: true,
fetch: () => new Response("ok"),
};
Runtime-Specific Options
bun
Bun-specific options merged into Bun.serve().
export default {
bun: {
idleTimeout: 10,
development: false,
},
fetch: () => new Response("ok"),
};
See Bun.serve options for available fields.
deno
Deno-specific options merged into Deno.serve().
export default {
deno: {
signal: AbortSignal.timeout(30_000),
onListen: (info) => console.log(`Listening on ${info.hostname}:${info.port}`),
},
fetch: () => new Response("ok"),
};
See Deno.ServeOptions for available fields.
node
Node.js-specific options including HTTP/HTTPS/HTTP2 server options.
export default {
node: {
http2: true,
requestTimeout: 30_000,
onError: (error) => {
console.error(error);
return new Response("Error", { status: 500 });
},
},
fetch: () => new Response("ok"),
};
Available fields:
- Standard Node.js server options (
requestTimeout,keepAliveTimeout, etc.) http2: Enable HTTP/2 (requires TLS)onError: Custom error handler for Node.js adapter
Complete Example
Using Default Export
// server.ts
import { log } from "sevok/log";
import { serveStatic } from "sevok/static";
export default {
port: 3000,
hostname: "127.0.0.1",
gracefulShutdown: true,
middleware: [
log(),
serveStatic({ dir: "./public" }),
],
routes: {
"/": () => new Response("Home"),
"/api/users": {
GET: () => new Response("List users"),
POST: () => new Response("Create user"),
},
"/api/users/:id": {
GET: (ctx) => new Response(`User ${ctx.params.id}`),
PUT: (ctx) => new Response(`Update user ${ctx.params.id}`),
DELETE: (ctx) => new Response(`Delete user ${ctx.params.id}`),
},
},
fetch: () => new Response("Not Found", { status: 404 }),
error: (error) => {
console.error(error);
return new Response("Internal Server Error", { status: 500 });
},
};
Using Named Exports
// server.ts
import { log } from "sevok/log";
import { serveStatic } from "sevok/static";
export const port = 3000;
export const hostname = "127.0.0.1";
export const gracefulShutdown = true;
export const middleware = [
log(),
serveStatic({ dir: "./public" }),
];
export const routes = {
"/": () => new Response("Home"),
"/api/users": {
GET: () => new Response("List users"),
POST: () => new Response("Create user"),
},
"/api/users/:id": {
GET: (ctx) => new Response(`User ${ctx.params.id}`),
PUT: (ctx) => new Response(`Update user ${ctx.params.id}`),
DELETE: (ctx) => new Response(`Delete user ${ctx.params.id}`),
},
};
export const fetch = () => new Response("Not Found", { status: 404 });
export const error = (error: unknown) => {
console.error(error);
return new Response("Internal Server Error", { status: 500 });
};
Notes
- The CLI automatically injects logging and static file middleware
- Use
--prodflag to disable watch mode and enable production defaults