@pikku/skills 0.12.58 → 0.12.60

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 (73) hide show
  1. package/dist/skills.gen.js +2 -2
  2. package/package.json +10 -7
  3. package/skills/pikku-a11y/SKILL.md +5 -3
  4. package/skills/pikku-addon/SKILL.md +8 -9
  5. package/skills/pikku-addon/references/addon-package-manifest.md +53 -0
  6. package/skills/pikku-agent/SKILL.md +16 -13
  7. package/skills/pikku-agent/references/runner-vercel.md +1 -1
  8. package/skills/pikku-architect/SKILL.md +7 -10
  9. package/skills/pikku-auth/SKILL.md +16 -20
  10. package/skills/pikku-auth/references/better-auth.md +74 -37
  11. package/skills/pikku-auth/references/sessions.md +8 -0
  12. package/skills/pikku-build/SKILL.md +36 -68
  13. package/skills/pikku-build/references/app.md +27 -828
  14. package/skills/pikku-build/references/feature.md +3 -5
  15. package/skills/pikku-build/references/phase-1-what-it-is.md +167 -0
  16. package/skills/pikku-build/references/phase-2-people-and-apps.md +133 -0
  17. package/skills/pikku-build/references/phase-3-plan.md +62 -0
  18. package/skills/pikku-build/references/phase-4-build.md +253 -0
  19. package/skills/pikku-build/references/phase-5-prove-and-ship.md +148 -0
  20. package/skills/pikku-build/references/platform.md +5 -6
  21. package/skills/pikku-build/references/quick.md +2 -2
  22. package/skills/pikku-build/references/ship.md +11 -5
  23. package/skills/pikku-changes/SKILL.md +13 -7
  24. package/skills/pikku-concepts/SKILL.md +26 -258
  25. package/skills/pikku-concepts/references/cli.md +63 -0
  26. package/skills/pikku-concepts/references/functions.md +117 -0
  27. package/skills/pikku-concepts/references/language.md +5 -5
  28. package/skills/pikku-concepts/references/packages.md +6 -4
  29. package/skills/pikku-concepts/references/testing.md +14 -0
  30. package/skills/pikku-convert-screen/SKILL.md +7 -1
  31. package/skills/pikku-deploy/SKILL.md +29 -30
  32. package/skills/pikku-deploy/references/ws.md +1 -1
  33. package/skills/pikku-emails/SKILL.md +7 -3
  34. package/skills/pikku-guide/SKILL.md +7 -10
  35. package/skills/pikku-i18n/SKILL.md +18 -19
  36. package/skills/pikku-i18n/references/messages.md +6 -8
  37. package/skills/pikku-knowledge/SKILL.md +42 -45
  38. package/skills/pikku-kysely/SKILL.md +50 -13
  39. package/skills/pikku-list-query/SKILL.md +27 -14
  40. package/skills/pikku-meta/SKILL.md +13 -16
  41. package/skills/pikku-meta/references/audit.md +1 -45
  42. package/skills/pikku-meta/references/versioning.md +1 -1
  43. package/skills/pikku-middleware/SKILL.md +23 -13
  44. package/skills/pikku-middleware/references/middleware-patterns.md +2 -2
  45. package/skills/pikku-n8n-import/SKILL.md +7 -8
  46. package/skills/pikku-permissions/SKILL.md +14 -8
  47. package/skills/pikku-react/SKILL.md +7 -6
  48. package/skills/pikku-realtime/SKILL.md +16 -11
  49. package/skills/pikku-report/SKILL.md +8 -10
  50. package/skills/pikku-scenario/SKILL.md +8 -12
  51. package/skills/pikku-scenario/references/steps.md +3 -4
  52. package/skills/pikku-scenario/references/virtual-users.md +1 -1
  53. package/skills/pikku-seo/SKILL.md +16 -8
  54. package/skills/pikku-service-backends/SKILL.md +26 -28
  55. package/skills/pikku-services/SKILL.md +8 -9
  56. package/skills/pikku-services/references/services.md +1 -1
  57. package/skills/pikku-software-archaeology/README.md +12 -1
  58. package/skills/pikku-software-archaeology/SKILL.md +9 -2
  59. package/skills/pikku-software-archaeology/references/pikku-mapping.md +1 -1
  60. package/skills/pikku-software-archaeology/references/sources/express.md +75 -0
  61. package/skills/pikku-software-archaeology/references/sources/laravel.md +77 -0
  62. package/skills/pikku-software-archaeology/references/sources/nestjs.md +73 -0
  63. package/skills/pikku-software-archaeology/references/sources/rails.md +72 -0
  64. package/skills/pikku-software-archaeology/references/tests-to-scenarios.md +72 -0
  65. package/skills/pikku-tailwind/SKILL.md +15 -16
  66. package/skills/pikku-theme/SKILL.md +15 -17
  67. package/skills/pikku-ui/SKILL.md +4 -3
  68. package/skills/pikku-webhook/SKILL.md +10 -11
  69. package/skills/pikku-wiring/SKILL.md +45 -47
  70. package/skills/pikku-wiring/references/channel.md +1 -1
  71. package/skills/pikku-wiring/references/scheduler.md +1 -1
  72. package/skills/pikku-wiring/references/trigger.md +24 -1
  73. package/skills/pikku-workflow/SKILL.md +7 -8
