Full-stack Preact, per route. (pracht /praxt/ — Dutch & German for splendor. Also: how you've always mispronounced Preact.)
Pick SPA, SSR, SSG, or ISG on a route-by-route basis. Ship less JavaScript by default. Deploy the same codebase to Node, Cloudflare, or Vercel.
npm create pracht@latest my-appDocumentation · Why pracht · Getting started · Compare to other frameworks
- Preact-first — the low bundle size that you know and love with a familiar API.
- Per-route render modes — SPA, SSR, SSG, and ISG in the same app. No global default fighting you.
- Explicit over magic — a typed
defineApp()manifest wires routes, shells, and middleware. What runs where is never a mystery. Prefer file-based routing? Opt in to the pages router and skip the manifest entirely. - Vite-native — instant HMR, fast builds, multi-environment output out of the box.
- Performance budgets built in —
pracht build --analyzereports per-route client JS (gzip + raw), and per-routebudgetsfail the build when a route ships too much. - Deploy anywhere — one codebase, one build, three production-ready adapters (Node, Cloudflare Workers, Vercel).
- Env safety built in — typed
serverEnv/publicEnvhelpers with aPRACHT_PUBLIC_prefix rule, and builds fail when client bundles reference non-public env vars.
Two routing styles, your choice:
Manifest routing — full control, explicit wiring:
// src/routes.ts
import { defineApp, group, route, timeRevalidate } from "@pracht/core";
export const app = defineApp({
shells: {
app: () => import("./shells/app.tsx"),
public: () => import("./shells/public.tsx"),
},
middleware: {
auth: () => import("./middleware/auth.ts"),
},
routes: [
group({ shell: "public" }, [
route("/", () => import("./routes/home.tsx"), { render: "ssg" }),
route("/pricing", () => import("./routes/pricing.tsx"), {
render: "isg",
revalidate: timeRevalidate(3600),
}),
]),
group({ shell: "app", middleware: ["auth"] }, [
route("/dashboard", () => import("./routes/dashboard.tsx"), { render: "ssr" }),
route("/settings", () => import("./routes/settings.tsx"), { render: "spa" }),
]),
],
});One manifest. Four render strategies. No renaming folders to change behavior.
Pages router — file-based, zero manifest:
// vite.config.ts
export default defineConfig({
plugins: [pracht({ pagesDir: "/src/pages", adapter: nodeAdapter() })],
});src/pages/
index.tsx → /
blog/[slug].tsx → /blog/:slug
Same render modes, same adapters — just let the filesystem drive.
npm create pracht@latest my-appThe prompts cover the target directory, hosting adapter (Node.js, Cloudflare Workers, Vercel), router (manifest or pages), and optional Tailwind CSS. For non-interactive runs pass flags instead — e.g. --template=tailwind (or --template=minimal), --adapter=node, --no-git, --yes. See packages/start/README.md for the full list.
The starter gives you:
pracht dev— local SSR + HMR, a/_prachtdevtools page with the resolved route/API graph (JSON at/_pracht.json), andServer-Timingmiddleware/loader/render phase timings on every dev SSR responsepracht build— client/server output plus SSG/ISG prerendering, with--analyzefor a per-route client JS report and budget enforcementpracht preview— build and serve the production build locallypracht inspect [routes|api|build] --json— resolved app graph metadatapracht generate route|shell|middleware|api— framework-native scaffolding;generate routealso emits a Playwright smoke test when the app has an e2e setuppracht verify— fast framework-aware checks with--changedand--json, includingdefineApp({ constraints })enforcement and app-graph snapshot freshnesspracht plan— semantic app-graph diff against a base git ref (--writerefreshes the committed.pracht/app-graph.jsonsnapshot;--markdownfor PR comments)pracht report— PR-ready markdown assembled from the graph diff, verify results, and bundle budgetspracht doctor— app wiring checks with optional JSON output- Optional Tailwind CSS wiring, a git repo with an initial commit, and (for the Node adapter) a multi-stage
Dockerfile
Pracht is built to be operated by coding agents as much as by humans — and for the humans reviewing what agents produce:
- Provable changes — a committed app-graph snapshot (
.pracht/app-graph.json) pluspracht plangives reviewers an intent-level diff of routes, render modes, shells, middleware, and API endpoints;pracht reportturns it into the factual half of a PR description. See docs/AGENT_WORKFLOW.md. - Machine-enforced invariants —
defineApp({ constraints })declares rules likerequireMiddleware("/app/**", "auth")thatpracht verifyenforces deterministically, so no author (human or LLM) can merge a violation. - MCP server —
pracht mcpstarts a stdio Model Context Protocol server so agents can natively inspect the resolved app graph, run doctor/verify diagnostics, diff and snapshot the graph (plan/report), read the authoring guide (get_docs), and scaffold routes, shells, middleware, and API handlers. See docs/MCP.md for registration and the tool reference. - Authoring guide for agents —
pracht llms --writedrops the framework's conventions intollms.txtso any coding agent picks them up. - Claude Code skills — 28 skills for scaffolding, auditing, testing, debugging, and deploying pracht apps live in skills/. See the agent skills section below.
The skills are distributed three ways (see the catalog):
- Discovery endpoint — every skill is published at
https://pracht.resynapse.dev/skills/<name>/SKILL.md, listed with SHA-256 digests in the manifest at/.well-known/agent-skills/index.jsonand advertised via aLink: rel="agent-skills"header. - create-pracht —
npm create pracht@latestseeds the full catalog into new apps'.claude/skills/and writes a.mcp.jsonregistering thepracht mcpserver (yes-default prompt,--no-agent-toolsto skip). - In this repo —
.claude/skillssymlinks to skills/, so Claude Code loads them automatically for contributors.
- VISION_MVP.md — scope and product direction
- docs/ARCHITECTURE.md — framework internals
- docs/ROUTING.md — manifest and matching model
- docs/RENDERING_MODES.md — SSR, SSG, ISG, SPA behavior
- docs/PERFORMANCE.md — bundle analysis and per-route client JS budgets
- docs/DATA_LOADING.md — loaders, forms, client hooks
- docs/API_VALIDATION.md — Standard Schema validation for API routes, typed
apiFetch() - docs/STYLING.md — CSS Modules, Tailwind, CSS-in-JS limitations
- docs/ADAPTERS.md — Node, Cloudflare, Vercel deployment paths
- docs/MCP.md — built-in MCP server for coding agents
- docs/AGENT_WORKFLOW.md — constraints, app-graph snapshots,
pracht plan/report - docs/ENV.md — typed env access,
PRACHT_PUBLIC_prefix rule, leak detection - packages/start/README.md — starter CLI details
Use the GitHub issue templates for bug reports and feature requests. When opening a pull request, follow .github/PULL_REQUEST_TEMPLATE.md.