Configuration — InertiaConfig
createInertia(config) accepts an InertiaConfig object. All fields except template are optional.
import { createInertia } from "deno-inertia"
import type { InertiaConfig } from "deno-inertia"
const inertia = createInertia({ ...config })Full reference
interface InertiaConfig {
// ---- Required ----
template: (page: PageData, assets: string) => string
// ---- Versioning ----
version?: string | (() => string | null)
// ---- Shared props ----
shared?: PropsResolver
always?: PropsResolver
// ---- Vite assets — auto mode (shorthand) ----
entry?: string // auto dev/prod via PROD_MODE env var
distDir?: string // build output dir, default: "dist"
react?: boolean // inject React Refresh preamble (React only)
// ---- Vite assets — explicit mode ----
vite?: ViteDevConfig // dev mode (mutually exclusive with prod)
prod?: ViteProdConfig // production mode (mutually exclusive with vite)
// ---- Behavior ----
clearFlash?: boolean
encryptHistory?: boolean
}template (required)
Function that receives page data (PageData) and asset tags (string) and returns the full HTML page.
template: (page, assets) => `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My App</title>
${assets}
</head>
<body>
${pageToDiv(page)}
</body>
</html>`,assets—<script>/<link>tags generated by Vite (dev or prod)pageToDiv(page)— serializesPageDatainto<div id="app" data-page="…">
version
Triggers a hard reload (409) if the client version differs from the server. Useful to force asset reloading after a deployment.
// Static value
version: "1.0.0"
// Computed dynamically (e.g. last commit hash)
version: () => Deno.env.get("APP_VERSION") ?? nullIf null, the check is disabled.
shared
Props merged into every Inertia response (HTML and JSON). Typically: auth.user, csrf_token, locale.
// Static object
shared: { appName: "My App" }
// Synchronous or asynchronous function
shared: async (request) => {
const user = await getSessionUser(request)
return { auth: { user } }
}In a partial reload, shared can be filtered if the key is not in X-Inertia-Partial-Data. For props always included, use always.
always
Props always included, even during a partial reload. Ideal for: flash, auth.user, csrf_token.
always: async (request) => ({
flash: await readFlash(request),
auth: { user: await getUser(request) },
})Priority — always overwrites shared if the same keys are present.
entry — auto mode (recommended)
The entry shorthand eliminates all Vite boilerplate. It reads PROD_MODE from the environment and automatically picks dev or prod mode:
const inertia = createInertia({
version: "1.0.0",
entry: "src/main.ts", // Vue
// entry: "src/main.tsx", react: true, // React
template: (page, assets) => `...`,
})- Dev (
PROD_MODEunset or"0") — equivalent tovite: { entry, url: VITE_URL }whereVITE_URLdefaults to"http://localhost:5173" - Prod (
PROD_MODE=1) — reads${distDir}/.vite/manifest.jsonsynchronously at startup; equivalent toprod: { manifest, entry }
| Field | Description | Default |
|---|---|---|
entry | Vite entry point (e.g. "src/main.ts") | — |
distDir | Build output directory | "dist" |
react | Inject React Refresh preamble | false |
viteandprodtake precedence —entryis ignored if either is set.
vite — development mode
interface ViteDevConfig {
url?: string // Vite server URL, default: "http://localhost:5173"
entry: string // e.g. "/src/main.ts" or "/src/main.tsx"
react?: boolean // inject @react-refresh preamble (React only)
}// Vue
vite: { url: "http://localhost:5173", entry: "/src/main.ts" }
// React — react: true injects the HMR preamble required by @vitejs/plugin-react
vite: { url: "http://localhost:5173", entry: "/src/main.tsx", react: true }Important — Without
react: true,@vitejs/plugin-reactthrows"can't detect preamble. Something is wrong."because the HTML is served by Deno instead of Vite.
prod — production mode
interface ViteProdConfig {
manifest: ViteManifest // result of readViteManifest()
entry: string // e.g. "src/main.ts" (no leading slash)
base?: string // asset URL prefix, default: "/assets/"
}const manifest = await readViteManifest("dist/.vite/manifest.json")
prod: { manifest, entry: "src/main.ts" }clearFlash
If true, automatically clears the __flash cookie in everyrender() response (HTML and JSON). Avoids calling clearFlashCookie() manually.
clearFlash: trueencryptHistory
Encrypts browser history state (Inertia v2). Propagated to the encryptHistory field of PageData.
encryptHistory: trueRequires @inertiajs/vue3@^2 or @inertiajs/react@^2.
Full example
Auto mode (recommended)
import { createInertia, pageToDiv, readFlash } from "deno-inertia"
const inertia = createInertia({
version: Deno.env.get("APP_VERSION") ?? "dev",
entry: "src/main.ts", // auto dev/prod via PROD_MODE
shared: async (req) => ({
locale: req.headers.get("Accept-Language")?.slice(0, 2) ?? "en",
}),
always: async (req) => ({
auth: { user: await getSessionUser(req) },
flash: await readFlash(req),
}),
clearFlash: true,
encryptHistory: false,
template: (page, assets) => `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My App</title>
${assets}
</head>
<body>${pageToDiv(page)}</body>
</html>`,
})Explicit mode (full control)
import { createInertia, readViteManifest, pageToDiv, readFlash } from "deno-inertia"
const IS_PROD = Deno.env.get("PROD_MODE") === "1"
const manifest = IS_PROD ? await readViteManifest("dist/.vite/manifest.json") : null
const inertia = createInertia({
version: Deno.env.get("APP_VERSION") ?? "dev",
...(IS_PROD && manifest
? { prod: { manifest, entry: "src/main.ts" } }
: { vite: { entry: "/src/main.ts" } }),
clearFlash: true,
template: (page, assets) => `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My App</title>
${assets}
</head>
<body>${pageToDiv(page)}</body>
</html>`,
})