create-pracht 0.6.0 → 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 +56 -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 -415
  25. package/skills/pracht-debug/SKILL.md +165 -120
  26. package/skills/pracht-deploy/SKILL.md +248 -329
  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 +166 -195
  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 +15 -11
  34. package/skills/upgrade-pracht/SKILL.md +12 -10
  35. package/src/index.js +43 -0
@@ -1,14 +1,12 @@
1
1
  ---
2
2
  name: pracht-debug
3
- version: 1.3.0
3
+ version: 1.4.0
4
4
  description: |
5
- Pracht framework-aware debugging. Systematically investigates route matching,
6
- loader/API route errors, rendering issues, middleware, API routes, HMR, and build
7
- problems. Uses pracht's architecture knowledge to find root causes fast.
8
- Use when asked to "debug this", "fix this bug", "why is this broken",
9
- "blank page", "hydration mismatch", or "404 on my route".
10
- Proactively suggest when the user reports errors or unexpected behavior
11
- in a pracht application.
5
+ Framework-aware debugging for pracht: route matching, loader and API errors,
6
+ rendering and hydration, middleware, HMR, and build failures — root cause first.
7
+ Use for "debug this", "fix this bug", "why is this broken", "blank page",
8
+ "hydration mismatch", "404 on my route"; suggest it when the user reports
9
+ unexpected pracht behavior.
12
10
  allowed-tools:
13
11
  - Bash
14
12
  - Read
@@ -21,126 +19,173 @@ allowed-tools:
21
19
 
22
20
  # Pracht Debug
23
21
 
24
- Framework-aware debugging for pracht applications — a full-stack Preact framework built on Vite.
22
+ **Iron law: no fixes without root-cause investigation first.** Read the
23
+ relevant source before diagnosing, start from the most likely cause for the
24
+ symptom rather than a full audit, and when you find the root cause explain
25
+ *why* it breaks. After fixing, prove the fix — run the test, check the dev
26
+ server. Never say "this should fix it."
25
27
 
26
- The user will describe a symptom (error, unexpected behavior, blank page, etc.). Investigate systematically using the checklist below, stopping when you find the root cause.
28
+ ## Instruments
27
29
 
28
- Before deep manual inspection, prefer running `pracht verify` (add `--changed` to scope the checks to git-changed files) for a fast agent loop or `pracht doctor` when the problem could be caused by broader broken app wiring or missing files.
29
- When another agent/tool needs the framework's resolved graph, prefer `pracht inspect routes --json`, `pracht inspect api --json`, or `pracht inspect build --json` over reconstructing it from source files. Prerequisites: `pracht inspect` needs the pracht plugin registered in the project's vite config, and `pracht inspect build` needs a prior `pracht build`.
30
- If the pracht MCP server is registered (docs/MCP.md), prefer the `inspect_routes`/`inspect_api`/`doctor`/`verify` MCP tools over shelling out — same payloads, structured results.
31
- While the dev server is running, `GET /_pracht` serves a devtools page with the same resolved route/API graph (raw JSON at `/_pracht.json`) — useful when you have a browser or `curl` handy but no CLI access. Under a Vite deploy base, prefix both paths with that base; links from the devtools and dev-404 pages already do so. Dev SSR responses also carry a `Server-Timing` header (`mw`, `loader`, `render` durations in ms) — check it in the browser Network panel or with `curl -sI` to see which phase makes a route slow.
30
+ Reach for these before deep manual inspection:
32
31
 
33
- ## Iron Law
32
+ | Tool | Use |
33
+ | ---- | --- |
34
+ | `pracht verify` (`--changed` to scope to git-changed files) | Fast confidence check |
35
+ | `pracht doctor` | Broader broken wiring or missing files |
36
+ | `pracht inspect routes\|api\|build --json` | The resolved graph — never reconstruct it from source |
37
+ | `GET /_pracht` (JSON at `/_pracht.json`) | Same graph from a running dev server, no CLI needed |
38
+ | `Server-Timing` on dev SSR responses | `mw` / `loader` / `render` durations in ms — which phase is slow |
34
39
 