@@ -0,0 +1,63 @@
1
+ # The Pikku CLI commands
2
+
3
+ `pikku doc` is the API surface — the `#pikku/*` exports. It does **not** list
4
+ commands, so this table is where they exist. `pikku <command> --help` has the
5
+ flags; the "Read" column is the skill that teaches the thing, where one does.
6
+
7
+ **Generating**
8
+
9
+ | Command | What it does | Read |
10
+ | ------------------------------------------ | ---------------------------------------------------- | ----------------------------- |
11
+ | `all` | Everything: types, schemas, wirings, clients | this skill |
12
+ | `bootstrap` | Type files only (the setup phase) | this skill |
13
+ | `schemas` | JSON Schemas for function input/output types | this skill |
14
+ | `fetch` / `websocket` / `rpc` / `realtime` | One client each, when you do not want `all` | `pikku-wiring`, `pikku-react` |
15
+ | `react-query` / `tanstack-start` | React Query hooks; the TanStack Start `makeApi` shim | `pikku-react` |
16
+ | `queue-service` | The queue service wrapper | `pikku-wiring` |
17
+ | `openapi` | An OpenAPI spec from the HTTP routes | — |
18
+ | `nextjs` | Next.js backend and HTTP wrappers | `pikku-deploy` |
19
+ | `new` | Scaffold a function or wiring | `pikku-wiring` |
20
+ | `enable` | Turn a Pikku feature on | `pikku-build` |
21
+ | `import` | Import workflows from another system | `pikku-n8n-import` |
22
+
23
+ **Running**
24
+
25
+ | Command | What it does | Read |
26
+ | --------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------- |
27
+ | `dev` | Local dev server, all services wired, watch + HMR | `pikku-build` |
28
+ | `serve` | Bundled bun/node runner — no watch, no codegen | `pikku-deploy` |
29
+ | `watch` | Regenerate on file change, without a server | — |
30
+ | `scenario list\|run` | Scenarios as e2e tests and health checks | `pikku-scenario` |
31
+ | `virtual-user run` | A declared virtual user, model-driven, against a stage | `pikku-scenario`, virtual-user-run reference |
32
+ | `virtual-user list\|sync\|secret` | Who is declared; what an environment will provision; minting their credentials | `pikku-scenario`, virtual-user-run reference |
33
+ | `db` | Local development database | `pikku-kysely` |
34
+
35
+ **Inspecting and evolving**
36
+
37
+ | Command | What it does | Read |
38
+ | ---------------------- | ----------------------------------------------------------------------- | ---------------------------- |
39
+ | `doc` | The installed API surface | this skill |
40
+ | `meta` / `info` | What the project declares, machine- and human-readable | `pikku-meta` |
41
+ | `validate` | Every check that applies — app structure, an addon's published file set | `pikku-build`, `pikku-addon` |
42
+ | `versions` / `release` | Contract hashes, breaking-change detection, versioned releases | `pikku-meta` |
43
+ | `audit` / `update` | Advisories; which `@pikku/*` can move and what peers that needs | `pikku-meta` |
44
+ | `scopes` / `roles` | Declared authorization scopes; roles from `defineSystemRole` | `pikku-auth` |
45
+ | `knowledge` | The knowledge base — what this app is, in its users' language | `pikku-knowledge` |
46
+ | `emails` | Email template generation | `pikku-emails` |
47
+
48
+ **Shipping, and the CLI itself**
49
+
50
+ | Command | What it does | Read |
51
+ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
52
+ | `deploy` | Deploy to cloud infrastructure | `pikku-deploy` |
53
+ | `binary` | Compile an entrypoint to a native binary (`bun build --compile`) | — |
54
+ | `dist` | Copy what `tsc` cannot emit — `.gen.json` meta, hand-authored `.d.ts` — into the build output. Run it after `tsc`, as a package's build script | — |
55
+ | `login` / `logout` / `whoami` | The CLI's session against a pikku server | — |
56
+ | `skills` | Install these skills into an agent (Claude Code, opencode, pi) | — |
57
+
58
+ `-c/--config`, `--log-level`, `--json` and the filter flags are **global
59
+ options**, not commands — they attach to the generating commands above.
60
+
61
+ A dash means no skill covers it beyond this line. `--help` is then the whole of
62
+ it — which is a reason to read `--help` rather than to assume the command does
63
+ what its name suggests.
@@ -0,0 +1,117 @@
1
+ # Functions and schemas
2
+
3
+ ## Functions
4
+
5
+ Three main function types:
6
+
7
+ ```typescript
8
+ // Requires authentication — receives session in wire context.
9
+ // input/output are Zod schemas; the data + return types are inferred from them.
10
+ const updateTodo = pikkuFunc({
11
+ input: UpdateTodoInput,
12
+ output: TodoOutput,
13
+ func: async (services, data, wire) => {
14
+ const { session } = wire
15
+ return services.todoStore.update(data.id, data)
16
+ },
17
+ })
18
+
19
+ // No authentication required
20
+ const listTodos = pikkuSessionlessFunc({
21
+ input: ListTodosInput,
22
+ output: TodoListOutput,
23
+ func: async (services, data) => {
24
+ return { todos: services.todoStore.list(data.filters) }
25
+ },
26
+ })
27
+
28
+ // No input or output (for scheduled tasks, lifecycle hooks)
29
+ const cleanup = pikkuVoidFunc(async (services) => {
30
+ services.todoStore.cleanOldItems()
31
+ })
32
+ ```
33
+
34
+ Services can be destructured inline in the `func` signature (e.g. `async ({ logger, todoStore }, { title }) => ...`). Full config options:
35
+
36
+ ```typescript
37
+ pikkuFunc({
38
+ // Identity and documentation — prose, so it follows `metaLocale` in
39
+ // pikku.config.json (default `en`). The identifier does not; see
40
+ // "What Language You Write In".
41
+ title?: string, // Human-readable name
42
+ description?: string, // What the function does
43
+ version?: number, // Contract version (see pikku-meta)
44
+ override?: string, // Logical name override, so several exports share a versioned base
45
+ tags?: string[], // For grouping and middleware targeting
46
+
47
+ // Contract
48
+ input?: ZodSchema, // Input validation schema
49
+ output?: ZodSchema, // Output validation schema
50
+ errors?: Array<typeof PikkuError>, // Errors this function may throw
51
+
52
+ // Reachability
53
+ expose?: boolean, // Allow external RPC calls (see pikku-wiring)
54
+ remote?: boolean, // Allow remote RPC calls
55
+ mcp?: boolean, // Expose as MCP tool (see pikku-wiring)
56
+ readonly?: boolean, // Declares the function performs no writes
57
+ deploy?: 'serverless' | 'server' | 'auto',
58
+
59
+ // Authorization — see pikku-auth
60
+ auth?: boolean, // Override default auth requirement
61
+ scopes?: ScopeId[], // AND-ed, checked before permissions; session required
62
+ permissions?: PermissionGroup, // OR-ed pool
63
+ permissionsInBody?: boolean, // Last resort; needs allow.permissionsInBody in config
64
+ middleware?: PikkuMiddleware[], // See pikku-middleware
65
+
66
+ // Agent tooling — see pikku-agent
67
+ approvalRequired?: boolean,
68
+ approvalDescription?: (services, data) => Promise<string>,
69
+
70
+ // Workflow step behavior — see pikku-workflow
71
+ workflowQueued?: boolean, // Dispatch via queue instead of inline
72
+ workflowRetries?: number,
73
+ workflowTimeout?: string, // e.g. '30s', '5m'
74
+
75
+ audit?: boolean | { durability?: 'best-effort' | 'transactional' },
76
+
77
+ func: async (services, data, wire) => { ... },
78
+ })
79
+ ```
80
+
81
+ `scopes` is the one option `pikkuSessionlessFunc` does not accept, and the
82
+ omission is deliberate: scopes are AND-ed and fail closed, so an anonymous
83
+ caller holds none and satisfies none — a sessionless function with scopes would
84
+ reject every caller it exists to serve. Gate those with `permissions`, which
85
+ receive the optional session and may pass anonymous.
86
+
87
+ **Generics XOR `input`/`output` — never both.** A function's data and return
88
+ types come from _one_ source: either the `input`/`output` schemas (preferred —
89
+ they double as runtime validation and OpenAPI) or type generics
90
+ (`pikkuFunc<In, Out>({ ... })`). Passing both makes the two disagree and forces
91
+ `as any` casts. Do not annotate the `func` return type inline either — let the
92
+ `output` schema (or the generic) be the single source of truth for the type.
93
+
94
+ ```typescript
95
+ // Correct — schema-based (no generics, no inline return type)
96
+ pikkuFunc({ input: MyInput, output: MyOutput, func: async (s, d) => { ... } })
97
+ // Correct — generic-based (no input/output)
98
+ pikkuFunc<MyIn, MyOut>({ func: async (s, d) => { ... } })
99
+ // WRONG — mixing the two
100
+ pikkuFunc<MyIn, MyOut>({ input: MyInput as any, func: async (s, d) => { ... } })
101
+ ```
102
+
103
+ ## Schemas (Validation)
104
+
105
+ Pikku uses Standard Schema — works with Zod, Valibot, ArkType:
106
+
107
+ ```typescript
108
+ import { z } from 'zod'
109
+
110
+ const CreateTodoInputSchema = z.object({
111
+ title: z.string().min(1).max(200),
112
+ priority: z.enum(['low', 'medium', 'high']).optional(),
113
+ tags: z.array(z.string()).optional(),
114
+ })
115
+ ```
116
+
117
+ Schemas serve triple duty: runtime validation, TypeScript types, and OpenAPI documentation.
@@ -31,10 +31,10 @@ identifier is a migration, not an edit.
31
31
  { "metaLocale": "de" }
