create-pracht 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/skills/add-auth/SKILL.md +63 -143
  3. package/skills/add-capabilities/SKILL.md +409 -0
  4. package/skills/add-content/SKILL.md +242 -0
  5. package/skills/add-db/SKILL.md +93 -202
  6. package/skills/add-i18n/SKILL.md +178 -217
  7. package/skills/add-images/SKILL.md +203 -0
  8. package/skills/add-observability/SKILL.md +118 -15
  9. package/skills/add-openapi/SKILL.md +209 -0
  10. package/skills/audit-a11y/SKILL.md +8 -9
  11. package/skills/audit-agent-surface/SKILL.md +335 -0
  12. package/skills/audit-auth/SKILL.md +16 -11
  13. package/skills/audit-bundles/SKILL.md +48 -12
  14. package/skills/audit-csrf/SKILL.md +9 -10
  15. package/skills/audit-deps/SKILL.md +8 -8
  16. package/skills/audit-headers/SKILL.md +9 -10
  17. package/skills/audit-islands/SKILL.md +9 -10
  18. package/skills/audit-loaders/SKILL.md +23 -8
  19. package/skills/audit-redirects/SKILL.md +9 -10
  20. package/skills/audit-secrets/SKILL.md +6 -6
  21. package/skills/audit-seo/SKILL.md +8 -8
  22. package/skills/audit-shells/SKILL.md +8 -9
  23. package/skills/configure-isg/SKILL.md +9 -10
  24. package/skills/migrate-nextjs/SKILL.md +200 -424
  25. package/skills/pracht-debug/SKILL.md +165 -128
  26. package/skills/pracht-deploy/SKILL.md +246 -331
  27. package/skills/pracht-scaffold/SKILL.md +123 -146
  28. package/skills/pracht-test-api/SKILL.md +10 -10
  29. package/skills/pre-deploy/SKILL.md +165 -200
  30. package/skills/scaffold-e2e/SKILL.md +11 -12
  31. package/skills/scaffold-tests/SKILL.md +10 -12
  32. package/skills/tune-render-mode/SKILL.md +7 -8
  33. package/skills/typed-routes/SKILL.md +9 -9
  34. package/skills/upgrade-pracht/SKILL.md +7 -8
  35. package/src/index.js +38 -0
@@ -1,13 +1,12 @@
1
1
  ---
2
2
  name: pracht-scaffold
3
- version: 1.1.0
3
+ version: 1.2.0
4
4
  description: |
5
- Pracht code scaffolding. Prefer the framework-native CLI generators
6
- (`pracht generate route|shell|middleware|api`) and only fall back to manual
7
- edits when the CLI flags cannot express the requested shape. Knows pracht
8
- conventions (Preact idioms, render modes, route manifest).
9
- Use when asked to "scaffold", "generate a route", "create a new page",
10
- "add middleware", "add an API route", or "create a shell".
5
+ Scaffold pracht code with the native generators (`pracht generate
6
+ route|shell|middleware|api`), falling back to manual edits only when the CLI
7
+ flags cannot express the requested shape.
8
+ Use for "scaffold", "generate a route", "create a new page", "add middleware",
9
+ "add an API route", "create a shell".
11
10
  allowed-tools:
12
11
  - Bash
13
12
  - Read
@@ -20,11 +19,12 @@ allowed-tools:
20
19
 
21
20
  # Pracht Scaffold
22
21
 
23
- Generate pracht framework modules with correct types, exports, and manifest wiring.
22
+ Parse what the user wants to create and generate it with the CLI. Ask when
23
+ something is ambiguous (render mode, shell assignment). Keep generated code
24
+ minimal — only the exports they actually need — and finish by summarizing what
25
+ was created and how it was wired.
24
26
 
25
- ## First Choice
26
-
27
- Use the CLI first:
27
+ ## Always try the CLI first
28
28
 
29
29
  ```bash
30
30
  pracht generate route --path /dashboard --render ssr
@@ -33,169 +33,146 @@ pracht generate middleware --name auth
33
33
  pracht generate api --path /health --methods GET,POST
34
34
  ```
35
35
 