35
- **NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST.**
40
+ `pracht inspect` needs the pracht plugin in the vite config; `inspect build`
41
+ needs a prior `pracht build`. Under a Vite deploy base, prefix `/_pracht` with
42
+ that base (links from the devtools and dev-404 pages already do). When the
43
+ pracht MCP server is registered (docs/MCP.md), prefer the
44
+ `inspect_routes`/`inspect_api`/`doctor`/`verify` MCP tools — same payloads,
45
+ structured results.
36
46
 
37
- ## Debugging Checklist
47
+ ## Checklist
38
48
 
39
- Work through these in order, stopping when you find the root cause:
49
+ Work in order; stop at the root cause.
40
50
 
41
51
  ### 1. Route matching
42
52
 
43
- - Run `pracht verify --changed` first if you want a cheap changed-file confidence check.
44
- - Run `pracht doctor` if the route might be missing, miswired, or pointing at a missing module across the project.
45
- - For machine-readable route wiring, run `pracht inspect routes --json`. With a running dev server, `curl http://localhost:5173/_pracht.json` returns the same graph.
46
- - Read `src/routes.ts` — is the route defined? Is the path correct?
47
- - Check for typos in file paths (the manifest uses relative paths like `"./routes/home.tsx"`).
48
- - For dynamic segments, verify bracket syntax: `route("/users/:id", ...)` in manifest, `[id].ts` in filenames.
49
- - Grep for the route path across the manifest and check `matchAppRoute()` logic if needed.
50
-
51
- ### 2. Typed route/link issues
52
-
53
- - If `<Link route="...">`, `href("...")`, or route-object `useNavigate()` fails to typecheck, run `pracht typegen --check` to detect stale generated files.
54
- - Run `pracht inspect routes --json` and confirm the route id exists. If it is a fallback id, remember path changes can rename it.
55
- - Check generated `src/pracht.d.ts` for inferred params. `:id`, `*`, and `:path*` params are required; extra params should fail at typecheck time.
56
- - If runtime navigation throws `Unknown pracht route id "..."`, in dev the error includes a `Did you mean "..."?` suggestion and the list of registered route ids (production builds tree-shake this and throw the bare error) — check for a typo first, then ensure `pracht typegen` was run and the component is rendered inside the pracht route tree.
57
- - For unexpected URLs, reproduce with `href(routeId, options)` and compare against the route's resolved path and params.
58
-
59
- ### 3. Loader / API route errors
60
-
61
- - For slow pages, read the dev `Server-Timing` response header (`mw`/`loader`/`render` in ms) to see which phase dominates before reading code.
62
- - Read the route module's `loader` function or the matching API route handler.
63
- - Check that `loader` returns serializable data (no functions, no circular refs).
64
- - Check that API route handlers return `Response` objects and branch on `request.method` when using a default export.
65
- - Look for unhandled promise rejections or thrown errors.
66
- - Verify `LoaderArgs` destructuring matches what the framework provides: `{ request, params, context, signal, url, route }`.
67
-
68
- ### 4. Rendering issues
69
-
70
- - **Blank page**: Check if the route has `render: "spa"` (no SSR content expected) vs `"ssr"`.
71
- - **Hydration mismatch**: In dev, pracht surfaces a fixed-position red banner at the top of the page listing each mismatched component (via Preact's `options.__m` hook). Compare server-rendered HTML vs client component output. Common causes:
72
- - Date/time rendering differences
73
- - Browser-only APIs used during SSR (`window`, `document`, `localStorage`)
74
- - Conditional rendering based on client state
75
- - **Missing shell**: Referencing an unregistered shell name throws at manifest resolution — `Unknown shell "..." for route "...". Did you mean "..."? Registered shells: ...` — and shows up in the dev error overlay as soon as the server loads the manifest. Verify the shell is registered in `defineApp({ shells: { ... } })` and assigned to the route/group.
76
- - **404 page**: Route not matched — check manifest wiring (step 1). In `pracht dev`, unmatched navigations render a dev-only 404 page listing every registered route with its render mode; compare the requested path against that table. The route table is also printed on dev-server startup and available via `pracht inspect routes`. Apps that declare `defineApp({ notFound })` render their own 404 page instead (in dev and production alike), so the route table is not shown — check `pracht inspect routes` directly. A 404 on a URL you *do* expect to work usually means the loader threw `notFound()`, not that matching failed.
77
-
78
- ### 5. Middleware issues
79
-
80
- - Verify middleware is registered in `defineApp({ middleware: { ... } })`. An
81
- unregistered name (on a route, group, or `api.middleware`) throws at manifest
82
- resolution — `Unknown middleware "..." for route "...". Did you mean "..."? Registered middleware: ...`
83
- - Verify middleware is applied to the route/group: `middleware: ["name"]`.
84
- - Middleware is wrap-around: it must always return a `Response`, either by
85
- calling `await next()` (to continue down the chain) or short-circuiting.
86
- - Common bugs:
87
- - Forgetting `return next()` → `Middleware "..." did not return a Response`
88
- - Calling `next()` twice → `Middleware "..." called next() multiple times`
89
- - Mutating a non-object `context` → mutations don't propagate; always pass
90
- an object as the request context.
91
- - Middleware runs server-side only, wrapping loaders and API handlers.
92
-
93
- ### 6. API route issues
94
-
95
- - API routes live in `src/api/` and are auto-discovered (no manifest entry needed).
96
- - For machine-readable API inventory, run `pracht inspect api --json`.
97
- - File path maps to URL: `src/api/health.ts` → `/api/health`, `src/api/users/[id].ts` → `/api/users/:id`.
98
- - Each file exports named HTTP method handlers (`GET`, `POST`, etc.) or one default handler.
99
- - Missing method handler → 405 response when there is no default handler.
100
- - Default handlers receive the same route args and can branch on `request.method`.
101
- - Handlers must return `Response` objects.
102
-
103
- ### 7. Vite plugin / HMR issues
104
-
105
- - Check `vite.config.ts` — is `pracht()` plugin included?
106
- - Virtual modules: `virtual:pracht/client` (hydration), `virtual:pracht/server` (SSR), `virtual:pracht/islands-client` (islands hydration).
107
- - HMR: changes to `src/routes.ts` restart the dev server (`server.restart()`, not a browser-side full reload); changes to route/shell/middleware/API/server/islands files invalidate the server module.
108
- - If HMR seems broken, check that the file is in one of the watched directories (`src/routes/`, `src/shells/`, `src/middleware/`, `src/api/`, `src/server/`, `src/islands/`).
109
-
110
- ### 8. Build / deployment issues
111
-
112
- - `pracht build` runs client + server builds, then prerenders SSG/ISG routes.
113
- - `pracht preview` builds and serves the production output locally (Node runs `dist/server/server.js`, Cloudflare delegates to `wrangler dev`).
114
- - `pracht inspect build --json` reports the resolved adapter target plus client/CSS/JS manifests from the latest build output (requires a prior `pracht build`).
115
- - Check `dist/client/` for client assets and `dist/server/` for server bundle.
116
- - ISG manifest: `dist/server/isg-manifest.json`. On Cloudflare the build also copies it to `dist/client/_pracht/isg.json` for the worker runtime to read via the assets binding.
117
- - Adapter mismatch: ensure `pracht({ adapter: nodeAdapter() })` or `cloudflareAdapter()` matches deployment target.
118
-
119
- ## Key Files
120
-
121
- | File | Purpose |
122
- | --------------------- | ----------------------------------------------------- |
123
- | `src/routes.ts` | App manifest — all route/shell/middleware definitions |
124
- | `vite.config.ts` | Vite config with `pracht()` plugin |
125
- | `src/routes/*.tsx` | Route modules (loader, Component) |
126
- | `src/shells/*.tsx` | Shell layout components |
127
- | `src/middleware/*.ts` | Server-side middleware |
128
- | `src/api/*.ts` | API route handlers |
129
-
130
- ## Framework Internals
131
-
132
- - `handlePrachtRequest()` dispatches: API routes → middleware → loader → render → HTML assembly
133
- - Route state JSON: returned when `x-pracht-route-state-request` header is present (client-side navigation)
134
- - Hydration state: injected as `window.__PRACHT_STATE__` in the HTML
135
- - Client router: `initClientRouter()` intercepts link clicks and fetches route state JSON
136
-
137
- ## Rules
138
-
139
- 1. Always read the relevant source files before diagnosing.
140
- 2. Start with the most likely cause based on the symptom, not a full audit.
141
- 3. When you find the root cause, explain _why_ it breaks and fix it.
142
- 4. If wiring looks suspicious, run `pracht verify` first, then `pracht doctor` if you need the full-project view. If running the dev server or tests would help, do so (`pracht dev`, `pnpm test`, `pnpm e2e`).
143
- 5. After fixing, verify the fix works (run relevant test or check dev server output).
144
- 6. Never say "this should fix it." Verify and prove it.
53
+ - `pracht inspect routes --json` (or `curl http://localhost:5173/_pracht.json`)
54
+ for the resolved wiring; `pracht doctor` if a route may be missing, miswired,
55
+ or pointing at a missing module.
56
+ - Is the route in `src/routes.ts` with the right path? The manifest uses
57
+ relative paths like `"./routes/home.tsx"` — check for typos.
58
+ - Dynamic segments: `route("/users/:id", ...)` in the manifest, `[id].ts` in
59
+ filenames.
60
+ - If needed, grep the route path across the manifest and check
61
+ `matchAppRoute()`.
62
+
63
+ ### 2. Typed routes and links
64
+
65
+ - A `<Link route="...">`, `href("...")`, or route-object `useNavigate()` that
66
+ fails to typecheck usually means stale generated files: `pracht typegen
67
+ --check`.
68
+ - Confirm the route id exists in `pracht inspect routes --json`. Fallback ids
69
+ get renamed by path changes.
70
+ - `src/pracht.d.ts` carries the inferred params. `:id`, `*`, and `:path*` are
71
+ required; extra params should fail at typecheck time.
72
+ - Runtime `Unknown pracht route id "..."`: dev appends `Did you mean "..."?`
73
+ plus the registered ids (production tree-shakes that and throws bare). Check
74
+ the typo first, then that `pracht typegen` ran and the component renders
75
+ inside the pracht route tree.
76
+ - For unexpected URLs, reproduce with `href(routeId, options)` and compare
77
+ against the route's resolved path and params.
78
+
79
+ ### 3. Loader / API errors
80
+
81
+ - On slow pages, read `Server-Timing` before reading code.
82
+ - Loaders must return serializable data — no functions, no circular refs.
83
+ - API handlers must return `Response` objects, and a default export must branch
84
+ on `request.method`.
85
+ - Look for unhandled rejections or thrown errors.
86
+ - `LoaderArgs` destructuring must match what the framework provides:
87
+ `{ request, params, context, signal, url, route }`.
88
+
89
+ ### 4. Rendering
90
+
91
+ - **Blank page** — check whether the route is `render: "spa"` (no SSR content
92
+ expected) rather than `"ssr"`.
93
+ - **Hydration mismatch** — dev shows a fixed red banner listing each mismatched
94
+ component (via Preact's `options.__m` hook). Compare server HTML against
95
+ client output. Usual causes: date/time differences, browser-only APIs during
96
+ SSR (`window`, `document`, `localStorage`), conditional rendering on client
97
+ state — or two copies of `@pracht/core` in the SSR module graph. The tell for
98
+ that last one: in the server-rendered HTML of *every* page, `useLocation()`
99
+ returns `/`, `useParams()` returns `{}`, and `useRouteData()` returns
100
+ `undefined`, while the hydrated client is correct — provider and hooks hold
101
+ different `createContext()` objects. The plugin prevents it by keeping
102
+ `@pracht/*` in `ssr.noExternal`; listing a `@pracht/*` package in
103
+ `ssr.external` overrides that and brings the split back.
104
+ - **Missing shell** — an unregistered shell name throws at manifest resolution
105
+ (`Unknown shell "..." for route "...". Did you mean "..."? Registered shells:
106
+ ...`) and appears in the dev error overlay as soon as the manifest loads.
107
+ Check `defineApp({ shells })` and the route/group assignment.
108
+ - **404** — usually step 1, but a 404 on a URL you *do* expect means the loader
109
+ threw `notFound()`, not that matching failed. In `pracht dev`, unmatched
110
+ navigations render a dev-only 404 listing every registered route and its
111
+ render mode (also printed at dev-server startup, also in `pracht inspect
112
+ routes`). Apps declaring `defineApp({ notFound })` render their own 404 page
113
+ in dev and production alike, so that table is not shown — read `pracht
114
+ inspect routes` directly.
115
+
116
+ ### 5. Middleware
117
+
118
+ - It must be registered in `defineApp({ middleware })` and applied via
119
+ `middleware: ["name"]` on the route or group. An unregistered name (route,
120
+ group, or `api.middleware`) throws at manifest resolution: `Unknown
121
+ middleware "..." for route "...". Did you mean "..."? Registered middleware:
122
+ ...`
123
+ - Middleware is wrap-around and server-side only, wrapping loaders and API
124
+ handlers. It must always return a `Response`, either from `await next()` or
125
+ by short-circuiting. Common failures:
126
+
127
+ | Bug | Error |
128
+ | --- | ----- |
129
+ | Forgetting `return next()` | `Middleware "..." did not return a Response` |
130
+ | Calling `next()` twice | `Middleware "..." called next() multiple times` |
131
+ | Mutating a non-object `context` | Silent — mutations don't propagate; always pass an object |
132
+
133
+ ### 6. API routes
134
+
135
+ - They live in `src/api/`, auto-discovered, no manifest entry.
136
+ `pracht inspect api --json` for the inventory.
137
+ - Path maps to URL: `src/api/health.ts` → `/api/health`,
138
+ `src/api/users/[id].ts` → `/api/users/:id`.
139
+ - Each file exports named method handlers (`GET`, `POST`, …) or one default
140
+ handler that branches on `request.method`. A missing method handler is a 405
141
+ when there is no default.
142
+
143
+ ### 7. Vite plugin and HMR
144
+
145
+ - Is `pracht()` in `vite.config.ts`? Virtual modules are
146
+ `virtual:pracht/client` (hydration), `virtual:pracht/server` (SSR),
147
+ `virtual:pracht/islands-client` (islands hydration).
148
+ - HMR only watches `src/routes/`, `src/shells/`, `src/middleware/`,
149
+ `src/api/`, `src/server/`, `src/islands/`.
150
+ - What each change does: editing `src/routes.ts` restarts the dev server
151
+ (`server.restart()`, not a browser reload). Route, shell, and island
152
+ components use Preact Fast Refresh; route/shell edits and client-reachable
153
+ loader dependencies also re-fetch active route data, with rapid saves
154
+ coalesced so the newest result settles last and a failed latest refresh
155
+ falling back to a reload. Adding or removing a route `loader` or route/shell
156
+ `head` export reloads so generated client hints stay current, and editing a
157
+ route/shell exporting document `headers()` reloads because CSP and other
158
+ response headers cannot be patched. Compiled formats get refresh
159
+ instrumentation after their companion Vite plugin runs, but Markdown, MDX,
160
+ and configured additional formats reload conservatively because a transform
161
+ may synthesize `headers()` from metadata; default `.tsrx` preserves state
162
+ when its source is headerless. Everything else invalidates the server module.
163
+
164
+ ### 8. Build and deployment
165
+
166
+ - `pracht build` runs the client and server builds, then prerenders SSG/ISG
167
+ routes. On serverful adapters a failed path is warned about and skipped, but
168
+ the build fails if *every* attempted prerender returns non-200 — use the
169
+ reported underlying error to fix the shared loader/render dependency; partial
170
+ output stays valid. Static exports fail on any bad path.
171
+ - `pracht preview` builds and serves production output locally (Node runs
172
+ `dist/server/server.js`; Cloudflare delegates to `wrangler dev`).
173
+ - `pracht inspect build --json` reports the resolved adapter target plus the
174
+ client/CSS/JS manifests from the last build.
175
+ - Client assets land in `dist/client/`, the server bundle in `dist/server/`.
176
+ The ISG manifest is `dist/server/isg-manifest.json`; on Cloudflare the build
177
+ also copies it to `dist/client/_pracht/isg.json` for the worker to read via
178
+ the assets binding.
179
+ - Confirm the adapter in `pracht({ adapter: … })` matches the deployment
180
+ target.
181
+
182
+ ## Framework internals
183
+
184
+ - `handlePrachtRequest()` dispatches: API routes → middleware → loader →
185
+ render → HTML assembly.
186
+ - Route-state JSON is returned when the `x-pracht-route-state-request` header
187
+ is present (client-side navigation).
188
+ - Hydration state is injected as `window.__PRACHT_STATE__`.
189
+ - `initClientRouter()` intercepts link clicks and fetches that route state.
145
190
 
146
191
  $ARGUMENTS