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. Every feature defaults to true. Turn one 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) |
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) |
💡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