36
- `pracht generate route` supports the full flag matrix below — do not fall back to manual edits for shapes it already covers:
37
-
38
- | Flag | Meaning |
39
- | ------------------ | ------------------------------------------------------------------------------------ |
40
- | `--path` (required) | Route path, e.g. `/dashboard` or `/blog/:slug` |
41
- | `--render` | Render mode: `ssr` (default), `spa`, `ssg`, or `isg` |
42
- | `--shell` | Registered shell name (manifest apps only) |
43
- | `--middleware` | Registered middleware names, comma-separated (manifest apps only) |
44
- | `--loader` | Include a `loader` export |
45
- | `--error-boundary` | Include an `ErrorBoundary` export |
46
- | `--static-paths` | Include `getStaticPaths` (added automatically for dynamic `ssg`/`isg` paths) |
47
- | `--title` | Page title used in the `head()` export |
48
- | `--revalidate` | ISG revalidation window in seconds (`isg` only, default 3600) |
49
- | `--json` | Machine-readable output |
50
-
51
- `generate shell` and `generate middleware` take `--name`; `generate api` takes `--path` and `--methods` (comma-separated). All subcommands accept `--json`.
52
-
53
- - `--shell`/`--middleware` names must already be registered in the app manifest — the CLI errors otherwise. Generate the shell/middleware first, then the route that references it.
54
- - If the pracht MCP server is registered (docs/MCP.md), call the `generate_route`/`generate_shell`/`generate_middleware`/`generate_api` MCP tools instead of Bash — same behavior, structured results.
55
- - Add `--json` when another agent/tool needs machine-readable output.
56
- - `generate route` also emits a Playwright smoke test in `e2e/` when the app has a Playwright setup (`playwright.config.*` or an `e2e/` directory). Pass `--no-test` to skip it, `--test` to force it. The test imports `@playwright/test`; if that dependency is absent, follow the generator's install note before typechecking. Keep the generated test — it is the output-level proof the route works.
57
- - Use `pracht inspect routes --json` or `pracht inspect api --json` to confirm current wiring before manual edits when the existing graph matters. `pracht inspect` requires the pracht plugin registered in the project's vite config.
58
- - If the app has typed routes (`src/pracht-routes.ts` / `.d.ts`) or the user asks for typed links, run `pracht typegen` after adding or renaming routes.
59
- - If the app commits `.pracht/app-graph.json`, run `pracht plan --write` after changing routes and include the refreshed snapshot — `pracht verify` fails when it is stale.
60
- - If `src/routes.ts` declares `constraints:`, respect them (e.g. put new `/app/**` routes behind the required middleware). Never delete or weaken a constraint to make `pracht verify` pass — that is a policy change the user must approve.
61
- - If the CLI can express the request, do not reimplement the scaffold by hand.
62
- - Only edit files manually when the CLI cannot cover the requested shape.
63
-
64
- The user will describe what they want to create. Parse their request and generate the appropriate module(s). Always ask if anything is ambiguous (e.g. render mode, shell assignment).
65
-
66
- ## What You Can Scaffold
67
-
68
- | Kind | Directory | Key exports | Example |
69
- | ---------- | ----------------- | -------------------------------------------------------------------- | ------------------------------ |
70
- | Route | `src/routes/` | `loader`, `head`, `Component`, `ErrorBoundary`, `getStaticPaths` | `src/routes/blog.tsx` |
71
- | Shell | `src/shells/` | `Shell`, `head` | `src/shells/marketing.tsx` |
72
- | Middleware | `src/middleware/` | `middleware` | `src/middleware/rate-limit.ts` |
73
- | API route | `src/api/` | Named HTTP method handlers (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`) or one default method dispatcher | `src/api/users/[id].ts` |
36
+ If the CLI can express the request, do not reimplement the scaffold by hand.
37
+ `pracht generate route` covers this flag matrix:
38
+
39
+ | Flag | Meaning |
40
+ | ------------------- | ---------------------------------------------------------------------------- |
41
+ | `--path` (required) | Route path, e.g. `/dashboard` or `/blog/:slug` |
42
+ | `--render` | `ssr` (default), `spa`, `ssg`, or `isg` |
43
+ | `--shell` | Registered shell name (manifest apps only) |
44
+ | `--middleware` | Registered middleware names, comma-separated (manifest apps only) |
45
+ | `--loader` | Include a `loader` export |
46
+ | `--error-boundary` | Include an `ErrorBoundary` export |
47
+ | `--static-paths` | Include `getStaticPaths` (automatic for dynamic `ssg`/`isg` paths) |
48
+ | `--title` | Page title for the `head()` export |
49
+ | `--revalidate` | ISG window in seconds (`isg` only, default 3600) |
50
+ | `--json` | Machine-readable output |
51
+
52
+ `generate shell` and `generate middleware` take `--name`; `generate api` takes
53
+ `--path` and `--methods`. All subcommands accept `--json` — use it when another
54
+ agent or tool consumes the output. When the pracht MCP server is registered
55
+ (docs/MCP.md), call the `generate_route`/`generate_shell`/`generate_middleware`/
56
+ `generate_api` MCP tools instead of Bash: same behavior, structured results.
57
+
58
+ - `--shell`/`--middleware` names must already be registered or the CLI errors.
59
+ Generate the shell or middleware first, then the route referencing it.
60
+ - `generate route` also emits a Playwright smoke test in `e2e/` when the app
61
+ has a Playwright setup (`playwright.config.*` or an `e2e/` directory);
62
+ `--no-test` skips it, `--test` forces it. The test imports
63
+ `@playwright/test` — if that dependency is missing, follow the generator's
64
+ install note before typechecking. Keep the test: it is the output-level proof
65
+ the route works.
66
+ - **The generators wire the manifest themselves.** `generate route` inserts the
67
+ `route(...)` call into `src/routes.ts` (adding `route`/`timeRevalidate`
68
+ imports as needed) and `generate shell`/`generate middleware` upsert their
69
+ registry entries. Do not re-edit the manifest after a successful run.
70
+
71
+ ## Project conventions
72
+
73
+ | Kind | Directory | Key exports |
74
+ | ---------- | ----------------- | -------------------------------------------------------------------------------- |
75
+ | Route | `src/routes/` | `loader`, `head`, `Component`, `ErrorBoundary`, `getStaticPaths` |
76
+ | Shell | `src/shells/` | `Shell`, `head` |
77
+ | Middleware | `src/middleware/` | `middleware` |
78
+ | API route | `src/api/` | Named method handlers (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`) or one default dispatcher |
79
+
80
+ Render modes: `"ssr"` (default), `"ssg"` (static at build), `"isg"`
81
+ (incremental static, `revalidate: timeRevalidate(seconds)` — import
82
+ `timeRevalidate` from `@pracht/core`), `"spa"` (client-only). Use Preact
83
+ idioms: `class` not `className`, functional components, `import type` for
84
+ type-only imports.
85
+
86
+ Before and after scaffolding:
87
+
88
+ - Read `pracht inspect routes --json` / `pracht inspect api --json` to confirm
89
+ current wiring when the existing graph matters. `pracht inspect` needs the
90
+ pracht plugin in the vite config.
91
+ - If `src/routes.ts` declares `constraints:`, respect them — e.g. put new
92
+ `/app/**` routes behind the required middleware. Never delete or weaken a
93
+ constraint to make `pracht verify` pass; that is a policy change only the
94
+ user can approve.
95
+ - Run `pracht typegen` after adding or renaming routes in a typed-routes app
96
+ (`src/pracht-routes.ts` / `.d.ts`), and include the generated files.
97
+ - Run `pracht plan --write` if the app commits `.pracht/app-graph.json` —
98
+ `pracht verify` fails on a stale snapshot.
99
+ - Finish with `pracht verify`.
100
+
101
+ ## Manual fallback
102
+
103
+ Only for shapes the CLI cannot express. Read the existing `src/routes.ts` first
104
+ to pick up current shells, middleware, and structure.
105
+
106
+ **Route** — `head()` plus `Component`; add `loader` only when the route needs
107
+ server data (the CLI omits it unless `--loader` is passed), `ErrorBoundary`
108
+ only if requested, and `getStaticPaths` only for SSG/ISG routes with dynamic
109
+ segments:
74
110
 