32
32
  ```
33
33
 
34
- Meta is the one part of a project the **Pikku Console** renders back to a human.
35
- A team reviewing their own functions, features and scenario reports in the
36
- Console is reading meta and nothing else, so a team whose working language is
37
- German should be able to read their Console in German. That is the entire reason
34
+ Meta is the one part of a project that is read back to a human. A team
35
+ reviewing their own functions, features and scenario reports is reading meta
36
+ and nothing else, so a team whose working language is German should be able to
37
+ read it in German. That is the entire reason
38
38
  the field exists.
39
39
 
40
40
  Read it before you author meta, and write descriptions, titles and templates in
@@ -79,7 +79,7 @@ settings, each on its own axis:
79
79
  // apps/app/src/i18n/active.json — what a first-time visitor opens in
80
80
  { "defaultLocale": "de" }
81
81
 
82
- // pikku.config.json — the language the team reads their Console in
82
+ // pikku.config.json — the language the team reads their meta in
83
83
  { "metaLocale": "de" }
84
84
  ```
85
85
 
@@ -4,14 +4,16 @@
4
4
 
5
5
  | Package | Use Case |
6
6
  | ----------------------------- | ------------------------------------- |
7
- | `@pikku/express-server` | Express standalone server |
7
+ | `@pikku/express` | Express standalone server |
8
8
  | `@pikku/express-middleware` | Express as middleware in existing app |
