Skip to main content

Class: ReactRoute

Defined in: ReactRoute.tsx:53

Base class for HTTP routes that serve React pages from the app/ directory.

Convention-based page routing:

  • app/layout.tsx — global HTML wrapper (loaded once, required)
  • app/_404.tsx — 404 error page (optional)
  • app/_500.tsx — 500 error page (optional)
  • app/pets.tsx — serves GET /pets
  • app/pets/index.tsx — also serves GET /pets (index convention)
  • app/_styles/ — CSS assets (imported by layout or page components)

Each page file exports:

  • default — React component (required)
  • fetchProps — async function (req) → props object (optional)

Subclass to inject DI services into fetchProps:

@Route("/*")
export class AppRouter extends ReactRoute {
@Inject(PetService) private pets: PetService;
protected async fetchProps(req) { return { pets: await this.pets.findAll() }; }
}

Constructors

Constructor

new ReactRoute(): ReactRoute

Returns

ReactRoute

Properties

appDir

protected readonly appDir: string = "apps/app"

Defined in: ReactRoute.tsx:58

Filesystem path to the app directory, relative to cwd. Default is apps/app.


cacheClient?

protected optional cacheClient?: Redis

Defined in: ReactRoute.tsx:55


cacheTTL

protected readonly cacheTTL: number = 60

Defined in: ReactRoute.tsx:61

Cache TTL in seconds. Caching is only active in production (NODE_ENV=production).


hydrate

protected readonly hydrate: boolean = false

Defined in: ReactRoute.tsx:64

Opt-in client-side hydration. When true, wraps the page in a hydration root and injects the client bundle.


hydratePropsId

protected readonly hydratePropsId: string = "react-props"

Defined in: ReactRoute.tsx:77

DOM element id for the serialized props <script> tag.


hydrateRootId

protected readonly hydrateRootId: string = "react-root"

Defined in: ReactRoute.tsx:74

DOM element id for the React hydration root.


logger

protected logger: any

Defined in: ReactRoute.tsx:94


maxDevReloadConnections

protected readonly maxDevReloadConnections: number = 100

Defined in: ReactRoute.tsx:80

Hard cap on concurrent dev-reload SSE connections per route instance.


userFields

protected readonly userFields: string[] | null = null

Defined in: ReactRoute.tsx:71

Allow-list of req.user field names exposed as props.user. Default null means no user object is exposed to pages or the hydration payload — only the scalar userUid is passed. Opt in per-subclass, e.g. protected readonly userFields = ["uid", "email"];.

Methods

canonicalizeQuery()

protected canonicalizeQuery(query): Record<string, string | string[]>

Defined in: ReactRoute.tsx:184

Produces a stable, key-order-independent representation of req.query for cache-key hashing. Sorting only the top-level keys (not array element order) avoids new collisions between semantically different multi-value query strings while eliminating key-order nondeterminism.

Parameters

query

Record<string, string | string[]> | undefined

Returns

Record<string, string | string[]>


escapeForInlineScript()

protected escapeForInlineScript(json): string

Defined in: ReactRoute.tsx:503

Escapes a JSON string for safe embedding inside an inline <script> element. Replacing every < (not just the literal substring "</script>") blocks the full HTML end-tag-open grammar (</script followed by whitespace, /, or >), which a substring match on "</script>" alone does not. JSON.stringify never emits a bare < outside of string content, so this is safe and JSON.parse treats < identically to <, so it round-trips losslessly.

Parameters

json

string

Returns

string


fetchProps()

protected fetchProps(_req): Promise<any>

Defined in: ReactRoute.tsx:418

Returns additional props merged into the page component props. Override in subclasses to provide DI-injected server-side data. Page-file fetchProps runs first; this override runs after and takes precedence.

Parameters

_req

HttpRequest

Returns

Promise<any>


get()

get(req, res): Promise<string | HttpResponse | undefined>

Defined in: ReactRoute.tsx:267

Parameters

req

HttpRequest

res

HttpResponse

Returns

Promise<string | HttpResponse | undefined>


hashRequest()

protected hashRequest(req): string

Defined in: ReactRoute.tsx:196

Computes a stable per-request cache key (MD5 of path + params + query + user identity).

Parameters

req

HttpRequest

Returns

string


init()

protected init(): Promise<void>

Defined in: ReactRoute.tsx:119

Returns

Promise<void>


isDevMode()

protected isDevMode(): boolean

Defined in: ReactRoute.tsx:218

Whether dev-only behaviors (live-reload SSE endpoint, reload script injection, manifest file-watching) are enabled. Explicit allow-list rather than !== "production" so an unset or misconfigured NODE_ENV in a real deployment fails closed (dev features OFF) instead of failing open. Override in a subclass to opt a non-standard environment name into dev mode.

Returns

boolean


pickUserFields()

protected pickUserFields(user): Record<string, any> | undefined

Defined in: ReactRoute.tsx:404

Picks the userFields allow-list out of user. Returns undefined (meaning: don't expose a user prop at all) when there's no user or no allow-list configured.

Parameters

user

any

Returns

Record<string, any> | undefined


resolveAppFile()

protected resolveAppFile(appDir, segment): string | null

Defined in: ReactRoute.tsx:228

Resolve a file in the app directory by trying multiple extensions in order. Tries .tsx → /index.tsx → .jsx → /index.jsx → .js → /index.js. In dev mode tsx handles .tsx directly; in production tsc outputs .js.

Parameters

appDir

string

segment

string

Returns

string | null