@percepta/create 4.1.7 → 4.1.8

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 (54) hide show
  1. package/dist/{git-ops-BD7JNnal.js → git-ops-BNpQnEc1.js} +1 -1
  2. package/dist/{git-ops-BD7JNnal.js.map → git-ops-BNpQnEc1.js.map} +1 -1
  3. package/dist/{github-D3YOEl91.js → github-BOp8VQCY.js} +1 -1
  4. package/dist/{github-D3YOEl91.js.map → github-BOp8VQCY.js.map} +1 -1
  5. package/dist/index.js +107 -15
  6. package/dist/index.js.map +1 -1
  7. package/dist/{init-BD3EyyLO.js → init-CsuO_mu2.js} +2 -4
  8. package/dist/{init-BD3EyyLO.js.map → init-CsuO_mu2.js.map} +1 -1
  9. package/dist/{register-app-DZg-Pmtd.js → register-app-mNc1oYVK.js} +3 -5
  10. package/dist/{register-app-DZg-Pmtd.js.map → register-app-mNc1oYVK.js.map} +1 -1
  11. package/dist/{register-os-blueprint-Cgq1rXzQ.js → register-os-blueprint-Gdyn0pN1.js} +3 -4
  12. package/dist/{register-os-blueprint-Cgq1rXzQ.js.map → register-os-blueprint-Gdyn0pN1.js.map} +1 -1
  13. package/dist/{status-K6raTwwu.js → status-BrK9v1yb.js} +3 -3
  14. package/dist/{status-K6raTwwu.js.map → status-BrK9v1yb.js.map} +1 -1
  15. package/dist/{sync-Bi958-2W.js → sync-DC5DhIBT.js} +3 -3
  16. package/dist/{sync-Bi958-2W.js.map → sync-DC5DhIBT.js.map} +1 -1
  17. package/dist/{upstream-CAraZeSS.js → upstream-PNL6DGtl.js} +3 -3
  18. package/dist/{upstream-CAraZeSS.js.map → upstream-PNL6DGtl.js.map} +1 -1
  19. package/package.json +3 -3
  20. package/template-versions.json +2 -2
  21. package/templates/monorepo/auth/src/drizzle/migrations/meta/0000_snapshot.json +547 -0
  22. package/templates/monorepo/package.json.template +6 -6
  23. package/templates/monorepo/pnpm-workspace.yaml +1 -1
  24. package/templates/webapp/AGENTS.md +38 -16
  25. package/templates/webapp/README.md +56 -58
  26. package/templates/webapp/agent-skills/access-control.md +10 -9
  27. package/templates/webapp/agent-skills/database.md +10 -4
  28. package/templates/webapp/agent-skills/inngest.md +10 -8
  29. package/templates/webapp/agent-skills/langfuse.md +7 -5
  30. package/templates/webapp/agent-skills/oneshot.md +15 -13
  31. package/templates/webapp/package.json.template +5 -5
  32. package/templates/webapp/playwright.config.ts +1 -2
  33. package/templates/webapp/src/app/(app)/page.tsx +5 -3
  34. package/templates/webapp/src/app/(auth)/layout.tsx +2 -2
  35. package/templates/webapp/src/app/(settings)/settings/page.tsx +20 -21
  36. package/templates/webapp/src/components/FaroProvider.tsx +1 -2
  37. package/templates/webapp/src/components/Header.tsx +2 -8
  38. package/templates/webapp/src/components/form/FormItem.tsx +1 -1
  39. package/templates/webapp/src/drizzle/db.ts +3 -1
  40. package/templates/webapp/src/drizzle/schema/utils/jsonbFromZod.ts +1 -1
  41. package/templates/webapp/src/instrumentation.ts +3 -6
  42. package/templates/webapp/src/lib/auth-client.ts +3 -2
  43. package/templates/webapp/src/lib/trpc.ts +1 -1
  44. package/templates/webapp/src/server/trpc.ts +1 -1
  45. package/templates/webapp/src/services/DatabaseService.ts +1 -1
  46. package/templates/webapp/src/services/access/AppAccessControl.ts +1 -3
  47. package/templates/webapp/src/services/inngest/AppWorkflowService.ts +1 -1
  48. package/templates/webapp/src/styles/globals.css +13 -2
  49. package/dist/manifest-By1SgOjC.js +0 -59
  50. package/dist/manifest-By1SgOjC.js.map +0 -1
  51. package/dist/template-versions-CEIP9vhl.js +0 -35
  52. package/dist/template-versions-CEIP9vhl.js.map +0 -1
  53. package/dist/validate-dssldJAj.js +0 -14
  54. package/dist/validate-dssldJAj.js.map +0 -1