9
- | `@pikku/fastify-server` | Fastify standalone |
9
+ | `@pikku/fastify` | Fastify standalone |
10
10
  | `@pikku/fastify-plugin` | Fastify plugin |
11
11
  | `@pikku/next` | Next.js API routes |
12
- | `@pikku/aws-lambda` | AWS Lambda handlers |
12
+ | `@pikku/lambda` | AWS Lambda handlers |
13
13
  | `@pikku/cloudflare` | Cloudflare Workers |
14
- | `@pikku/uws-server` | uWebSockets.js (high perf) |
14
+ | `@pikku/uws` | uWebSockets.js (high perf) |
15
+ | `@pikku/ws` | `ws` WebSocket server |
16
+ | `@pikku/azure-functions` | Azure Functions |
15
17
  | `@pikku/modelcontextprotocol` | MCP server |
16
18
 
17
19
  ## Service Packages
@@ -0,0 +1,14 @@
1
+ # Testing
2
+
3
+ Functions are easily testable because they're pure:
4
+
5
+ ```typescript
6
+ const mockServices = {
7
+ logger: new MockLogger(),
8
+ todoStore: new MockTodoStore(),
9
+ }
10
+
11
+ // Call function directly — no HTTP, no framework
12
+ const result = await listTodos.func(mockServices, { userId: 'test' })
13
+ expect(result.todos).toHaveLength(3)
14
+ ```
@@ -1,6 +1,12 @@
1
1
  ---
2
2
  name: pikku-convert-screen
3
- description: Use when an old screen, page or feature (from an old console, another repo, screenshots, or a description) has to be rebuilt in the current app. Extracts what it does as plain business logic, with no layout or code detail, then designs it fresh in the current design system. TRIGGER on "convert this screen", "port the old console page", "we had this before, bring it back", "redesign X from the old console". DO NOT TRIGGER for whole-repo reverse engineering (use pikku-software-archaeology) or for restyling a screen that already exists in the app.
3
+ description: >-
4
+ Rebuild an old screen, page or feature (from an old console, another repo, screenshots or a
5
+ description) in the current app: extract what it does as plain business logic, no layout or code
6
+ detail, then design it fresh in the current design system. TRIGGER on "convert this screen", "port
7
+ the old console page", "we had this before, bring it back", "redesign X from the old console". DO
8
+ NOT TRIGGER for whole-repo reverse engineering (use pikku-software-archaeology) or restyling a
9
+ screen already in the app.
4
10
  installGroups: [core]
