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.
- package/package.json +1 -1
- package/skills/add-auth/SKILL.md +63 -143
- package/skills/add-capabilities/SKILL.md +409 -0
- package/skills/add-content/SKILL.md +242 -0
- package/skills/add-db/SKILL.md +93 -202
- package/skills/add-i18n/SKILL.md +178 -217
- package/skills/add-images/SKILL.md +203 -0
- package/skills/add-observability/SKILL.md +118 -15
- package/skills/add-openapi/SKILL.md +209 -0
- package/skills/audit-a11y/SKILL.md +8 -9
- package/skills/audit-agent-surface/SKILL.md +335 -0
- package/skills/audit-auth/SKILL.md +16 -11
- package/skills/audit-bundles/SKILL.md +48 -12
- package/skills/audit-csrf/SKILL.md +9 -10
- package/skills/audit-deps/SKILL.md +8 -8
- package/skills/audit-headers/SKILL.md +9 -10
- package/skills/audit-islands/SKILL.md +9 -10
- package/skills/audit-loaders/SKILL.md +23 -8
- package/skills/audit-redirects/SKILL.md +9 -10
- package/skills/audit-secrets/SKILL.md +6 -6
- package/skills/audit-seo/SKILL.md +8 -8
- package/skills/audit-shells/SKILL.md +8 -9
- package/skills/configure-isg/SKILL.md +9 -10
- package/skills/migrate-nextjs/SKILL.md +200 -424
- package/skills/pracht-debug/SKILL.md +165 -128
- package/skills/pracht-deploy/SKILL.md +246 -331
- package/skills/pracht-scaffold/SKILL.md +123 -146
- package/skills/pracht-test-api/SKILL.md +10 -10
- package/skills/pre-deploy/SKILL.md +165 -200
- package/skills/scaffold-e2e/SKILL.md +11 -12
- package/skills/scaffold-tests/SKILL.md +10 -12
- package/skills/tune-render-mode/SKILL.md +7 -8
- package/skills/typed-routes/SKILL.md +9 -9
- package/skills/upgrade-pracht/SKILL.md +7 -8
- package/src/index.js +38 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pracht-scaffold
|
|
3
|
-
version: 1.
|
|
3
|
+
version: 1.2.0
|
|
4
4
|
description: |
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
| `--
|
|
42
|
-
| `--
|
|
43
|
-
| `--
|
|
44
|
-
| `--
|
|
45
|
-
| `--
|
|
46
|
-
| `--
|
|
47
|
-
| `--
|
|
48
|
-
| `--
|
|
49
|
-
| `--
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
-
|
|
59
|
-
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
//
|
|
139
|
-
//
|
|
140
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
160
|
-
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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.
|
|
3
|
+
version: 1.2.1
|
|
4
4
|
description: |
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Use
|
|
9
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
config
|
|
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
|