@@ -0,0 +1,547 @@
1
+ {
2
+ "id": "b5bbeb48-5edf-4779-b6ee-d2839eb302fd",
3
+ "prevId": "00000000-0000-0000-0000-000000000000",
4
+ "version": "7",
5
+ "dialect": "postgresql",
6
+ "tables": {
7
+ "public.group_members": {
8
+ "name": "group_members",
9
+ "schema": "",
10
+ "columns": {
11
+ "group_id": {
12
+ "name": "group_id",
13
+ "type": "uuid",
14
+ "primaryKey": false,
15
+ "notNull": true
16
+ },
17
+ "user_id": {
18
+ "name": "user_id",
19
+ "type": "uuid",
20
+ "primaryKey": false,
21
+ "notNull": true
22
+ },
23
+ "created_at": {
24
+ "name": "created_at",
25
+ "type": "timestamp",
26
+ "primaryKey": false,
27
+ "notNull": true,
28
+ "default": "now()"
29
+ }
30
+ },
31
+ "indexes": {
32
+ "group_members_user_id_index": {
33
+ "name": "group_members_user_id_index",
34
+ "columns": [
35
+ {
36
+ "expression": "user_id",
37
+ "isExpression": false,
38
+ "asc": true,
39
+ "nulls": "last"
40
+ }
41
+ ],
42
+ "isUnique": false,
43
+ "concurrently": false,
44
+ "method": "btree",
45
+ "with": {}
46
+ }
47
+ },
48
+ "foreignKeys": {
49
+ "group_members_group_id_groups_id_fk": {
50
+ "name": "group_members_group_id_groups_id_fk",
51
+ "tableFrom": "group_members",
52
+ "tableTo": "groups",
53
+ "columnsFrom": ["group_id"],
54
+ "columnsTo": ["id"],
55
+ "onDelete": "cascade",
56
+ "onUpdate": "no action"
57
+ },
58
+ "group_members_user_id_users_id_fk": {
59
+ "name": "group_members_user_id_users_id_fk",
60
+ "tableFrom": "group_members",
61
+ "tableTo": "users",
62
+ "columnsFrom": ["user_id"],
63
+ "columnsTo": ["id"],
64
+ "onDelete": "cascade",
65
+ "onUpdate": "no action"
66
+ }
67
+ },
68
+ "compositePrimaryKeys": {
69
+ "group_members_pkey": {
70
+ "name": "group_members_pkey",
71
+ "columns": ["group_id", "user_id"]
72
+ }
73
+ },
74
+ "uniqueConstraints": {},
75
+ "policies": {},
76
+ "checkConstraints": {},
77
+ "isRLSEnabled": false
78
+ },
79
+ "public.groups": {
80
+ "name": "groups",
81
+ "schema": "",
82
+ "columns": {
83
+ "id": {
84
+ "name": "id",
85
+ "type": "uuid",
86
+ "primaryKey": true,
87
+ "notNull": true
88
+ },
89
+ "external_id": {
90
+ "name": "external_id",
91
+ "type": "text",
92
+ "primaryKey": false,
93
+ "notNull": true
94
+ },
95
+ "name": {
96
+ "name": "name",
97
+ "type": "text",
98
+ "primaryKey": false,
99
+ "notNull": true
100
+ },
101
+ "source": {
102
+ "name": "source",
103
+ "type": "text",
104
+ "primaryKey": false,
105
+ "notNull": true
106
+ },
107
+ "deleted_at": {
108
+ "name": "deleted_at",
109
+ "type": "timestamp",
110
+ "primaryKey": false,
111
+ "notNull": false
112
+ },
113
+ "created_at": {
114
+ "name": "created_at",
115
+ "type": "timestamp",
116
+ "primaryKey": false,
117
+ "notNull": true,
118
+ "default": "now()"
119
+ },
120
+ "updated_at": {
121
+ "name": "updated_at",
122
+ "type": "timestamp",
123
+ "primaryKey": false,
124
+ "notNull": true,
125
+ "default": "now()"
126
+ }
127
+ },
128
+ "indexes": {
129
+ "groups_live_external_id_index": {
130
+ "name": "groups_live_external_id_index",
131
+ "columns": [
132
+ {
133
+ "expression": "external_id",
134
+ "isExpression": false,
135
+ "asc": true,
136
+ "nulls": "last"
137
+ }
138
+ ],
139
+ "isUnique": true,
140
+ "where": "\"groups\".\"deleted_at\" IS NULL",
141
+ "concurrently": false,
142
+ "method": "btree",
143
+ "with": {}
144
+ },
145
+ "groups_source_index": {
146
+ "name": "groups_source_index",
147
+ "columns": [
148
+ {
149
+ "expression": "source",
150
+ "isExpression": false,
151
+ "asc": true,
152
+ "nulls": "last"
153
+ }
154
+ ],
155
+ "isUnique": false,
156
+ "concurrently": false,
157
+ "method": "btree",
158
+ "with": {}
159
+ }
160
+ },
161
+ "foreignKeys": {},
162
+ "compositePrimaryKeys": {},
163
+ "uniqueConstraints": {},
164
+ "policies": {},
165
+ "checkConstraints": {},
166
+ "isRLSEnabled": false
167
+ },
168
+ "public.account": {
169
+ "name": "account",
170
+ "schema": "",
171
+ "columns": {
172
+ "id": {
173
+ "name": "id",
174
+ "type": "text",
175
+ "primaryKey": true,
176
+ "notNull": true
177
+ },
178
+ "user_id": {
179
+ "name": "user_id",
180
+ "type": "uuid",
181
+ "primaryKey": false,
182
+ "notNull": true
183
+ },
184
+ "account_id": {
185
+ "name": "account_id",
186
+ "type": "text",
187
+ "primaryKey": false,
188
+ "notNull": true
189
+ },
190
+ "provider_id": {
191
+ "name": "provider_id",
192
+ "type": "text",
193
+ "primaryKey": false,
194
+ "notNull": true
195
+ },
196
+ "access_token": {
197
+ "name": "access_token",
198
+ "type": "text",
199
+ "primaryKey": false,
200
+ "notNull": false
201
+ },
202
+ "refresh_token": {
203
+ "name": "refresh_token",
204
+ "type": "text",
205
+ "primaryKey": false,
206
+ "notNull": false
207
+ },
208
+ "expires_at": {
209
+ "name": "expires_at",
210
+ "type": "integer",
211
+ "primaryKey": false,
212
+ "notNull": false
213
+ },
214
+ "access_token_expires_at": {
215
+ "name": "access_token_expires_at",
216
+ "type": "timestamp",
217
+ "primaryKey": false,
218
+ "notNull": false
219
+ },
220
+ "refresh_token_expires_at": {
221
+ "name": "refresh_token_expires_at",
222
+ "type": "timestamp",
223
+ "primaryKey": false,
224
+ "notNull": false
225
+ },
226
+ "scope": {
227
+ "name": "scope",
228
+ "type": "text",
229
+ "primaryKey": false,
230
+ "notNull": false
231
+ },
232
+ "id_token": {
233
+ "name": "id_token",
234
+ "type": "text",
235
+ "primaryKey": false,
236
+ "notNull": false
237
+ },
238
+ "password": {
239
+ "name": "password",
240
+ "type": "text",
241
+ "primaryKey": false,
242
+ "notNull": false
243
+ },
244
+ "created_at": {
245
+ "name": "created_at",
246
+ "type": "timestamp",
247
+ "primaryKey": false,
248
+ "notNull": true
249
+ },
250
+ "updated_at": {
251
+ "name": "updated_at",
252
+ "type": "timestamp",
253
+ "primaryKey": false,
254
+ "notNull": true
255
+ }
256
+ },
257
+ "indexes": {},
258
+ "foreignKeys": {
259
+ "account_user_id_users_id_fk": {
260
+ "name": "account_user_id_users_id_fk",
261
+ "tableFrom": "account",
262
+ "tableTo": "users",
263
+ "columnsFrom": ["user_id"],
264
+ "columnsTo": ["id"],
265
+ "onDelete": "cascade",
266
+ "onUpdate": "no action"
267
+ }
268
+ },
269
+ "compositePrimaryKeys": {},
270
+ "uniqueConstraints": {},
271
+ "policies": {},
272
+ "checkConstraints": {},
273
+ "isRLSEnabled": false
274
+ },
275
+ "public.session": {
276
+ "name": "session",
277
+ "schema": "",
278
+ "columns": {
279
+ "id": {
280
+ "name": "id",
281
+ "type": "text",
282
+ "primaryKey": true,
283
+ "notNull": true
284
+ },
285
+ "user_id": {
286
+ "name": "user_id",
287
+ "type": "uuid",
288
+ "primaryKey": false,
289
+ "notNull": true
290
+ },
291
+ "token": {
292
+ "name": "token",
293
+ "type": "text",
294
+ "primaryKey": false,
295
+ "notNull": true
296
+ },
297
+ "expires_at": {
298
+ "name": "expires_at",
299
+ "type": "timestamp",
300
+ "primaryKey": false,
301
+ "notNull": true
302
+ },
303
+ "ip_address": {
304
+ "name": "ip_address",
305
+ "type": "text",
306
+ "primaryKey": false,
307
+ "notNull": false
308
+ },
309
+ "user_agent": {
310
+ "name": "user_agent",
311
+ "type": "text",
312
+ "primaryKey": false,
313
+ "notNull": false
314
+ },
315
+ "impersonated_by": {
316
+ "name": "impersonated_by",
317
+ "type": "text",
318
+ "primaryKey": false,
319
+ "notNull": false
320
+ },
321
+ "created_at": {
322
+ "name": "created_at",
323
+ "type": "timestamp",
324
+ "primaryKey": false,
325
+ "notNull": true
326
+ },
327
+ "updated_at": {
328
+ "name": "updated_at",
329
+ "type": "timestamp",
330
+ "primaryKey": false,
331
+ "notNull": true
332
+ }
333
+ },
334
+ "indexes": {},
335
+ "foreignKeys": {
336
+ "session_user_id_users_id_fk": {
337
+ "name": "session_user_id_users_id_fk",
338
+ "tableFrom": "session",
339
+ "tableTo": "users",
340
+ "columnsFrom": ["user_id"],
341
+ "columnsTo": ["id"],
342
+ "onDelete": "cascade",
343
+ "onUpdate": "no action"
344
+ }
345
+ },
346
+ "compositePrimaryKeys": {},
347
+ "uniqueConstraints": {
348
+ "session_token_unique": {
349
+ "name": "session_token_unique",
350
+ "nullsNotDistinct": false,
351
+ "columns": ["token"]
352
+ }
353
+ },
354
+ "policies": {},
355
+ "checkConstraints": {},
356
+ "isRLSEnabled": false
357
+ },
358
+ "public.users": {
359
+ "name": "users",
360
+ "schema": "",
361
+ "columns": {
362
+ "id": {
363
+ "name": "id",
364
+ "type": "uuid",
365
+ "primaryKey": true,
366
+ "notNull": true
367
+ },
368
+ "name": {
369
+ "name": "name",
370
+ "type": "text",
371
+ "primaryKey": false,
372
+ "notNull": true
373
+ },
374
+ "email": {
375
+ "name": "email",
376
+ "type": "text",
377
+ "primaryKey": false,
378
+ "notNull": true
379
+ },
380
+ "email_verified": {
381
+ "name": "email_verified",
382
+ "type": "boolean",
383
+ "primaryKey": false,
384
+ "notNull": true,
385
+ "default": false
386
+ },
387
+ "image": {
388
+ "name": "image",
389
+ "type": "text",
390
+ "primaryKey": false,
391
+ "notNull": false
392
+ },
393
+ "role": {
394
+ "name": "role",
395
+ "type": "text",
396
+ "primaryKey": false,
397
+ "notNull": true,
398
+ "default": "'user'"
399
+ },
400
+ "banned": {
401
+ "name": "banned",
402
+ "type": "boolean",
403
+ "primaryKey": false,
404
+ "notNull": false,
405
+ "default": false
406
+ },
407
+ "ban_reason": {
408
+ "name": "ban_reason",
409
+ "type": "text",
410
+ "primaryKey": false,
411
+ "notNull": false
412
+ },
413
+ "ban_expires": {
414
+ "name": "ban_expires",
415
+ "type": "timestamp",
416
+ "primaryKey": false,
417
+ "notNull": false
418
+ },
419
+ "created_at": {
420
+ "name": "created_at",
421
+ "type": "timestamp",
422
+ "primaryKey": false,
423
+ "notNull": true,
424
+ "default": "now()"
425
+ },
426
+ "updated_at": {
427
+ "name": "updated_at",
428
+ "type": "timestamp",
429
+ "primaryKey": false,
430
+ "notNull": true,
431
+ "default": "now()"
432
+ },
433
+ "external_id": {
434
+ "name": "external_id",
435
+ "type": "text",
436
+ "primaryKey": false,
437
+ "notNull": false
438
+ }
439
+ },
440
+ "indexes": {
441
+ "users_lower_email_index": {
442
+ "name": "users_lower_email_index",
443
+ "columns": [
444
+ {
445
+ "expression": "lower(\"email\")",
446
+ "asc": true,
447
+ "isExpression": true,
448
+ "nulls": "last"
449
+ }
450
+ ],
451
+ "isUnique": true,
452
+ "concurrently": false,
453
+ "method": "btree",
454
+ "with": {}
455
+ },
456
+ "users_external_id_index": {
457
+ "name": "users_external_id_index",
458
+ "columns": [
459
+ {
460
+ "expression": "external_id",
461
+ "isExpression": false,
462
+ "asc": true,
463
+ "nulls": "last"
464
+ }
465
+ ],
466
+ "isUnique": true,
467
+ "where": "\"users\".\"external_id\" IS NOT NULL",
468
+ "concurrently": false,
469
+ "method": "btree",
470
+ "with": {}
471
+ }
472
+ },
473
+ "foreignKeys": {},
474
+ "compositePrimaryKeys": {},
475
+ "uniqueConstraints": {
476
+ "users_email_unique": {
477
+ "name": "users_email_unique",
478
+ "nullsNotDistinct": false,
479
+ "columns": ["email"]
480
+ }
481
+ },
482
+ "policies": {},
483
+ "checkConstraints": {},
484
+ "isRLSEnabled": false
485
+ },
486
+ "public.verification": {
487
+ "name": "verification",
488
+ "schema": "",
489
+ "columns": {
490
+ "id": {
491
+ "name": "id",
492
+ "type": "text",
493
+ "primaryKey": true,
494
+ "notNull": true
495
+ },
496
+ "identifier": {
497
+ "name": "identifier",
498
+ "type": "text",
499
+ "primaryKey": false,
500
+ "notNull": true
501
+ },
502
+ "value": {
503
+ "name": "value",
504
+ "type": "text",
505
+ "primaryKey": false,
506
+ "notNull": true
507
+ },
508
+ "expires_at": {
509
+ "name": "expires_at",
510
+ "type": "timestamp",
511
+ "primaryKey": false,
512
+ "notNull": true
513
+ },
514
+ "created_at": {
515
+ "name": "created_at",
516
+ "type": "timestamp",
517
+ "primaryKey": false,
518
+ "notNull": false
519
+ },
520
+ "updated_at": {
521
+ "name": "updated_at",
522
+ "type": "timestamp",
523
+ "primaryKey": false,
524
+ "notNull": false
525
+ }
526
+ },
527
+ "indexes": {},
528
+ "foreignKeys": {},
529
+ "compositePrimaryKeys": {},
530
+ "uniqueConstraints": {},
531
+ "policies": {},
532
+ "checkConstraints": {},
533
+ "isRLSEnabled": false
534
+ }
535
+ },
536
+ "enums": {},
537
+ "schemas": {},
538
+ "sequences": {},
539
+ "roles": {},
540
+ "policies": {},
541
+ "views": {},
542
+ "_meta": {
543
+ "columns": {},
544
+ "schemas": {},
545
+ "tables": {}
546
+ }
547
+ }
@@ -29,11 +29,6 @@
29
29
  "access:reconcile": "percepta-access-control reconcile --input access/reconcile.yaml",