5
11
  ---
6
12
 
@@ -1,14 +1,13 @@
1
1
  ---
2
2
  name: pikku-deploy
3
3
  description: >-
4
- Use when deploying a Pikku app to a runtime — Express, Fastify, uWebSockets.js, the `ws` library,
5
- Next.js, AWS Lambda, Cloudflare Workers or Azure Functions. Covers the bootstrap every runtime
6
- shares, choosing between them, and the behaviour that differs: which accept
7
- `RunHTTPWiringOptions`, how each one runs scheduled tasks, and where CORS and health checks live.
8
- TRIGGER when: writing or debugging `start.ts` / a worker entry / a Lambda handler, code imports
9
- `@pikku/express`, `@pikku/fastify`, `@pikku/uws`, `@pikku/ws`, `@pikku/next`, `@pikku/lambda`,
10
- `@pikku/cloudflare` or `@pikku/azure-functions`, or the user asks how to serve, host or deploy a
11
- Pikku app. DO NOT TRIGGER when: defining functions or wirings with no runtime-specific code.
4
+ Deploying a Pikku app to a runtime: Express, Fastify, uWebSockets.js, `ws`, Next.js, AWS Lambda,
5
+ Cloudflare Workers, Azure Functions. Covers the shared bootstrap, choosing a runtime, which accept
6
+ RunHTTPWiringOptions, scheduled tasks per runtime, CORS and health checks. TRIGGER when: writing
7
+ or debugging `start.ts`, a worker entry or Lambda handler, importing
8
+ @pikku/express|fastify|uws|ws|next|lambda|cloudflare|azure-functions, or asked how to serve, host
9
+ or deploy a Pikku app. DO NOT TRIGGER when: defining functions or wirings with no runtime-specific
10
+ code.
12
11
  installGroups: [core]
13
12
  ---
14
13
 
@@ -35,23 +34,23 @@ Two families, and the difference decides how you write the entry file.
35
34
  **Long-running servers** own a process. Services are built once at startup and
36
35
  live in module scope for the life of the server.
37
36
 
38
- | Runtime | Package | Reach for it when |
39
- | --- | --- | --- |
40
- | Express | `@pikku/express` | An existing Express app, or you want static assets and upload handling |
41
- | Fastify | `@pikku/fastify` | An existing Fastify app, or you want its stricter defaults |
42
- | uWebSockets.js | `@pikku/uws` | Highest throughput, HTTP and WebSocket on one port |
43
- | ws | `@pikku/ws` | WebSocket only, attached to an `http.Server` you own |
37
+ | Runtime | Package | Reach for it when |
38
+ | -------------- | ---------------- | ---------------------------------------------------------------------- |
39
+ | Express | `@pikku/express` | An existing Express app, or you want static assets and upload handling |
40
+ | Fastify | `@pikku/fastify` | An existing Fastify app, or you want its stricter defaults |
41
+ | uWebSockets.js | `@pikku/uws` | Highest throughput, HTTP and WebSocket on one port |
42
+ | ws | `@pikku/ws` | WebSocket only, attached to an `http.Server` you own |
44
43
 
45
44
  **Per-invocation runtimes** are handed a request and torn down. Services are
46
45
  cached in module scope across warm invocations, and the deploy codegen writes
47
46
  that caching for you.
48
47
 
49
- | Runtime | Package | Reach for it when |
50
- | --- | --- | --- |
51
- | AWS Lambda | `@pikku/lambda` | API Gateway, EventBridge, SQS |
52
- | Cloudflare Workers | `@pikku/cloudflare` | Edge, Durable Objects for channels |
53
- | Azure Functions | `@pikku/azure-functions` | Azure hosting — note channels are not implemented |
54
- | Next.js | `@pikku/next` | Pikku behind Next routes, or RPC from Server Components |
48
+ | Runtime | Package | Reach for it when |
49
+ | ------------------ | ------------------------ | ------------------------------------------------------- |
50
+ | AWS Lambda | `@pikku/lambda` | API Gateway, EventBridge, SQS |
51
+ | Cloudflare Workers | `@pikku/cloudflare` | Edge, Durable Objects for channels |
52
+ | Azure Functions | `@pikku/azure-functions` | Azure hosting — note channels are not implemented |
53
+ | Next.js | `@pikku/next` | Pikku behind Next routes, or RPC from Server Components |
55
54
 
