内容
<p align="center">
<a href="https://github.com/JoviDeCroock/pracht">
<img src="./assets/banner.svg" alt="pracht — One app graph, for browsers and for agents." width="720">
</a>
</p>
<p align="center">
<a href="https://www.npmjs.com/package/@pracht/core"><img src="https://img.shields.io/npm/v/@pracht/core?color=8b5cf6&label=%40pracht%2Fcore" alt="npm version"></a>
<a href="https://github.com/JoviDeCroock/pracht/actions/workflows/ci.yml"><img src="https://github.com/JoviDeCroock/pracht/actions/workflows/ci.yml/badge.svg" alt="CI status"></a>
</p>
# pracht
**One app graph, projected to browsers and to agents.** _(pracht /praxt/ — Dutch & German for splendor. Also: how you've always mispronounced Preact.)_
Other frameworks render your app for humans and leave agents to scrape it. Pracht resolves your routes, loaders, API routes, and capabilities into one explicit graph, then projects that graph two ways: components for people, and typed, trust-gated tools for agents — over HTTP, [WebMCP](https://developer.chrome.com/docs/ai/webmcp), remote MCP, and `llms.txt`. It is a Preact framework, so the human half is small; it is an explicit framework, so the agent half is something you declare rather than something that gets scraped off you.
```bash
npm create pracht@latest my-app
```
**[Documentation](https://pracht.resynapse.dev/docs)** · [Why pracht](https://pracht.resynapse.dev/docs/why-pracht) · [Getting started](https://pracht.resynapse.dev/docs/getting-started) · [Compare to other frameworks](https://pracht.resynapse.dev/docs/demo-comparison)
## Why pracht
- **One explicit app graph** — a typed `defineApp()` manifest wires routes, shells, middleware, and capabilities. What runs where is never a mystery, and because the graph is resolved rather than inferred, tooling can read it. Prefer file-based routing? Opt in to the pages router and skip the manifest entirely.
- **The graph is projected to agents, not scraped from them** — one `defineCapability()` contract becomes a server call, an HTTP endpoint, a WebMCP page tool, and a tool on your app's own remote MCP endpoint, listed for discovery in a generated `llms.txt`. Same validation, same middleware, same effect class on every transport.
- **Trust ships with the surface** — Web Bot Auth (RFC 9421) verified agent identity, per-capability policies, a prepare/commit confirmation gate for destructive effects, one structured audit event per dispatch, and `pracht eval` to prove agent flows in CI.
- **Preact-first** — 0 KB of client JavaScript on a static route, 8.0 KB gzip with islands, 17.4 KB fully hydrated with the router. Measured by `pnpm bench` in this repo and gated in CI, not asserted.
- **Per-route render and hydration modes** — SPA, SSR, SSG, and ISG, and full, islands, or no hydration, chosen per route. No global default fighting you.
- **Vite-native** — instant HMR, fast builds, multi-environment output out of the box.
- **Performance budgets built in** — `pracht build --analyze` reports per-route client JS (gzip + raw), and per-route `budgets` fail the build when a route ships too much.
- **Env safety built in** — typed `serverEnv`/`publicEnv` helpers with a `PRACHT_PUBLIC_` prefix rule, and builds fail when client bundles reference non-public env vars.
- **Optional content collections** — `@pracht/content` gives loaders and build plugins one server-only registry for routes, locales, source/compiled representations, caching, and emitted assets.
- **Markdown images without runtime JavaScript** — `@pracht/markdown` compiles ordinary relative Markdown images through `@pracht/image` into cached responsive WebP variants for SSR, SSG, and hydration-disabled routes.
- **Deploy anywhere** — one codebase, one build, five production-ready adapters (Node, Cloudflare Workers, Netlify, Vercel, and pure static export).
## At a glance
Two routing styles, your choice:
**Manifest routing** — full control, explicit wiring:
```ts
// 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:
```ts
// 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. Directory
`_app.tsx` files provide shells, a root `_middleware.ts` wraps every page, and
modules in `src/capabilities/` plus `agents` / `constraints` from
`src/pages/_app.config.ts` provide the same agent surface as a manifest app.
Eject when you need per-route shell or middleware assignment, explicit route
ids, path-prefix groups, or webhook ISG policies. See
[docs/ROUTING.md](docs/ROUTING.md#pages-router-auto-discovery).
## Create an app
```bash
npm create pracht@latest my-app
```
The prompts cover the target directory, hosting adapter (Node.js, Cloudflare Workers, Vercel, Netlify, or a pure static export), 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](packages/start/README.md) for the full list.
The starter gives you:
- `pracht dev` — local SSR + HMR, a `/_pracht` devtools page with the resolved route/API graph plus a live capability-traffic log with explicit agent attribution (JSON at `/_pracht.json`), and `Server-Timing` middleware/loader/render phase timings on every dev SSR response
- `pracht build` — client/server output plus SSG/ISG prerendering, with `--analyze` for a per-route client JS report and budget enforcement
- `pracht preview` — build and serve the production build locally
- `pracht inspect [routes|api|capabilities|agents|build] --json` — resolved app graph metadata; `agents` summarizes the configured agent surface (transports, policies, MCP, llms.txt)
- `pracht generate route|shell|middleware|api` — framework-native scaffolding; `generate route` also emits a Playwright smoke test when the app has an e2e setup
- `pracht verify` — fast framework-aware checks with `--changed` and `--json`, including `defineApp({ constraints })` enforcement and app-graph snapshot freshness
- `pracht plan` — semantic app-graph diff against a base git ref (`--write` refreshes the committed `.pracht/app-graph.json` snapshot; `--markdown` for PR comments)
- `pracht report` — PR-ready markdown assembled from the graph diff, verify results, and bundle budgets
- `pracht 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`
## AI-assisted development
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`) plus `pracht plan` gives reviewers an intent-level diff of routes, render modes, shells, middleware, and API endpoints; `pracht report` turns it into the factual half of a PR description. See [docs/AGENT_WORKFLOW.md](docs/AGENT_WORKFLOW.md).
- **Machine-enforced invariants** — `defineApp({ constraints })` declares rules like `requireMiddleware("/app/**", "auth")` that `pracht verify` enforces deterministically, so no author (human or LLM) can merge a violation.
- **MCP server** — `pracht dev-mcp` starts a stdio [Model Context Protocol](https://modelcontextprotocol.io) 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](docs/MCP.md) for registration and the tool reference.
- **Authoring guide for agents** — `pracht llms --write` drops the framework's conventions into `llms.txt` so any coding agent picks them up.
- **Capabilities, WebMCP & remote MCP** — `@pracht/capabilities` lets you define a typed application operation once (JSON Schema contract, effect class, middleware) and project it to server code, a generated HTTP endpoint, a WebMCP page tool for in-browser agents, an MCP tool at your app's own `/mcp` endpoint for agents that never open a browser, and the human UI via `<Form capability>` — private by default, with `pracht verify` enforcing the security defaults and effect-driven revalidation keeping the page consistent after mutations. The same pipeline can be mounted in non-Pracht applications with `createCapabilityHost()`. See [docs/CAPABILITIES.md](docs/CAPABILITIES.md) and [docs/REMOTE_MCP.md](docs/REMOTE_MCP.md).
- **Agent trust layer** — Web Bot Auth (RFC 9421) verified agent identity on the request context with observe/require policies, a prepare/commit confirmation flow for destructive capabilities, capability audit events, and `pracht eval` for scripted agent-task checks in CI — over the capability HTTP projection or, with `"transport": "mcp"`, over the app's own remote MCP endpoint. See [docs/AGENT_TRUST.md](docs/AGENT_TRUST.md).
- **llms.txt** — the opt-in `llmsTxt` plugin option emits an [llms.txt](https://llmstxt.org) index of your pages, API routes, and HTTP-exposed capabilities at build time and serves it live in dev. See [docs/LLMS_TXT.md](docs/LLMS_TXT.md).
- **Claude Code skills** — 33 skills for scaffolding, auditing, testing, debugging, and deploying pracht apps live in [skills/](skills/README.md). See the [agent skills](#agent-skills) section below.
## Agent skills
The skills are distributed three ways (see the [catalog](skills/README.md)):
- **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.json`](https://pracht.resynapse.dev/.well-known/agent-skills/index.json) and advertised via a `Link: rel="agent-skills"` header.
- **create-pracht** — `npm create pracht@latest` seeds five core skills into new apps' `.claude/skills/` and writes a `.mcp.json` registering `pracht dev-mcp` (yes-default prompt, `--agent-tools=full` for the whole catalog, `--no-agent-tools` to skip).
- **In this repo** — `.claude/skills` symlinks to [skills/](skills/README.md), so Claude Code loads them automatically for contributors.
## Repo map
- [VISION_MVP.md](VISION_MVP.md) — scope and product direction
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — framework internals
- [docs/ROUTING.md](docs/ROUTING.md) — manifest and matching model
- [docs/RENDERING_MODES.md](docs/RENDERING_MODES.md) — SSR, SSG, ISG, SPA behavior
- [docs/PERFORMANCE.md](docs/PERFORMANCE.md) — bundle analysis and per-route client JS budgets
- [docs/DATA_LOADING.md](docs/DATA_LOADING.md) — loaders, forms, client hooks
- [docs/CONTENT.md](docs/CONTENT.md) — server-only collections and official Markdown integration
- [docs/API_VALIDATION.md](docs/API_VALIDATION.md) — Standard Schema validation for API routes, typed `apiFetch()`
- [docs/OPENAPI.md](docs/OPENAPI.md) — optional OpenAPI 3.1 JSON/UI endpoints and build output
- [docs/CAPABILITIES.md](docs/CAPABILITIES.md) — typed capabilities, HTTP projection, WebMCP page tools
- [docs/REMOTE_MCP.md](docs/REMOTE_MCP.md) — serving capabilities as MCP tools over Streamable HTTP
- [docs/AGENT_TRUST.md](docs/AGENT_TRUST.md) — Web Bot Auth, effect-class confirmation flow, audit hook, `pracht eval`
- [docs/CAPABILITY_GRAPH.md](docs/CAPABILITY_GRAPH.md) — the capability graph product bet: proposal, decision log, staged plan
- [docs/LLMS_TXT.md](docs/LLMS_TXT.md) — generated llms.txt: pages, API endpoints, capabilities
- [docs/STYLING.md](docs/STYLING.md) — CSS Modules, Tailwind, CSS-in-JS limitations
- [docs/ADAPTERS.md](docs/ADAPTERS.md) — Node, Cloudflare, Netlify, Vercel, and static-export deployment paths
- [docs/IMAGES.md](docs/IMAGES.md) — responsive `<Image>`, runtime loaders, and static variants
- [packages/i18n/README.md](packages/i18n/README.md) — `@pracht/i18n`: locale-detection middleware, typed dictionaries, hreflang helpers
- [packages/query/README.md](packages/query/README.md) — `@pracht/query`: TanStack Query with server-fetched queries hydrated into the browser cache
- [packages/session/README.md](packages/session/README.md) — `@pracht/session`: encrypted cookie or store-backed sessions, middleware, and password hashing
- [docs/MCP.md](docs/MCP.md) — built-in MCP server for coding agents (development time)
- [docs/AGENT_WORKFLOW.md](docs/AGENT_WORKFLOW.md) — constraints, app-graph snapshots, `pracht plan`/`report`
- [docs/ENV.md](docs/ENV.md) — typed env access, `PRACHT_PUBLIC_` prefix rule, leak detection
- [packages/start/README.md](packages/start/README.md) — starter CLI details
- [packages/test/README.md](packages/test/README.md) — `@pracht/test` unit-testing utilities for loaders, API routes, middleware, and forms
## Contributing
Use the GitHub issue templates for bug reports and feature requests. When opening a pull request, follow [.github/PULL_REQUEST_TEMPLATE.md](.github/PULL_REQUEST_TEMPLATE.md).
连接信息
猜你喜欢
暂无推荐服务器