30
30
  "auth:db:migrate": "pnpm --dir auth run db:migrate"
31
31
  },
32
- "engines": {
33
- "node": ">=20",
34
- "pnpm": ">=10"
35
- },
36
- "packageManager": "pnpm@10.6.4",
37
32
  "devDependencies": {
38
33
  "@percepta/access-control": "^1.0.0",
39
34
  "@percepta/build": "^1.0.0",
@@ -45,5 +40,10 @@
45
40
  "tsdown": "^0.21.10",
46
41
  "turbo": "^2.9.6",
47
42
  "typescript": "^6.0.3"
48
- }
43
+ },
44
+ "engines": {
45
+ "node": ">=20",
46
+ "pnpm": ">=10"
47
+ },
48
+ "packageManager": "pnpm@10.6.4"
49
49
  }
@@ -9,4 +9,4 @@ minimumReleaseAgeExclude:
9
9
 
10
10
  overrides:
11
11
  fast-xml-parser@<=5.5.6: 5.5.6
12
- '@opentelemetry/exporter-prometheus@<=0.217.0': 0.217.0
12
+ "@opentelemetry/exporter-prometheus@<=0.217.0": 0.217.0
@@ -86,9 +86,22 @@ Import components directly:
86
86
 
87
87
  ```tsx
88
88
  import {
89
- Button, Dialog, DropdownMenu, Select, Tabs,
90
- Input, Checkbox, Switch, Card, Badge, Table,
91
- Tooltip, Popover, Accordion, Avatar, Calendar,
89
+ Button,
90
+ Dialog,
91
+ DropdownMenu,
92
+ Select,
93
+ Tabs,
94
+ Input,
95
+ Checkbox,
96
+ Switch,
97
+ Card,
98
+ Badge,
99
+ Table,
100
+ Tooltip,
101
+ Popover,
102
+ Accordion,
103
+ Avatar,
104
+ Calendar,
92
105
  // ... 47+ components available
93
106
  } from "@percepta/design";
94
107
  ```