56
55
  Then read the reference for the one you picked: `references/express.md`,
57
56
  `references/fastify.md`, `references/uws.md`, `references/ws.md`,
@@ -84,16 +83,16 @@ hand-written handlers are for the cases the deploy codegen does not cover.
84
83
  `maxBodySize`, `respondWith404`, `coerceDataFromSchema` and `bubbleErrors` reach
85
84
  the request only on the runtimes that thread them through.
86
85
 
87
- | Runtime | Accepts options | Where an oversized body is actually stopped |
88
- | --- | --- | --- |
89
- | Express | `init(httpOptions)` | The `express.json` parser limit, fed by `maxBodySize` |
90
- | Fastify | `init(httpOptions)` | Fastify's own `bodyLimit`, set from `maxBodySize` |
91
- | uWS | HTTP handler only | The handler counts bytes itself and answers `413` |
92
- | ws | Yes, on the handler | `maxPayload` on the `WebSocketServer` |
93
- | Next.js | Only via your own `PikkuNextJS` handler | Next's own limits |
94
- | Lambda | **No** | API Gateway's payload limit |
95
- | Cloudflare | Partially — `runFetch(request, hibernation, options)` | The platform's limit |
96
- | Azure | **No** | Azure's request limits |
86
+ | Runtime | Accepts options | Where an oversized body is actually stopped |
87
+ | ---------- | ----------------------------------------------------- | ----------------------------------------------------- |
88
+ | Express | `init(httpOptions)` | The `express.json` parser limit, fed by `maxBodySize` |
89
+ | Fastify | `init(httpOptions)` | Fastify's own `bodyLimit`, set from `maxBodySize` |
90
+ | uWS | HTTP handler only | The handler counts bytes itself and answers `413` |
91
+ | ws | Yes, on the handler | `maxPayload` on the `WebSocketServer` |
92
+ | Next.js | Only via your own `PikkuNextJS` handler | Next's own limits |
93
+ | Lambda | **No** | API Gateway's payload limit |
94
+ | Cloudflare | Partially — `runFetch(request, hibernation, options)` | The platform's limit |
95
+ | Azure | **No** | Azure's request limits |
97
96
 
98
97
  On Fastify, leaving `maxBodySize` unset keeps Fastify's stricter 1MB default
99
98
  rather than loosening it to Pikku's 10MB fallback. On uWS the chunks are dropped
@@ -16,7 +16,7 @@ the upgrade and message plumbing to them.
16
16
 