75
- ## Templates (manual fallback)
76
-
77
- Use these only when the CLI cannot express the requested shape.
111
+ ```tsx
112
+ import type { LoaderArgs, RouteComponentProps } from "@pracht/core";
78
113
 
79
- ### Route
114
+ export async function loader(_args: LoaderArgs) {
115
+ return {/* loader data */};
116
+ }
80
117
 
81
- ```tsx
82
118
  export function head() {
83
119
  return { title: "Page Title" };
84
120
  }
85
121
 
86
- export function Component() {
122
+ export function Component({ data }: RouteComponentProps<typeof loader>) {
87
123
  return <section>{/* route UI */}</section>;
88
124
  }
89
125
  ```
90
126
 
91
- - Include a `loader` only when the route needs server data (matches the CLI, which omits it unless `--loader` is passed):
92
-
93
- ```tsx
94
- import type { LoaderArgs, RouteComponentProps } from "@pracht/core";
95
-
96
- export async function loader(_args: LoaderArgs) {
97
- return {
98
- /* loader data */
99
- };
100
- }
101
-
102
- export function Component({ data }: RouteComponentProps<typeof loader>) {
103
- return <section>{/* route UI */}</section>;
104
- }
105
- ```
106
-
107
- - Include `ErrorBoundary` only if requested.
108
- - Include `getStaticPaths` only for SSG/ISG routes with dynamic segments.
109
- - Use `RouteComponentProps<typeof loader>` for typed `data` prop.
110
-
111
- ### Shell
112
-
113
- ```tsx
114
- import type { ShellProps } from "@pracht/core";
115
-
116
- export function Shell({ children }: ShellProps) {
117
- return (
118
- <div class="shell-name">
119
- <nav>{/* navigation */}</nav>
120
- <main>{children}</main>
121
- </div>
122
- );
123
- }
124
-
125
- export function head() {
126
- return { title: "Shell Title" };
127
- }
128
- ```
129
-
130
- ### Middleware
127
+ **Shell** — `Shell({ children }: ShellProps)` rendering `{children}`, plus an
128
+ optional `head()`. Never render `<html>`, `<head>`, or `<body>`.
131
129
 
132
- Middleware wraps the rest of the request via `next()`:
130
+ **Middleware** — wrap-around via `next()`:
133
131
 
134
132
  ```ts
135
133
  import { redirect, type MiddlewareFn } from "@pracht/core";
136
134
 
137
135
  export const middleware: MiddlewareFn = async ({ context, request }, next) => {
138
- // Mutate context, validate auth, etc.
139
- // - Call `return next()` to continue
140
- // - Return `redirect("/path", { request })` to short-circuit with a redirect
141
- // - Return any `Response` to short-circuit
142
- // - Wrap `await next()` in try/catch/finally for tracing/logging
136
+ // `return next()` continues; returning any Response short-circuits, e.g.
137
+ // `redirect("/path", { request })`. Wrap `await next()` in try/catch/finally
138
+ // for tracing.
143
139
  return next();
144
140
  };
145
141
  ```
146
142
 
147
- ### API Route
143
+ **API route** — one export per method the user needs (or a default export only
144
+ when they want to branch on `request.method` manually), parsing bodies with
145
+ `request.json()` / `request.formData()` and always returning a `Response`:
148
146
 
149
147
  ```ts
150
148
  import type { ApiRouteArgs } from "@pracht/core";
151
149
 
152
150
  export function GET({ params, url }: ApiRouteArgs) {
153
- return Response.json({
154
- /* response data */
155
- });
151
+ return Response.json({/* response data */});
156
152
  }
157
153
  ```
158
154
 
159
- - Only include the HTTP methods the user needs.
160
- - Use a default export only when the user wants to branch on `request.method` manually.
161
- - Use `request.json()`, `request.formData()`, etc. for body parsing.
162
- - Always return `Response` objects (typically `Response.json()`).
163
- - Dynamic segments use bracket syntax in filenames: `[id].ts`, `[...slug].ts`.
164
- - For live server→client updates, use Server-Sent Events:
165
- `createEventStream(request, { keepAlive: 15 })` from `@pracht/core/server`
166
- returns `{ response, send, close }` — return `response`, push with
167
- `send({ data, event?, id? })`, and stop producing when `send()` returns
168
- `false` (client disconnected). Consume in components with
169
- `useEventSource(url, { json: true })` from `@pracht/core`. Works on all
170
- adapters. For WebSockets use `isUpgradeRequest(request)` plus the
171
- per-adapter recipes in `docs/ADAPTERS.md` (Cloudflare: API route + Durable
172
- Object; Node: `nodeAdapter({ configureServerFrom })`; Vercel: unsupported —
173
- use SSE).
174
-
175
- ## Wiring Into the Manifest (manual fallback only)
176
-
177
- The CLI generators wire the manifest themselves: `pracht generate route` inserts the `route(...)` call into `src/routes.ts` (adding `route`/`timeRevalidate` imports as needed), and `generate shell`/`generate middleware` upsert their registry entries. **Do not re-edit the manifest after a successful `pracht generate` run.**
178
-
179
- Only when you created module files by hand, update `src/routes.ts` to register the new module:
180
-
181
- - **Routes**: Add a `route("/path", () => import("./routes/filename.tsx"), { id: "name", render: "ssr" })` call inside the appropriate group or at the top level. Plain strings like `"./routes/filename.tsx"` also work.
182
- - **Shells**: Add to the `shells` record: `shellName: () => import("./shells/filename.tsx")` (or `"./shells/filename.tsx"`).
183
- - **Middleware**: Add to the `middleware` record: `mwName: () => import("./middleware/filename.ts")` (or `"./middleware/filename.ts"`).
184
- - **API routes**: No manifest change needed — auto-discovered from `src/api/` by the Vite plugin.
185
-
186
- Available render modes: `"ssr"` (default), `"ssg"` (static at build), `"isg"` (incremental static with `revalidate: timeRevalidate(seconds)`), `"spa"` (client-only).
187
-
188
- Import `timeRevalidate` from `"@pracht/core"` when using ISG.
189
-
190
- ## Rules
191
-
192
- 1. Prefer `pracht generate ...` over manual edits.
193
- 2. Read the project's existing `src/routes.ts` to determine current shells, middleware, and route structure before adding when the CLI cannot finish the job on its own.
194
- 3. Place files in the conventional directories (`src/routes/`, `src/shells/`, `src/middleware/`, `src/api/`).
195
- 4. Keep generated code minimal — only include exports the user actually needs.
196
- 5. Use Preact idioms: `class` not `className`, functional components, `import type` for type-only imports.
197
- 6. When route ids/paths change in a typed-routes app, run `pracht typegen` and include the generated route files.
198
- 7. Finish with `pracht verify` (and `pracht plan --write` when the app commits an app-graph snapshot).
199
- 8. After scaffolding, summarize what was created and how it was wired.
155
+ Dynamic segments use bracket filenames: `[id].ts`, `[...slug].ts`. API routes
156
+ are auto-discovered — no manifest entry.
157
+
158
+ For live server→client updates, use Server-Sent Events:
159
+ `createEventStream(request, { keepAlive: 15 })` from `@pracht/core/server`
160
+ returns `{ response, send, close }` — return `response`, push with
161
+ `send({ data, event?, id? })`, and stop producing when `send()` returns `false`
162
+ (client disconnected). Consume with `useEventSource(url, { json: true })` from
163
+ `@pracht/core`. Works on every adapter. For WebSockets use
164
+ `isUpgradeRequest(request)` plus the per-adapter recipes in `docs/ADAPTERS.md`
165
+ (Cloudflare: API route + Durable Object; Node:
166
+ `nodeAdapter({ configureServerFrom })`; Vercel: unsupported — use SSE).
167
+
168
+ **Manifest wiring**, only for hand-created files:
169
+
170
+ - Route — a `route("/path", () => import("./routes/file.tsx"), { id: "name",
171
+ render: "ssr" })` call in the right group or at the top level.
172
+ - Shell — `shellName: () => import("./shells/file.tsx")` in the `shells` record.
173
+ - Middleware — `mwName: () => import("./middleware/file.ts")` in the
174
+ `middleware` record.
175
+
176
+ Plain `"./routes/file.tsx"` strings work in place of the import functions.
200
177
 
201
178
  $ARGUMENTS
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: pracht-test-api
3
- version: 1.2.0
3
+ version: 1.2.1
4
4
  description: |
5
- Auto-generate Vitest request/response tests for every handler in `src/api/`.
6
- Each test instantiates a `Request`, calls the exported HTTP method handler
7
- directly, and asserts on the returned `Response` — no server boot required.
8
- Use when asked to "test my API routes", "scaffold API tests", "generate
9
- tests for src/api", or "add tests for this endpoint".
5
+ Generate Vitest request/response tests for every handler in `src/api/`: build a
6
+ `Request`, call the exported method handler directly, assert on the returned
7
+ `Response` — no server boot.
8
+ Use for "test my API routes", "scaffold API tests", "generate tests for
9
+ src/api", "add tests for this endpoint".
10
10
  allowed-tools:
11
11
  - Bash
12
12
  - Read
@@ -31,10 +31,10 @@ prompt the user to). This skill does not handle Vitest setup.
31
31
 
32
32
  ## Step 2: Enumerate API handlers
33
33
 
34
- If the pracht MCP server is registered (see docs/MCP.md), prefer its tools
35
- (`inspect_routes`, `inspect_api`, `inspect_build`, `doctor`, `verify`,
36
- `generate_*`) over shelling out. Prerequisite: `pracht inspect` needs a vite
37
- config with the pracht plugin registered.
34
+ MCP: when the pracht MCP server is registered (docs/MCP.md), prefer its
35
+ `inspect_routes`/`inspect_api`/`inspect_build`/`doctor`/`verify`/`generate_*`
36
+ tools over shelling out. `pracht inspect` needs the pracht plugin in the vite
37
+ config.
38
38
 
39
39
  ```bash
40
40
  pracht inspect api --json