Application · In depth

defineApp / Application

Define pages, socket routes and application services together. Nothing listens until run(); one owner starts and stops the shared HTTP/WebSocket listener.

Explain it like I’m five

The simple mental model

One front door serves pages and ongoing socket conversations. The application prepares its staff before opening that door, then closes the door and sends the staff home in order.

When it fits

When should I use it?

Use it as the entry point for a multi-page site, a realtime UI, a routed socket backend, or their combination. Lower-level server classes remain available for custom ownership.

A practical API pattern

Follow the example

This pattern explains the named API. Application classes, credentials, and assets may need to be supplied; use a complete recipe for a runnable starting point.

Read this article as Markdown

JavaScript
import { defineApp } from 'redweb';
import { HomePage, DashboardPage } from './pages';
import { MatchRoute, ChatRoute } from './sockets';
import { GameSimulation } from './simulation';

const app = defineApp({
  pages: [HomePage, DashboardPage],
  sockets: [MatchRoute, ChatRoute],
  services: [GameSimulation],
  port: 8181,
});

await app.run();
  1. 1

    Declare pages with decorators and socket routes with message-type handlers, then register their classes in one definition.

  2. 2

    Acquire app-wide resources in service onInit(app, signal), not constructors. onInit can register Express endpoints through app.app before listening.

  3. 3

    Await run to know startup succeeded; no separately stored HTTP server or second socket startup call is necessary. CommonJS entry points use an async function or handle the returned promise; top-level await requires a suitable ESM configuration.

  4. 4

    For tests, use an ephemeral port, disable process signal ownership and await shutdown in cleanup. The generated applications ship real HTTP/socket and process tests.

Configuration

Choices you can make

  • pages: decorated page classes (default [])
  • sockets: SocketRoute classes (default [])
  • services: application-wide classes with onInit(app, signal) and onShutdown() (default [])
  • port: number (default 8181); use 0 for an ephemeral test port
  • bind: string (default 0.0.0.0)
  • httpServices: existing Express service descriptors; route-specific SocketService classes remain on socket routes
  • startupTimeoutMs / shutdownTimeoutMs: total lifecycle budgets (default 5000 each)
  • signals: install owned process signal handling when run begins (default true); embedded applications/tests can set false
  • Existing live-page/HTTP options, including templateRoot, authentication, origins, server (Express app), development and ssl
  • Static export remains exportStatic(); defineApp does not accept a static export flag
Surface area

Methods and members

defineApp(options) / new Application(options)

Create a deferred definition. Registration arrays are copied; imports and definitions open no port or process handlers.

run(): Promise<Application>

Initialize services in order and bind one HTTP/WS listener. Repeated calls share startup while running. A stopped application cannot restart.

shutdown(): Promise<void>

Cancel pending startup and perform bounded, idempotent cleanup. Close HTTP/socket resources before releasing application services in reverse order. Preserve cleanup errors.

options

Copied definition, available for defining independent test applications with port: 0 and signals: false. Captured objects and supplied Express apps are not deep-cloned.

app / server / http / sockets / services

Runtime Express application, native listener, HTTP adapter, optional WebSocket server and service instances. HTTP members are null before startup; await run before use.

revoke(principal): Promise<number>

Revoke matching live-page sessions; zero before live pages have been initialized.

inspect(): DevelopmentSnapshot | null

Return opt-in live-page inspection metadata, or null when unavailable/disabled.