Skip to content

Configuration — InertiaConfig

createInertia(config) accepts an InertiaConfig object. All fields except template are optional.

ts
import { createInertia } from "deno-inertia"
import type { InertiaConfig } from "deno-inertia"

const inertia = createInertia({ ...config })

Full reference

ts
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.

ts
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) — serializes PageData into <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.

ts
// Static value
version: "1.0.0"

// Computed dynamically (e.g. last commit hash)
version: () => Deno.env.get("APP_VERSION") ?? null

If null, the check is disabled.


shared

Props merged into every Inertia response (HTML and JSON). Typically: auth.user, csrf_token, locale.

ts
// 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.

ts
always: async (request) => ({
  flash: await readFlash(request),
  auth:  { user: await getUser(request) },
})

Priorityalways 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:

ts
const inertia = createInertia({
  version: "1.0.0",
  entry: "src/main.ts",   // Vue
  // entry: "src/main.tsx", react: true,  // React
  template: (page, assets) => `...`,
})
  • Dev (PROD_MODE unset or "0") — equivalent to vite: { entry, url: VITE_URL } where VITE_URL defaults to "http://localhost:5173"
  • Prod (PROD_MODE=1) — reads ${distDir}/.vite/manifest.json synchronously at startup; equivalent to prod: { manifest, entry }
FieldDescriptionDefault
entryVite entry point (e.g. "src/main.ts")
distDirBuild output directory"dist"
reactInject React Refresh preamblefalse

vite and prod take precedence — entry is ignored if either is set.


vite — development mode

ts
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)
}
ts
// 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-react throws "can't detect preamble. Something is wrong." because the HTML is served by Deno instead of Vite.


prod — production mode

ts
interface ViteProdConfig {
  manifest: ViteManifest  // result of readViteManifest()
  entry:    string        // e.g. "src/main.ts" (no leading slash)
  base?:    string        // asset URL prefix, default: "/assets/"
}
ts
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.

ts
clearFlash: true

encryptHistory

Encrypts browser history state (Inertia v2). Propagated to the encryptHistory field of PageData.

ts
encryptHistory: true

Requires @inertiajs/vue3@^2 or @inertiajs/react@^2.


Full example

ts
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)

ts
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>`,
})