@lastshotlabs/slingshot-ssr
npm install @lastshotlabs/slingshot-ssr
Functions
Section titled “Functions”buildAfterFn
Section titled “buildAfterFn”Build the after() scheduler for a single request.
Returns a function that, when called from within a load function, enqueues
a callback in the current request’s after-queue. Pass the returned function
as shell._after so that buildLoadContext() in the renderer can expose
it as ctx.after().
On edge runtimes, returns a no-op function with a console warning.
function buildAfterFn(): (callback: () => void | Promise<void>) => voidSource: packages/slingshot-ssr/src/after/index.ts
buildPageChain
Section titled “buildPageChain”Build a synthetic route chain for a manifest-backed page declaration.
function buildPageChain(declaration: ResolvedPageDeclaration, params: Record<string, string>, url: URL, query: Record<string, string>,): SsrRouteChainSource: packages/slingshot-ssr/src/pageResolver.ts
buildPageRouteTable
Section titled “buildPageRouteTable”Compile manifest page declarations into a route table.
The returned table is sorted by specificity so static routes win over dynamic ones, mirroring the file-system SSR resolver.
function buildPageRouteTable(pages: Readonly<Record<string, PageDeclaration>>, entityConfigs: ReadonlyMap<string, ResolvedEntityConfig>,): readonly ResolvedPageDeclaration[]Source: packages/slingshot-ssr/src/pageResolver.ts
clearRouteModuleCache
Section titled “clearRouteModuleCache”Clear the route-module import cache. Intended for tests and dev-mode watchers that need to pick up a freshly-edited route file.
function clearRouteModuleCache(): voidSource: packages/slingshot-ssr/src/routeExecution.ts
createCircuitBreaker
Section titled “createCircuitBreaker”Create a circuit breaker wrapping an external dependency.
function createCircuitBreaker(options: Partial<CircuitBreakerOptions> = {}): CircuitBreakerSource: packages/slingshot-ssr/src/circuitBreaker.ts
createFileBasedRouteSource
Section titled “createFileBasedRouteSource”Build the default file-based route source.
This is what createSsrPackage uses when no explicit routeSource is
configured. Existing apps that pass serverRoutesDir to createSsrPackage
get this source behind the scenes — no migration needed.
function createFileBasedRouteSource(config: FileBasedRouteSourceConfig): SsrRouteSourceSource: packages/slingshot-ssr/src/routeSource/fileBased.ts
createSsrPackage
Section titled “createSsrPackage”Create the Slingshot SSR package.
Registers SSR middleware, server action routes, metadata routes, and
optional entity-driven page support when config.pages is supplied.
The package itself owns no entities — page routes are driven imperatively
from setupMiddleware/setupRoutes/setupPost lifecycle hooks, so the
definePackage input has empty entities: [].
function createSsrPackage(rawConfig: SsrPluginConfig): SlingshotPackageDefinitionSource: packages/slingshot-ssr/src/plugin.ts
DEFAULT_MAX_ROUTE_PARAM_BYTES
Section titled “DEFAULT_MAX_ROUTE_PARAM_BYTES”Default maximum byte length of a single decoded route param.
Per spec — pluggable through SsrPluginConfig.maxRouteParamBytes. Requests
whose decoded params exceed this cap are rejected with HTTP 414.
Source: packages/slingshot-ssr/src/resolver.ts
DRAFT_MODE_COOKIE
Section titled “DRAFT_MODE_COOKIE”The name of the HTTP cookie used to signal draft mode.
The cookie is HttpOnly, Secure, SameSite=Lax, Path=/. Its presence (with any non-empty value) indicates draft mode is active for the request.
Source: packages/slingshot-ssr/src/draft/index.ts
draftMode
Section titled “draftMode”Access draft mode state for the current request.
Returns an object with:
isEnabled— whether the request carries the draft mode cookieenable()— sets the draft cookie on the response (HttpOnly, Secure, SameSite=Lax, Path=/)disable()— clears the draft cookie by expiring it in the past
Must be called from within a withDraftContext() wrapper. Calling outside
of a draft context (e.g. from a non-SSR route) throws a descriptive error.
In edge runtimes where AsyncLocalStorage is unavailable, draftMode()
returns a permanent no-op (isEnabled: false) instead of throwing.
function draftMode(): voidSource: packages/slingshot-ssr/src/draft/index.ts
drainAfterCallbacks
Section titled “drainAfterCallbacks”Run all after-callbacks registered for the current request.
Called by the SSR middleware after the response body stream has been flushed. Callbacks are executed in registration order. Errors in individual callbacks are caught and logged — they never propagate to the caller or affect other callbacks in the queue.
Safe to call outside an after context (returns immediately).
async function drainAfterCallbacks(): Promise<void>Source: packages/slingshot-ssr/src/after/index.ts
generatePageStaticParams
Section titled “generatePageStaticParams”Generate static param sets for entity-driven page declarations.
Static list, create-form, and dashboard pages emit a single empty param set when their path contains no dynamic segments. Detail and edit-form pages enumerate entity records and map route param names to record field names.
async function generatePageStaticParams(declaration: ResolvedPageDeclaration, adapters: Readonly<Record<string, PageEntityAdapter>>,): Promise<StaticParamSet[]>Source: packages/slingshot-ssr/src/static-params/pageStaticParams.ts
initRouteTree
Section titled “initRouteTree”Initialise the route tree for a given server routes directory.
Scans the directory and caches the result. Safe to call multiple times — returns the cached result if already initialised.
Called automatically:
- by the SSR plugin’s
setupMiddlewareat request time - by
slingshot-ssg’s renderer beforeresolveRouteChainat build time
Tooling that calls resolveRouteChain directly (e.g. custom build scripts,
dev tooling, tests) must call this first to populate the cache.
function initRouteTree(serverRoutesDir: string): voidSource: packages/slingshot-ssr/src/resolver.ts
invalidateRouteTree
Section titled “invalidateRouteTree”Invalidate the cached route tree for a directory.
Called by the dev-mode file watcher when files are added, changed, or
removed. After invalidation, the next call to initRouteTree will re-scan.
Test code can call this between cases to ensure a fresh resolution.
function invalidateRouteTree(serverRoutesDir: string): voidSource: packages/slingshot-ssr/src/resolver.ts
isDraftRequest
Section titled “isDraftRequest”Returns true when the incoming request carries the draft mode cookie.
Used by the ISR middleware to decide whether to bypass the cache. Does not require a draft context to be active — reads directly from the Hono context.
function isDraftRequest(c: HonoContext): booleanSource: packages/slingshot-ssr/src/draft/index.ts
isForbidden
Section titled “isForbidden”Returns true when the loader result signals forbidden (403). @internal
function isForbidden(result: SsrLoaderReturn): result is SsrForbiddenResultSource: packages/slingshot-ssr/src/types.ts
isLoadResult
Section titled “isLoadResult”Returns true when the loader result is a successful load with a data field.
function isLoadResult(result: SsrLoaderReturn): result is SsrLoadResultSource: packages/slingshot-ssr/src/types.ts
isNotFound
Section titled “isNotFound”Returns true when the loader result signals not-found.
function isNotFound(result: SsrLoaderReturn): result is SsrNotFoundResultSource: packages/slingshot-ssr/src/types.ts
isRedirect
Section titled “isRedirect”Returns true when the loader result is a redirect.
function isRedirect(result: SsrLoaderReturn): result is SsrRedirectResultSource: packages/slingshot-ssr/src/types.ts
isRouteParamTooLargeError
Section titled “isRouteParamTooLargeError”Returns true when err is a RouteParamTooLargeError. Uses a name
check so the guard works across module boundaries / duplicate class loads.
function isRouteParamTooLargeError(err: unknown): err is RouteParamTooLargeErrorSource: packages/slingshot-ssr/src/resolver.ts
isUnauthorized
Section titled “isUnauthorized”Returns true when the loader result signals unauthorized (401). @internal
function isUnauthorized(result: SsrLoaderReturn): result is SsrUnauthorizedResultSource: packages/slingshot-ssr/src/types.ts
prerenderPprShells
Section titled “prerenderPprShells”PPR build-time pre-rendering.
Call this after the Vite build to pre-compute static shells for all PPR routes.
Each route’s element is rendered via extractPprShell() (from snapshot/ssr);
successful shells are stored in cache keyed by route path.
Usage pattern:
import { prerenderPprShells } from '@lastshotlabs/slingshot-ssr/ppr'import { createPprCache, extractPprShell } from '@lastshotlabs/snapshot/ssr'
const pprCache = createPprCache()
await prerenderPprShells([{ path: '/dashboard', element: <DashboardPage loaderData={...} /> },{ path: '/home', element: <HomePage loaderData={...} /> },],pprCache,// Pass extractPprShell from snapshot/ssr — avoids circular depextractPprShell,)Why pass extractPprShell as a parameter?
slingshot-ssr must not import from @lastshotlabs/snapshot to avoid a
circular package dependency. The consumer app imports both packages and passes
extractPprShell as a callback — structural typing ensures compatibility.
async function prerenderPprShells(routes: readonly PprRouteDescriptor[], cache: PprCacheShape, extractShell: (element: ReactElement) => Promise<PprShellShape>,): Promise<void>Source: packages/slingshot-ssr/src/ppr/index.ts
registerMetadataRoutes
Section titled “registerMetadataRoutes”Register metadata file routes on a Hono application.
Checks for convention files in the server/ directory (the parent of
serverRoutesDir) and registers GET handlers for each that exists:
server/sitemap.ts→GET /sitemap.xmlserver/robots.ts→GET /robots.txtserver/manifest.ts→GET /manifest.webmanifestandGET /manifest.json
Handlers dynamically import the convention file and call its default export. Each handler must be registered before SSR middleware so it takes priority.
Routes are only registered when the corresponding file exists — if the file does not exist, the route is not registered and the request falls through to SSR or the SPA.
function registerMetadataRoutes(app: unknown, serverRoutesDir: string): voidSource: packages/slingshot-ssr/src/metadata/index.ts
registerMetadataRoutesFromDir
Section titled “registerMetadataRoutesFromDir”Register metadata file routes on a Hono application, scanning a directory
directly for the convention files (sitemap.ts, robots.ts, manifest.ts).
Unlike registerMetadataRoutes, which derives the scan directory from
a server/routes path, this takes the metadata directory itself — the
right entry point when route discovery doesn’t use the file-based layout
(e.g. a TanStack routeSource) but metadata files still live in server/.
Registered routes are logged at info level for boot-time visibility; when no convention file exists, nothing is registered and requests fall through to SSR or the SPA.
function registerMetadataRoutesFromDir(app: unknown, metadataDir: string): voidSource: packages/slingshot-ssr/src/metadata/index.ts
resolveGlobalMiddlewarePath
Section titled “resolveGlobalMiddlewarePath”Resolve the global server middleware file path for a given routes directory.
Looks for middleware.ts adjacent to serverRoutesDir (i.e. in the parent
server/ directory). This is the same check performed inside resolveRouteChain,
but exposed separately so the middleware handler can run global middleware even
when no page route matched — enabling redirects, rewrites, and auth guards for
unmatched URLs without requiring a file-based page.
function resolveGlobalMiddlewarePath(serverRoutesDir: string): string | nullSource: packages/slingshot-ssr/src/resolver.ts
resolvePageDeclaration
Section titled “resolvePageDeclaration”Resolve a pathname against a compiled page route table.
function resolvePageDeclaration(pathname: string, routeTable: readonly ResolvedPageDeclaration[],): voidSource: packages/slingshot-ssr/src/pageResolver.ts
resolvePageLoader
Section titled “resolvePageLoader”Resolve and execute the generated loader for a page declaration.
async function resolvePageLoader(declaration: ResolvedPageDeclaration, params: Readonly<Record<string, string>>, query: Readonly<Record<string, string>>, adapters: Readonly<Record<string, PageEntityAdapter>>, entityConfigs: ReadonlyMap<string, ResolvedEntityConfig>, navigation?: NavigationConfig,): Promise<PageLoaderResult>Source: packages/slingshot-ssr/src/pageLoaders.ts
resolveRouteChain
Section titled “resolveRouteChain”Resolve a URL pathname to a full route chain including all ancestor layout.ts
files, parallel @slot directories, interception routes, and middleware.
Returns null if no matching page route is found.
Layout detection (Phase 25): Walks up from the matched file’s directory toward
serverRoutesDir, checking for layout.ts or layout/index.ts at each level.
Layouts are collected in root-first order.
Parallel routes (Phase 26): Scans the leaf directory for @-prefixed
subdirectories and attempts to resolve the pathname within each slot’s tree.
Intercepting routes (Phase 27): When fromPath is provided, checks for
(.), (..), and (...) interception directories relative to fromPath’s
level and tries to match pathname within them before the direct match.
Middleware (Phase 29): Checks for middleware.ts adjacent to serverRoutesDir
(i.e., server/middleware.ts when serverRoutesDir is server/routes).
function resolveRouteChain(pathname: string, serverRoutesDir: string, fromPath?: string, options: ResolveRouteOptions = {},): SsrRouteChain | nullSource: packages/slingshot-ssr/src/resolver.ts
Execute fn with retry on failure.
Implements exponential backoff with full jitter between retries. The initial call counts as attempt 1; subsequent retries use the formula:
delay = random(0, baseDelayMs * 2^(attempt-1))async function retry<T>(fn: () => Promise<T>, options: Partial<RetryOptions> = {},): Promise<T>Source: packages/slingshot-ssr/src/retry.ts
validatePageAdapters
Section titled “validatePageAdapters”P-SSR-3: Validate at plugin setup time that every entity referenced by a page declaration has a registered adapter. Without this, missing adapters surface only when the page is requested, returning a 500. Catching at setup fails the plugin init with a descriptive message that includes the offending page route.
function validatePageAdapters(pages: Readonly<Record<string, PageDeclaration>>, adapters: Readonly<Record<string, PageEntityAdapter | undefined>>,): voidSource: packages/slingshot-ssr/src/pageLoaders.ts
withAfterContext
Section titled “withAfterContext”Wrap a request handler with a fresh per-request after-callback queue.
All after() calls within fn (including those inside nested load functions)
are captured in the same queue and drained when drainAfterCallbacks() is
called after the response stream flushes.
On edge runtimes where ALS is unavailable, fn is called directly and
after() callbacks are silently discarded.
function withAfterContext<T>(fn: () => Promise<T>): Promise<T>Source: packages/slingshot-ssr/src/after/index.ts
withDraftContext
Section titled “withDraftContext”Wraps a request handler so that draftMode() is available within it.
Called by the SSR middleware around every render invocation so that load
functions and route handlers can call draftMode() without receiving the
Hono context explicitly.
All code executing within fn() — including transitively called functions
— has access to the draft context via the ambient draftMode() function.
function withDraftContext<T>(c: HonoContext, fn: () => T | Promise<T>): Promise<T>Source: packages/slingshot-ssr/src/draft/index.ts
Constants
Section titled “Constants”IsrInvalidatorsCap
Section titled “IsrInvalidatorsCap”Capability handle for the ISR invalidators (path and tag invalidation).
Cross-package consumers (server actions, route handlers, peer plugins) resolve it
through ctx.capabilities.require(IsrInvalidatorsCap) to invalidate paths and tags
on the active ISR cache adapter.
Source: packages/slingshot-ssr/src/public.ts
Provider-owned package contract for slingshot-ssr.
Source: packages/slingshot-ssr/src/public.ts
Classes
Section titled “Classes”PageNotFoundError
Section titled “PageNotFoundError”Error thrown when a page loader cannot resolve the requested entity record.
Source: packages/slingshot-ssr/src/pageLoaders.ts
RouteParamTooLargeError
Section titled “RouteParamTooLargeError”Thrown by route resolution helpers when a decoded route param exceeds the configured byte cap. The SSR middleware catches this and returns a 414 URI Too Long response without invoking the renderer.
Source: packages/slingshot-ssr/src/resolver.ts
SsrAssetManifestError
Section titled “SsrAssetManifestError”Error thrown when the asset manifest file cannot be read or parsed.
In production mode, createSsrPackage() treats this as a startup error —
the server will not start without a valid manifest. Run bun run build
before starting the server in production.
Source: packages/slingshot-ssr/src/assets.ts
Interfaces
Section titled “Interfaces”CircuitBreaker
Section titled “CircuitBreaker”Circuit breaker contract.
Implementations wrap an external dependency call with failure counting, automatic circuit opening, and recovery probing.
Source: packages/slingshot-ssr/src/circuitBreaker.ts
CircuitBreakerOptions
Section titled “CircuitBreakerOptions”Options for createCircuitBreaker.
Source: packages/slingshot-ssr/src/circuitBreaker.ts
CustomPageDeclaration
Section titled “CustomPageDeclaration”Escape hatch for renderer-specific custom page rendering.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
DefineRouteOptions
Section titled “DefineRouteOptions”Options accepted by defineRoute().
The TData generic threads from load through to Page and meta,
so TypeScript checks prop types automatically without manual annotations.
Source: packages/slingshot-ssr/src/types.ts
DraftModeStatus
Section titled “DraftModeStatus”Read-only snapshot of draft mode status for the current request.
Returned by draftMode() and exposed as ctx.draftMode() in load functions.
Source: packages/slingshot-ssr/src/draft/index.ts
EntityDashboardPageDeclaration
Section titled “EntityDashboardPageDeclaration”Aggregate/stats dashboard page.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
EntityDetailPageDeclaration
Section titled “EntityDetailPageDeclaration”Single-record page resolved by primary key or lookup operation.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
EntityFieldMeta
Section titled “EntityFieldMeta”Entity field metadata passed to renderers.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
EntityFormPageDeclaration
Section titled “EntityFormPageDeclaration”Create or edit form bound to an entity.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
EntityListPageDeclaration
Section titled “EntityListPageDeclaration”Paginated list/table of entity records.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
EntityMeta
Section titled “EntityMeta”Entity metadata passed to renderers alongside loaded page data.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
FileBasedRouteSourceConfig
Section titled “FileBasedRouteSourceConfig”Configuration for createFileBasedRouteSource.
Source: packages/slingshot-ssr/src/routeSource/fileBased.ts
IsrCacheAdapter
Section titled “IsrCacheAdapter”Interface for ISR cache backends.
Implement this interface to provide a custom cache store. Two built-in
adapters are provided: createMemoryIsrCache() (single-instance) and
createRedisIsrCache() (multi-instance/distributed).
All methods are async to allow network-backed implementations (Redis, KV stores).
Source: packages/slingshot-ssr/src/isr/types.ts
IsrCacheEntry
Section titled “IsrCacheEntry”A single cached ISR page entry.
Stores the rendered HTML, response headers, and timing metadata needed to implement stale-while-revalidate logic. Both memory and Redis adapters use this shape — Redis serializes it as JSON.
Source: packages/slingshot-ssr/src/isr/types.ts
IsrConfig
Section titled “IsrConfig”ISR (Incremental Static Regeneration) configuration for createSsrPackage().
When set, any loader returning revalidate: N causes the rendered HTML to be
stored in the configured adapter. Subsequent requests are served from cache
until the entry is stale, at which point it is regenerated in the background
(stale-while-revalidate).
Source: packages/slingshot-ssr/src/isr/types.ts
IsrSink
Section titled “IsrSink”Mutable sink for ISR metadata from the renderer back to the middleware.
The middleware creates a plain object {} satisfying this interface,
attaches it to SsrShell._isr, and reads revalidate/tags/noStore
from it after the renderer returns. The renderer writes to this object after
calling load().
Source: packages/slingshot-ssr/src/types.ts
NavigationBadgeConfig
Section titled “NavigationBadgeConfig”Navigation badge declaration.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
NavigationConfig
Section titled “NavigationConfig”Renderer-agnostic shell/navigation configuration.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
NavigationItem
Section titled “NavigationItem”Single navigation item in the app shell.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
PageChartConfig
Section titled “PageChartConfig”Dashboard chart declaration.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
PageDeclarationBase
Section titled “PageDeclarationBase”Base fields shared by all page declarations.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
PageDetailSection
Section titled “PageDetailSection”Section declaration for detail pages.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
PageFieldOverride
Section titled “PageFieldOverride”Per-field form override.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
PageFilterConfig
Section titled “PageFilterConfig”Filter control declaration for entity-list pages.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
PageLoaderResult
Section titled “PageLoaderResult”Result of executing an entity-driven page loader.
Contains the resolved declaration, loaded data, derived entity metadata, and optional navigation/ISR hints for renderer implementations.
Source: packages/slingshot-ssr/src/types.ts
PagePermissionConfig
Section titled “PagePermissionConfig”Permission requirement declared directly on a page.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
PageRelatedSection
Section titled “PageRelatedSection”Related-entity section on a detail page.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
PageStatConfig
Section titled “PageStatConfig”Dashboard stat-card declaration.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
PageTitleField
Section titled “PageTitleField”Field-reference page title.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
PageTitleTemplate
Section titled “PageTitleTemplate”Template-based page title.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
PprCacheShape
Section titled “PprCacheShape”Structural equivalent of PprCache from @lastshotlabs/snapshot/ssr.
Passed by the consumer app (which imports from both packages) so that
slingshot-ssr never imports from snapshot directly.
Source: packages/slingshot-ssr/src/ppr/index.ts
PprRouteDescriptor
Section titled “PprRouteDescriptor”A PPR-enabled route descriptor passed to prerenderPprShells().
The caller is responsible for constructing the element (the full React
tree for this route, including all providers) before calling the build step.
Source: packages/slingshot-ssr/src/ppr/index.ts
ResolvedPageDeclaration
Section titled “ResolvedPageDeclaration”A page declaration after route-table compilation and entity resolution.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
ResolveRouteChainOptions
Section titled “ResolveRouteChainOptions”Per-call options for SsrRouteSource.resolveChain.
Source: packages/slingshot-ssr/src/routeSource/types.ts
ResolveRouteOptions
Section titled “ResolveRouteOptions”Per-call options for SsrRouteSource.resolve.
Source: packages/slingshot-ssr/src/routeSource/types.ts
RetryOptions
Section titled “RetryOptions”Options for retry.
Source: packages/slingshot-ssr/src/retry.ts
RobotsConfig
Section titled “RobotsConfig”Configuration for robots.txt generation.
Source: packages/slingshot-ssr/src/metadata/index.ts
RouteExecution
Section titled “RouteExecution”Result of executing a file-based route module’s loader and meta.
Source: packages/slingshot-ssr/src/routeExecution.ts
SerializableHandlerRef
Section titled “SerializableHandlerRef”Serializable handler reference used in manifest-backed page declarations.
This mirrors the root manifest handler-ref shape without introducing a runtime
dependency from slingshot-ssr back to the root package.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
SitemapEntry
Section titled “SitemapEntry”A single entry in a sitemap response.
Serialised to a <url> element in the sitemap XML output.
All fields except url are optional and omitted from the XML when undefined.
Source: packages/slingshot-ssr/src/metadata/index.ts
SlingshotSsrRenderer
Section titled “SlingshotSsrRenderer”The renderer contract for slingshot-ssr.
Framework-agnostic. snapshot/ssr provides createReactRenderer() for React apps.
Any object with resolve, render, and renderChain matching these signatures is
valid — TypeScript verifies compatibility structurally at the consumer’s compile time.
Cross-repo coupling: snapshot/ssr does NOT import this type. The consumer app
imports from both packages and TypeScript verifies structural compatibility.
This is intentional — no forced dependency between the two packages.
Source: packages/slingshot-ssr/src/types.ts
SsrCacheControl
Section titled “SsrCacheControl”Cache-control configuration for SSR responses.
Source: packages/slingshot-ssr/src/types.ts
SsrForbiddenResult
Section titled “SsrForbiddenResult”Signal from a server route’s load() that the user lacks permission.
slingshot-ssr responds with 403 Forbidden. Co-locate a forbidden.ts
convention file to render a custom UI instead of a plain-text fallback.
Source: packages/slingshot-ssr/src/types.ts
SsrLoadContext
Section titled “SsrLoadContext”The context object passed to every server route load() and meta() function.
Provides request data and access to the slingshot instance. All data fetching
in load() should go through bsCtx — no HTTP round trips needed since
the loader runs in the same process as the database.
Source: packages/slingshot-ssr/src/types.ts
SsrLoadResult
Section titled “SsrLoadResult”Successful load result from a server route’s load() function.
The generic parameter TData types the data field, connecting loader return
type to component props via defineRoute(). Defaults to Record<string, unknown>
for backwards-compatible untyped usage.
Both data and queryCache must be JSON-serializable — they are embedded
in the HTML as dehydrated state for client hydration.
Source: packages/slingshot-ssr/src/types.ts
SsrMeta
Section titled “SsrMeta”Head/meta tag configuration returned by a server route’s meta() function.
All string values are HTML-escaped before injection into the document.
Source: packages/slingshot-ssr/src/types.ts
SsrNotFoundResult
Section titled “SsrNotFoundResult”Signal from a server route’s load() that the resource was not found.
slingshot-ssr falls through to the SPA, which renders its own 404 page.
The HTTP response will be 200 (the SPA handles the 404 UI).
Source: packages/slingshot-ssr/src/types.ts
SsrPluginConfig
Section titled “SsrPluginConfig”Configuration for createSsrPackage().
Source: packages/slingshot-ssr/src/types.ts
SsrQueryCacheEntry
Section titled “SsrQueryCacheEntry”A TanStack Query cache entry to pre-seed during SSR.
The queryKey array must match exactly the key used by the corresponding
client-side useQuery() hook. On hydration, the client reads this entry
from the dehydrated state and skips the network request.
Source: packages/slingshot-ssr/src/types.ts
SsrRedirectResult
Section titled “SsrRedirectResult”Signal from a server route’s load() that the client should be redirected.
slingshot-ssr responds with the appropriate HTTP redirect status.
Source: packages/slingshot-ssr/src/types.ts
SsrRouteChain
Section titled “SsrRouteChain”A resolved layout chain from root to leaf page.
Used by SlingshotSsrRenderer.renderChain() to render nested layouts. When no
layout.ts files are found, layouts is empty and the middleware calls
renderer.render() instead of renderer.renderChain().
Source: packages/slingshot-ssr/src/types.ts
SsrRouteMatch
Section titled “SsrRouteMatch”A resolved server route — the output of the file-based route resolver.
Passed from the resolver to the renderer’s render() method. Contains
everything the renderer needs to load data and produce HTML.
Source: packages/slingshot-ssr/src/types.ts
SsrRouteSource
Section titled “SsrRouteSource”Pluggable route discovery + resolution.
Implementations must be safe to call concurrently. State changes (init,
invalidate) happen at well-defined moments — boot and dev-mode file-watcher
notifications. Resolution (resolve, resolveChain,
resolveGlobalMiddleware) is called on every SSR request and must be sync
and side-effect-free.
Source: packages/slingshot-ssr/src/routeSource/types.ts
SsrShell
Section titled “SsrShell”The HTML tag strings injected into the document head by slingshot-ssr.
Passed to the renderer’s render() method. The renderer is responsible for
embedding these in the correct positions in the HTML output.
Standard injection order in <head>:
headTags— title, meta, OG tagsassetTags— hashed<link>and<script>from Vite manifest- Renderer-specific dehydrated state scripts
Source: packages/slingshot-ssr/src/types.ts
SsrUnauthorizedResult
Section titled “SsrUnauthorizedResult”Signal from a server route’s load() that the user is not authenticated.
slingshot-ssr responds with 401 Unauthorized. Co-locate an unauthorized.ts
convention file to render a custom UI instead of a plain-text fallback.
Source: packages/slingshot-ssr/src/types.ts
StaticRoute
Section titled “StaticRoute”A single route that exports generateStaticParams, plus the pre-computed
param sets returned by calling it at build time.
routePath uses the file-system-derived URL pattern (e.g. /players/[id]).
paramSets is the array returned by the route’s generateStaticParams export.
Source: packages/slingshot-ssr/src/static-params/index.ts
CircuitResult
Section titled “CircuitResult”Result returned by CircuitBreaker.execute.
Source: packages/slingshot-ssr/src/circuitBreaker.ts
CircuitState
Section titled “CircuitState”Circuit breaker state machine states.
Source: packages/slingshot-ssr/src/circuitBreaker.ts
GenerateStaticParams
Section titled “GenerateStaticParams”Function exported from a route file to enumerate all static paths at build time.
Called during the static-params build phase. Receives an empty SsrLoadContext
(no live request data) — only use it to access database handles via
ctx.bsCtx when running inside the SSG crawler that injects a real context.
Returning an empty array or not exporting this function causes the route to be rendered on-demand (no pre-rendering for that route).
Source: packages/slingshot-ssr/src/types.ts
PageData
Section titled “PageData”Result shape returned by page loaders.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
PageDeclaration
Section titled “PageDeclaration”Discriminated union of all supported manifest page declarations.
Source: packages/slingshot-ssr/src/pageDeclarations.ts
SsgStaticPathsFn
Section titled “SsgStaticPathsFn”Exported from dynamic route files to enumerate all static paths.
Required when load() returns revalidate: false on a dynamic route.
Called during slingshot ssg — inject a DB context via globalThis.__ssgDb
before calling this from the SSG crawler.
Source: packages/slingshot-ssr/src/types.ts
SsrLoaderReturn
Section titled “SsrLoaderReturn”All possible return types from a server route’s load() function.
Source: packages/slingshot-ssr/src/types.ts
SsrMiddlewareResult
Section titled “SsrMiddlewareResult”Result returned from the server/middleware.ts function.
Return one of four shapes:
{ redirect, status? }— redirect the request to a new URL{ rewrite }— internally rewrite the route resolution to a different path{ headers }— add headers to the final rendered response{}— pass through unchanged
Source: packages/slingshot-ssr/src/types.ts
Exports
Section titled “Exports”defineRoute
Section titled “defineRoute”Type-safe route definition helper. Connects the loader’s return type to the
page component’s loaderData prop type, eliminating manual type annotations.
The returned object contains load, Page, and optionally meta and
generateStaticParams. Spread the named exports for the module exports and
use route.Page as the default export.
Rule 9: defineRoute does not redefine types — it constrains the existing
SsrLoadResult<TData> generic at the call site.
Source: packages/slingshot-ssr/src/types.ts
executeRouteModule
Section titled “executeRouteModule”Execute a file-based route module’s load() and (if present) meta(),
returning the loader result, the meta object, and the page component.
This is the canonical helper for SlingshotSsrRenderer implementations.
Without it, every renderer has to hand-roll the dynamic-import + load +
meta dance and risks subtle drift across consumers (request-time renderer,
SSG renderer, test renderers).
The helper does not invoke the page component — it only returns it. The
renderer decides whether to call renderToString (React), renderToReadableStream
(RSC), or any other output strategy.
Loader signals ({ redirect: ... }, { notFound: true }, etc.) are passed
through on loaderResult unchanged. Callers should check via the
isRedirect / isNotFound / etc. helpers before rendering.
Source: packages/slingshot-ssr/src/routeExecution.ts
loadRouteModule
Section titled “loadRouteModule”Dynamically import a file-based route module, with module-level caching.
Test code can clear the cache between cases via clearRouteModuleCache().
Production callers should not need to clear the cache — module identity is
keyed by absolute file path, which is stable for the lifetime of the build.
Source: packages/slingshot-ssr/src/routeExecution.ts