Inertia SSR (JS)

Server-side rendering settings for Inertia.js responses (Node SSR server).

InertiaConfig(ssr=True) enables a separate Node SSR server for initial HTML responses. Litestar sends the full Inertia page object to that server, then injects the rendered head tags and body markup back into the HTML response.

This SSR path is distinct from framework proxy mode:

  • Inertia SSR: InertiaConfig(ssr=True)

  • Meta-framework proxy mode: ViteConfig(mode="framework") or alias mode="ssr"

The SSR server is a Node /render endpoint. Litestar posts the page object to InertiaSSRConfig.url and uses the returned head and body fields when building the initial HTML response. This request is required when SSR is enabled; failures to contact the configured endpoint are errors, not a silent fallback to client-side rendering.

Typical file layout:

  • Browser entry: resources/main.tsx or resources/main.ts

  • Node SSR entry: resources/ssr.tsx or resources/ssr.ts

Process management

InertiaSSRConfig.command can start the Node /render server during Litestar lifespan:

from litestar_vite import InertiaConfig, InertiaSSRConfig

InertiaConfig(
    ssr=InertiaSSRConfig(
        command=["npm", "run", "start:ssr"],
        auto_start=True,
        health_check=True,
    )
)

When command is set and auto_start is true, litestar-vite starts the process on application startup and stops it on shutdown. Set auto_start=False when another process manager owns the SSR server. With health_check=True, startup polls the configured SSR URL up to health_check_timeout seconds and logs a warning if the endpoint does not become reachable.

Plugin boundary

Generated Litestar scaffolds do not install @inertiajs/vite by default. The default frontend bridge remains litestar-vite-plugin because it owns Litestar-specific behavior:

  • writing and reading the .litestar.json bridge contract;

  • dev/prod asset resolution and proxy integration;

  • route and schema type generation;

  • CSRF helper wiring for generated Inertia entries;

  • the resolvePageComponent() wrapper used by the templates.

The upstream @inertiajs/vite plugin may be useful if an application wants to experiment with its page shorthand or Laravel-centered SSR automation, but it must not replace the litestar-vite-plugin bridge/proxy/typegen responsibilities. If both plugins are combined, keep litestar-vite-plugin as the bridge owner and treat @inertiajs/vite as application owned integration code.

When you use the default script-element bootstrap transport:

  • Inertia v3 clients use the script-element bootstrap by default, so no extra client defaults block is required.

  • Inertia v2 clients must keep defaults.future.useScriptElementForInitialPage in the browser entry so hydration reads the initial page payload correctly instead of expecting the default data-page attribute.

  • Inertia v2 SSR entries should mirror the same option because Inertia applies the same defaults during server rendering.

  • Set use_script_element=False if you need to keep the legacy data-page attribute bootstrap.

Note

This guidance is intentionally version-scoped. Inertia v2 still uses the future namespace for script-element bootstrap, while Inertia v3 removes that extra client configuration.

Selector behavior follows SPAConfig.app_selector. If you render into #root instead of #app, keep the browser template, SSR output, and app selector aligned so Litestar can replace the correct wrapper element during the initial SSR response.

class litestar_vite.config.InertiaSSRConfig[source]

Bases: object

Server-side rendering settings for Inertia.js.

Inertia SSR runs a separate Node server that renders the initial HTML for an Inertia page object. Litestar sends the page payload to the SSR server (by default at http://127.0.0.1:13714/render) and injects the returned head tags and body markup into the HTML response.

When command is set, the plugin spawns the Node /render server in the server lifespan (mirroring Vite process management) and tears it down on shutdown. This makes SSR examples self-contained — no second terminal needed.

Notes

  • This is not Litestar-Vite’s framework proxy mode (mode="framework"; aliases: mode="ssr" / mode="ssg").

  • When enabled, failures to contact the SSR server are treated as errors (no silent fallback).

target_selector: str = '#app'

CSS selector for the element whose outer HTML is replaced by the SSR-rendered body.

Used by _render_template (template mode) to locate the mount point in the rendered Jinja HTML. Defaults to #app to match Inertia’s convention.

For mode="hybrid", SPAConfig.app_selector is the source of truth and this field is ignored — SPA config already governs the SPA shell selector.

command: list[str] | None = None

Command to start the Node /render server, e.g. ["npm", "run", "start:ssr"].

When set, the plugin spawns the command as a subprocess in the server lifespan and stops it on shutdown. Set to None to disable auto-start (run the SSR server manually in a separate terminal).

cwd: Path | None = None

Working directory for the SSR command. Defaults to ViteConfig.root_dir when None.

auto_start: bool = True

When True and command is set, the plugin starts the Node SSR process in lifespan.

Set to False to keep the command around for documentation but skip auto-start (useful when running under an external process manager).

health_check: bool = False

When True, poll the SSR url until it responds before completing app startup.

Default is False so the SSR process starts in the background and Litestar can serve requests immediately. Set to True if you want startup to block until /render is ready (catches misconfigured commands early at the cost of slower boot).

health_check_timeout: float = 10.0

Seconds to wait for the SSR endpoint to become reachable during startup.

Only consulted when health_check is True. On timeout the plugin logs a warning and continues — startup is not aborted.

__init__(enabled: bool = True, url: str = 'http://127.0.0.1:13714/render', timeout: float = 2.0, target_selector: str = '#app', command: list[str] | None = None, cwd: TypeAliasForwardRef('pathlib.Path') | None = None, auto_start: bool = True, health_check: bool = False, health_check_timeout: float = 10.0) None