Configuration Reference
Every option accepted by the pracht() Vite plugin and by defineApp(), with its default and a pointer to the guide that explains it.
pracht() — the Vite plugin
import { defineConfig } from "vite";
import { pracht } from "@pracht/vite-plugin";
import { nodeAdapter } from "@pracht/adapter-node";
export default defineConfig({
plugins: [pracht({ adapter: nodeAdapter() })],
});
Everything below is optional. The defaults are the conventions a create-pracht
app already follows, so most apps pass only an adapter.
Project layout
| Option |
Default |
Description |
appFile |
"/src/routes.ts" |
The route manifest. Ignored when pagesDir is set |
routesDir |
"/src/routes" |
Where route modules are discovered |
shellsDir |
"/src/shells" |
Where shell modules are discovered |
middlewareDir |
"/src/middleware" |
Where middleware modules are discovered |
apiDir |
"/src/api" |
Where API routes are auto-discovered |
serverDir |
"/src/server" |
Server-only modules, never bundled for the client |
islandsDir |
"/src/islands" |
Components hydrated on hydration: "islands" routes |
capabilitiesDir |
"/src/capabilities" |
Capability modules registered in the manifest |
additionalExtensions |
[] |
Extra dot-prefixed route/shell extensions to discover, e.g. [".vue"]. Register the transforming plugin separately; pracht only discovers the modules. .tsrx is discovered without configuration |
Routing
| Option |
Default |
Description |
adapter |
Node adapter |
Deployment target. See Adapters |
pagesDir |
(unset) |
Opt into file-system routing, e.g. "/src/pages". Overrides appFile |
pagesDefaultRender |
"ssr" |
Render mode for pages that do not export RENDER_MODE. Pages router only |
Build
| Option |
Default |
Description |
prerenderConcurrency |
10 |
Maximum SSG/ISG pages rendered in parallel by pracht build |
maxBodySize |
1048576 (1 MiB) |
Largest request body the dev SSR middleware accepts |
inlineCss |
false |
Inline the complete matched route/shell production CSS in each HTML document instead of linking it. See Performance |
budgets |
{} |
Per-route gzip client-JS budgets, e.g. { "*": "120kb", "/dashboard": "200kb" }. "*" applies everywhere; explicit paths override it. Exceeding one fails the build unless you pass pracht build --no-budget-fail |
precompileSsrJsx |
false |
Precompile safe Preact JSX DOM subtrees in SSR/SSG server bundles. Client bundles keep the normal transform for hydration |
envSafety |
{} (enabled) |
Fail the build when a production client chunk references a non-public env var. { allow: ["NAME"] } permits specific ones; false disables the check. See Environment Variables |
Client bundle
client switches off router features so they are compiled out of the client
bundle, and switches on the one diagnostic a production build can carry. Turn a
feature off only when the app really does not use it — the router then silently
stops honouring the corresponding route options and <Link> props.
| Option |
Default |
Description |
client.prefetch |
true |
JS prefetching driven by route({ prefetch }) and <Link prefetch>. Off also drops the separate prefetch chunk and makes prefetch() a no-op |
client.navigationGuards |
true |
useBlocker() navigation guards. Off also drops the per-history-entry index the router stamps so a refused back/forward traversal can be put back, and makes useBlocker() never block (it warns in development) |
client.hydrationWarnings |
false |
Keep the hydration-mismatch reporter in the production client and islands bundles, so a build can be checked before it is deployed. Not for the build you ship |
An unknown key here is an error rather than a silent no-op, so a typo cannot
quietly ship the feature you meant to remove.
Chunking
| Option |
Default |
Description |
vendorChunk |
true |
Contribute the Preact vendor chunk group to whatever the app configured in build.rollupOptions.output. false contributes nothing |
Agent surfaces
| Option |
Default |
Description |
llmsTxt |
false |
Emit llms.txt from the resolved app graph |
llmsTxt.title |
package name |
H1 title |
llmsTxt.description |
package description |
Blockquote summary under the title; omitted when neither is set |
llmsTxt.origin |
(unset) |
Origin prepended to every link, e.g. "https://example.com". Links stay root-relative when omitted |
llmsTxt.include |
["pages", "api", "capabilities"] |
Which sections to emit |
llmsTxt.exclude |
[] |
Path patterns to leave out, using the same segment globs as constraints (* is one segment, trailing ** is the rest) |
devPageTools |
true |
Register the dev-only, read-only pracht_* WebMCP page tools on every document pracht dev serves. false skips them. Never part of a build. See Dev page tools |
💡llms.txt invites agents to fetch every URL it lists. Exclude anything an
anonymous agent cannot use — pages behind auth middleware, internal tooling,
deliberate error routes. Capabilities are matched by their dispatch path
(/api/capabilities/**).
Vite options that matter
defineApp() — the route manifest
import { defineApp, group, route } from "@pracht/core";
export const app = defineApp({
routes: [route("/", "./routes/home.tsx", { render: "ssg" })],
});
| Field |
Type |
Description |
routes |
(RouteDefinition | GroupDefinition)[] |
Required. The route tree. See Routing |
shells |
Record<string, ModuleRef> |
Named shell modules |
middleware |
Record<string, ModuleRef> |
Named middleware modules |
capabilities |
Record<string, ModuleRef> |
Named capabilities, e.g. { "notes.search": () => import("./capabilities/notes-search.ts") }. Server-only and private unless they declare expose |
notFound |
ModuleRef | NotFoundConfig |
The 404 page. Deliberately not a route |
api |
ApiConfig |
App-wide API policy — see below |
agents |
PrachtAgentsConfig |
Agent trust: Web Bot Auth policy and keys, the destructive-capability confirmation flow, and the remote MCP endpoint with its optional OAuth resource-server config. Serializable data and module references only |
constraints |
RouteConstraint[] |
Declarative invariants over the resolved graph, enforced by pracht verify. See Coding Agents |
viewTransitions |
boolean |
Enable the View Transitions API for every client navigation by default. See View Transitions |
loaderTimeoutMs |
number |
Budget in milliseconds for the signal passed to middleware, loaders, and API handlers. Default 30000. The signal aborts when the budget runs out or the client disconnects, whichever comes first; one budget covers the whole request, including the not-found render after notFound(). It applies to SSG/ISG prerendering too, so a short edge budget can fail the build. See Data Loading |
api
| Field |
Default |
Description |
middleware |
[] |
Named middleware applied to every API route |
requireSameOrigin |
true |
Reject state-changing API requests (POST/PUT/PATCH/DELETE) unless the browser signals an exact same-origin fetch, or Origin/Referer matches the request URL's origin. same-site is deliberately not accepted, because sibling subdomains can be attacker-controlled. Set false only if your middleware implements its own CSRF protection |
route() and group() take the same meta fields — see the
RouteMeta table. A group's meta cascades to
its children, and a child's own meta wins.
Where the rest lives