@@ -114,13 +127,17 @@ Provides centralized linter (oxlint), formatter (oxfmt), TypeScript, bundler (ts
114
127
  ```ts
115
128
  // oxfmt.config.ts
116
129
  import { defineOxfmtReactConfig } from "@percepta/build/oxfmt";
117
- export default defineOxfmtReactConfig({ stylesheet: "./src/styles/globals.css" });
130
+ export default defineOxfmtReactConfig({
131
+ stylesheet: "./src/styles/globals.css",
132
+ });
118
133
  ```
119
134
 
120
135
  ```ts
121
136
  // vitest.config.ts
122
137
  import { createVitestConfig } from "@percepta/build/vitest";
123
- export default createVitestConfig({ additionalSetupFiles: ["./vitest.setup.ts"] });
138
+ export default createVitestConfig({
139
+ additionalSetupFiles: ["./vitest.setup.ts"],
140
+ });
124
141
  ```
125
142
 
126
143
  Linting is configured once at the monorepo root via `@percepta/build/oxlint`.
@@ -151,7 +168,10 @@ import { getLogger } from "@/services/logger/AppLogger";
151
168
  const logger = getLogger();
152
169
 
153
170
  // safe data appears as-is; unsafe data (PII) is redacted
154
- logger.info({ safe: { requestId }, unsafe: { email } }, "User action completed");
171
+ logger.info(
172
+ { safe: { requestId }, unsafe: { email } },
173
+ "User action completed",
174
+ );
155
175
 
156
176
  // errors go as the third argument
157
177
  logger.error({ safe: { documentId } }, "Processing failed", error);
@@ -192,15 +212,15 @@ Requires `@percepta/mosaic-typescript-sdk` as a peer dependency.
192
212
 
193
213
  Detailed how-to guides for each major stack component. Read the relevant guide when working with that technology.
194
214
 
195
- | Guide | File | When to read |
196
- |-------|------|-------------|
197
- | Background Jobs (Inngest) | [agent-skills/inngest.md](agent-skills/inngest.md) | Adding async tasks, scheduled jobs, or agent workflows |
198
- | LLM Calls | [agent-skills/llm.md](agent-skills/llm.md) | Adding backend model calls, streaming, or structured generation |
199
- | LLM Observability (Langfuse) | [agent-skills/langfuse.md](agent-skills/langfuse.md) | App uses LLMs and needs trace/eval monitoring |
200
- | Database (Drizzle) | [agent-skills/database.md](agent-skills/database.md) | Adding tables, writing migrations, querying data |
201
- | Access Control (SpiceDB) | [agent-skills/access-control.md](agent-skills/access-control.md) | Adding Zed policy, app roles, permissioned resources, or group sync |
202
- | Deployment (Ryvn) | [agent-skills/ryvn.md](agent-skills/ryvn.md) | Ryvn service release notes; environment installs live in infra |
203
- | Build App (Oneshot) | [agent-skills/oneshot.md](agent-skills/oneshot.md) | Building a complete app from requirements end-to-end |
215
+ | Guide | File | When to read |
216
+ | ---------------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------- |
217
+ | Background Jobs (Inngest) | [agent-skills/inngest.md](agent-skills/inngest.md) | Adding async tasks, scheduled jobs, or agent workflows |
218
+ | LLM Calls | [agent-skills/llm.md](agent-skills/llm.md) | Adding backend model calls, streaming, or structured generation |
219
+ | LLM Observability (Langfuse) | [agent-skills/langfuse.md](agent-skills/langfuse.md) | App uses LLMs and needs trace/eval monitoring |
220
+ | Database (Drizzle) | [agent-skills/database.md](agent-skills/database.md) | Adding tables, writing migrations, querying data |
221
+ | Access Control (SpiceDB) | [agent-skills/access-control.md](agent-skills/access-control.md) | Adding Zed policy, app roles, permissioned resources, or group sync |
222
+ | Deployment (Ryvn) | [agent-skills/ryvn.md](agent-skills/ryvn.md) | Ryvn service release notes; environment installs live in infra |
223
+ | Build App (Oneshot) | [agent-skills/oneshot.md](agent-skills/oneshot.md) | Building a complete app from requirements end-to-end |
204
224
 
205
225
  ## Key Patterns
206
226
 
@@ -211,7 +231,9 @@ Type-safe API layer. Define routers in `src/server/api/`, compose in `root.ts`:
211
231
  ```tsx
212
232
  // src/server/api/root.ts
213
233
  import { router } from "../trpc";
214
- export const appRouter = router({ /* add routers here */ });
234
+ export const appRouter = router({
235
+ /* add routers here */
236
+ });
215
237
  export type AppRouter = typeof appRouter;
216
238
  ```
217
239