Application
bootstrap/app.ts is the single wiring point for a Rudder app. It builds an Application instance using a fluent configurator, registers route loaders, middleware, and exception handlers, and returns a Rudder runtime ready to handle HTTP requests.
// bootstrap/app.ts
import 'reflect-metadata'
import 'dotenv/config'
import { Application } from '@rudderjs/core'
import { RateLimit } from '@rudderjs/middleware'
import config from '../config/index.ts'
import providers from './providers.ts'
export default Application.configure({ config, providers })
.withRouting({
web: () => import('../routes/web.ts'),
api: () => import('../routes/api.ts'),
commands: () => import('../routes/console.ts'),
})
.withMiddleware((m) => {
m.use(RateLimit.perMinute(60))
})
.withExceptions((e) => {
e.render(PaymentError, (err) =>
Response.json({ code: err.code }, { status: 402 }),
)
})
.create()+server.ts at the project root wires the result to Vike:
import type { Server } from 'vike/types'
import app from './bootstrap/app.js'
export default { fetch: app.fetch } satisfies Serverimport 'reflect-metadata' belongs at the very top of bootstrap/app.ts — it must run before any decorator-using class is loaded.
Server adapter
No server: option is needed — Rudder auto-resolves @rudderjs/server-hono (the default HTTP adapter) and constructs it with your config/server.ts settings. Pass an explicit adapter only when you need to:
import { hono } from '@rudderjs/server-hono'
export default Application.configure({
server: hono(config.server), // explicit — same as the auto-resolved default
config,
providers,
})Use the explicit form when swapping in a different adapter, or when bundling the app to a single file — auto-resolution is a runtime lookup that bundlers can't statically trace, so a bundled build must import the adapter itself.
AppBuilder API
Application.configure(options) returns an AppBuilder. Chain these methods, then call .create().
| Method | Signature | Description |
|---|---|---|
withRouting |
(options: { web?, api?, commands?, channels? }) => AppBuilder |
Registers lazy route loader functions (channels loads broadcast channel routes). Each loader is a dynamic import returning a side-effect module. |
withMiddleware |
(fn: (m: MiddlewareConfigurator) => void) => AppBuilder |
Registers global middleware. See Middleware for the configurator API. |
withExceptions |
(fn: (e: ExceptionConfigurator) => void) => AppBuilder |
Registers custom error renderers, ignored types, and the report destination. See Error Handling. |
create |
() => Rudder |
Finalises configuration and returns the application instance. Provider boot (phase 1) is kicked off eagerly but not awaited; the HTTP handler (phase 2) is built lazily on the first request. |
Rudder instance API
create() returns a Rudder instance — your application handle.
| Method | Signature | Description |
|---|---|---|
handleRequest |
(req: Request, env?, ctx?) => Promise<Response> |
Awaits provider boot (started at construction) and builds the HTTP handler on the first call, then handles the incoming HTTP request. |
boot |
() => Promise<void> |
Boots all service providers without starting an HTTP server. Used by the Rudder CLI and background workers. |
fetch |
(req: Request, env?, ctx?) => Promise<Response> |
WinterCG-compatible alias for handleRequest. Works with Vike, Cloudflare Workers, and any platform that consumes a fetch handler. |
app() and resolve()
After bootstrap, two global helpers are available anywhere in the codebase:
import { app, resolve } from '@rudderjs/core'
const application = app() // Application singleton
const userService = resolve<UserService>('userService') // shorthand for app().make()Both throw if the application has not been created yet.
Re-exports from @rudderjs/core
Common framework primitives are re-exported from @rudderjs/core so most apps need only the one import:
| Re-export | Source |
|---|---|
rudder, Rudder, Command, parseSignature |
@rudderjs/console |
Container, container, Injectable, Inject |
core DI |
Listener, EventDispatcher, dispatch, dispatcher, EventFake |
core Events |
FormRequest, ValidationError, validate, z |
core Validation |
Env, env, Collection, resolveOptionalPeer, dump, dd, sleep, tap |
@rudderjs/support |
config (typed; overrides the untyped config from @rudderjs/support) |
core Config |
AppRequest, AppResponse, RouteHandler, MiddlewareHandler |
@rudderjs/contracts |
HttpException, abort, abort_if, abort_unless, report, setExceptionReporter |
core Exceptions |
Notes
Application.configure().create()returns a singleton in production. Inlocal/developmentit recreates on each call to support hot reload.Rudder.boot()runsregister()thenboot()on every provider in declaration order. Provider order matters — for example,DatabaseServiceProvidermust come before any provider that queries models.Rudder.handleRequest()callsboot()automatically on the first HTTP request. Subsequent calls skip the boot phase.- Route loaders passed to
withRouting()are dynamic imports returning side-effect modules — they register routes by callingRoute.get/post/...and don't need to export anything. Application.resetForTesting()is available for test teardown.