17
17
  ```typescript
18
18
  import { DEFAULT_WS_MAX_PAYLOAD, pikkuWebsocketHandler } from '@pikku/ws'
19
- import { stopSingletonServices } from '@pikku/core'
19
+ import { stopSingletonServices } from '@pikku/core/utils'
20
20
  import { Server } from 'http'
21
21
  import { WebSocketServer } from 'ws'
22
22
 
@@ -1,9 +1,13 @@
1
1
  ---
2
2
  name: pikku-emails
3
3
  description: >-
4
- Use when working with Pikku's file-based email templates: authoring html, subject and text templates, locales, partials and theme, running `pikku emails generate`, and rendering and sending them through an EmailService.
5
- TRIGGER when: code uses renderEmailTemplate, EmailTemplateName, EmailService, SendTemplateEmailInput or LocalEmailService, or imports from .pikku/email/pikku-emails.gen; the project has an emails/ directory (templates/, locales/, partials/, theme.json) or emailTemplatesDir in pikku.config.json; or the user asks to add, edit or translate a transactional email (verification, password reset, invitation, receipt) or wire email sending.
6
- DO NOT TRIGGER when: the task is i18n for the app UI (use pikku-i18n) or sign-in flows in general (use pikku-auth).
4
+ Pikku's file-based email templates: html/subject/text templates, locales, partials, theme, `pikku
5
+ emails generate`, rendering and sending via EmailService. TRIGGER when: code uses
6
+ renderEmailTemplate, EmailTemplateName, EmailService, SendTemplateEmailInput, LocalEmailService or
7
+ imports .pikku/email/pikku-emails.gen; the project has an emails/ directory or emailTemplatesDir
8
+ in pikku.config.json; or the user adds, edits or translates a transactional email (verification,
9
+ reset, invitation, receipt). DO NOT TRIGGER for app UI i18n (use pikku-i18n) or sign-in flows in
10
+ general (use pikku-auth).
7
11
  installGroups: [core]
8
12
  ---
9
13
 
@@ -1,16 +1,13 @@
1
1
  ---
2
2
  name: pikku-guide
3
3
  description: >-
4
- Use when writing, rewriting or regenerating a Pikku project's end-user guide, built from the
5
- scenario suite with `pikku scenario guide`. Pages are hand-written markdown, one section per
6
- task, each followed by a `pikku:guide` HTML-comment marker (feature and scenario attributes) that
7
- pulls in the screenshot and recording that scenario filed. Covers planning pages from the suite,
8
- writing task prose in the app's language, per-section markers, the capture step, seed data that
9
- appears on camera, `.guide.lock` staleness, `document: false`, and the traps that make a guide
10
- come out empty, refused, or as a wall of videos. TRIGGER when: user asks for a user guide, help
11
- pages, docs with screenshots, "document the app", or complains that the /docs pages are bad,
12
- thin, or all videos. DO NOT TRIGGER when: user asks about API reference docs, README files, the
13
- Pikku framework's own documentation site, or writing the scenarios themselves (use pikku-scenario).
4
+ Write, rewrite or regenerate a project's end-user guide from the scenario suite (`pikku scenario
5
+ guide`): hand-written markdown with `pikku:guide` markers that pull in scenario screenshots and
6
+ recordings. Covers planning, markers, capture, seed data, `.guide.lock`, `document: false`, and
7
+ traps that leave a guide empty, refused or all videos. TRIGGER when: asked for a user guide, help
8
+ pages, docs with screenshots, "document the app", or the /docs pages are bad, thin or all videos.
9
+ DO NOT TRIGGER for API reference, READMEs, the Pikku framework's own docs, or writing scenarios
10
+ (use pikku-scenario).
14
11
  installGroups: [core]
15
12
  ---
16
13
 
@@ -1,13 +1,12 @@
1
1
  ---
2
2
  name: pikku-i18n
3
3
  description: >-
4
- Use when writing user-facing text in a Pikku frontend, or making one speak another language.
5
- Covers Paraglide JS message functions compiled from per-locale messages JSON files, adding a second
6
- language, generated enum-label maps with @pikku/paraglide, and right-to-left support (document direction, flow-relative
7
- styles) for Arabic, Hebrew, Farsi and Urdu. TRIGGER when: scaffolding or editing a frontend and writing display
8
- text, asked to make copy translatable, adding a language, labelling an enum/status/role value,
9
- or asked to support RTL / mirror the layout. DO NOT TRIGGER for backend functions, error
10
- messages thrown from functions, or log output — none of those are display strings.
4
+ Writing user-facing text in a Pikku frontend or making it speak another language: Paraglide JS
5
+ message functions from per-locale JSON, adding a language, generated enum-label maps
6
+ (@pikku/paraglide), and RTL support (Arabic, Hebrew, Farsi, Urdu). TRIGGER when: writing display
7
+ text in a frontend, making copy translatable, adding a language, labelling an enum/status/role
8
+ value, or supporting RTL. DO NOT TRIGGER for backend functions, error messages thrown from
9
+ functions, or log output.
11
10
  installGroups: [client]
12
11
  ---
13
12
 
@@ -22,11 +21,11 @@ type-checks them, so an i18n mistake blocks the build rather than the release.
22
21
 
23
22
  ## Pick the reference
24
23
 
25
- | You are… | Read |
26
- | --- | --- |
27
- | Writing copy, wiring Paraglide, or adding a language | `references/messages.md` |
28
- | Labelling an enum, status, kind or role value | `references/enum-labels.md` |
29
- | Adding Arabic (or Hebrew, Farsi, Urdu), or writing layout styles | `references/rtl.md` |
24
+ | You are… | Read |
25
+ | ---------------------------------------------------------------- | --------------------------- |
26
+ | Writing copy, wiring Paraglide, or adding a language | `references/messages.md` |
27
+ | Labelling an enum, status, kind or role value | `references/enum-labels.md` |
28
+ | Adding Arabic (or Hebrew, Farsi, Urdu), or writing layout styles | `references/rtl.md` |
30
29
 
31
30
  ## Three axes, and a brief usually means only one
32
31
 
@@ -34,14 +33,14 @@ type-checks them, so an i18n mistake blocks the build rather than the release.
34
33
  codebase. Reading it as one about the codebase is the most expensive mistake
35
34
  available here.
36
35
 
37
- | Axis | What it covers | What sets it |
38
- | --- | --- | --- |
39
- | **Identifiers** | Function, component, type and file names; tables and columns | Nothing — always English |
40
- | **Meta** | `description` / `name` / `title` authored in code, rendered by the console | `metaLocale` in `pikku.config.json` |
41
- | **Product UI** | Every string the app shows a user | `messages/<locale>.json` + `defaultLocale` |
36
+ | Axis | What it covers | What sets it |
37
+ | --------------- | ------------------------------------------------------------------------ | ------------------------------------------ |
38
+ | **Identifiers** | Function, component, type and file names; tables and columns | Nothing — always English |
39
+ | **Meta** | `description` / `name` / `title` authored in code, read back to the team | `metaLocale` in `pikku.config.json` |
40
+ | **Product UI** | Every string the app shows a user | `messages/<locale>.json` + `defaultLocale` |
42
41
 
43
42
  `baseLocale` stays `en` whatever language the product speaks — it names the
44
- message *source* catalogue every other locale is derived from, not the language
43
+ message _source_ catalogue every other locale is derived from, not the language
45
44
  the app is in. Set `defaultLocale` instead.
46
45
 
47
46
  ## Direction is one setting, not per-component work
@@ -59,7 +58,7 @@ is what makes an RTL language just another locale file.
59
58
  `m['enum__' + x]()`, no key-string resolver. A computed key cannot be
60
59
  type-checked or tree-shaken, so a renamed message degrades to silent runtime
61
60
  text. Where the key is genuinely dynamic, map the discriminant to a message
62
- *function* — the map is checked, a string is not.
61
+ _function_ — the map is checked, a string is not.
63
62
  - **Do not `asI18n()` a hardcoded English string.** `asI18n` exists to pass
64
63
  opaque server data (a name, a slug, an id) through the i18n gate. An enum value
65
64
  goes through its generated label map.
@@ -29,11 +29,11 @@ is a statement about **one** of three separate things, and reading it as a
29
29
  statement about the codebase is the single most expensive mistake available in
30
30
  this skill. Three axes:
31
31
 
32
- | Axis | What it covers | What sets it |
33
- | --------------- | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
34
- | **Identifiers** | Function, component, type and file names; database tables and columns | Nothing — always English, no setting |
35
- | **Meta** | `description` / `name` / `title` / `template` authored inside the code, which the Pikku Console renders | `metaLocale` in `pikku.config.json`, default `en` |
36
- | **Product UI** | Every string the app shows a user | `messages/<locale>.json` + `defaultLocale` — **this axis only** |
32
+ | Axis | What it covers | What sets it |
33
+ | --------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
34
+ | **Identifiers** | Function, component, type and file names; database tables and columns | Nothing — always English, no setting |
35
+ | **Meta** | `description` / `name` / `title` / `template` authored inside the code, read back to the team | `metaLocale` in `pikku.config.json`, default `en` |
36
+ | **Product UI** | Every string the app shows a user | `messages/<locale>.json` + `defaultLocale` — **this axis only** |
37
37
 
38
38
  A non-English product moves the third row and nothing else.
39
39
 
@@ -63,7 +63,7 @@ So a German medical portal is **three** settings, not one:
63
63
  // apps/app/src/i18n/active.json — what a visitor opens in
64
64
  { "defaultLocale": "de" }
65
65
 
66
- // pikku.config.json — the language the team reads their Console in
66
+ // pikku.config.json — the language the team reads their meta in
67
67
  { "metaLocale": "de" }
68
68
  ```
69
69
 
@@ -221,8 +221,6 @@ The wrapper alternative — a module that walks the namespace and pipes each mes
221
221
  - Don't edit or commit anything under `src/paraglide/` — it's regenerated; change `messages/*.json` instead.
222
222
  - **Don't wrap `m`.** No re-export module, no branding layer, no resolver. Components import `m` from `../paraglide/messages.js` and call it. `@pikku/react`'s `I18nString` is declared as `string & { readonly __brand: 'LocalizedString' }` — deliberately identical to Paraglide's own `LocalizedString` — so `m.some__key()` satisfies the template's `I18nNode` gate natively. A wrapper adds nothing and costs per-message tree-shaking.
223
223
 
224
- `packages/console` is the one place in this repo that still wraps it, in `src/i18n/messages.ts`, to keep the debug mask (`█`) it carried over from i18next. That wrapper is a leftover, not a pattern — the generated-locale approach above is how a new app gets the same masking without touching every export. Don't copy it.
225
-
226
224
  The `mKey`/`mList` runtime resolvers that used to live beside it are **gone**, and must not come back. `mList` resolved indexed `prefix.0` keys that no longer exist; `mKey` took a computed string, which is exactly the type safety Paraglide exists to provide. Where a key really is dynamic, map the discriminant to a message _function_ and call it — the map is type-checked, a string is not.
227
225
 
228
226
  - Don't re-resolve messages by string key or re-implement `{param}` interpolation. A key-string resolver turns a missing key back into silent runtime text, surrendering the type safety that is the entire reason to use Paraglide.