create-kuckit-app 2.0.2 → 2.2.0

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 (62) hide show
  1. package/README.md +24 -14
  2. package/package.json +3 -1
  3. package/templates/base/.claude/skills/beads/CLAUDE.md +87 -0
  4. package/templates/base/.claude/skills/beads/README.md +123 -0
  5. package/templates/base/.claude/skills/beads/SKILL.md +77 -715
  6. package/templates/base/.claude/skills/beads/adr/0001-bd-prime-as-source-of-truth.md +61 -0
  7. package/templates/base/.claude/skills/beads/resources/AGENTS.md +62 -0
  8. package/templates/base/.claude/skills/beads/resources/ASYNC_GATES.md +175 -0
  9. package/templates/base/.claude/skills/beads/resources/BOUNDARIES.md +520 -0
  10. package/templates/base/.claude/skills/beads/resources/CHEMISTRY_PATTERNS.md +197 -0
  11. package/templates/base/.claude/skills/beads/resources/CLI_REFERENCE.md +561 -0
  12. package/templates/base/.claude/skills/beads/resources/DEPENDENCIES.md +754 -0
  13. package/templates/base/.claude/skills/beads/resources/INTEGRATION_PATTERNS.md +438 -0
  14. package/templates/base/.claude/skills/beads/resources/ISSUE_CREATION.md +150 -0
  15. package/templates/base/.claude/skills/beads/resources/MOLECULES.md +370 -0
  16. package/templates/base/.claude/skills/beads/resources/PATTERNS.md +363 -0
  17. package/templates/base/.claude/skills/beads/resources/RESUMABILITY.md +239 -0
  18. package/templates/base/.claude/skills/beads/resources/STATIC_DATA.md +61 -0
  19. package/templates/base/.claude/skills/beads/resources/TROUBLESHOOTING.md +537 -0
  20. package/templates/base/.claude/skills/beads/resources/WORKFLOWS.md +638 -0
  21. package/templates/base/.claude/skills/beads/resources/WORKTREES.md +95 -0
  22. package/templates/base/.claude/skills/browser-skill/SKILL.md +72 -0
  23. package/templates/base/.claude/skills/knowledge/SKILL.md +155 -205
  24. package/templates/base/.claude/skills/knowledge/reference/doc-mapping.md +49 -0
  25. package/templates/base/.claude/skills/knowledge/reference/extraction-prompts.md +102 -0
  26. package/templates/base/.claude/skills/kuckit/SKILL.md +15 -9
  27. package/templates/base/.claude/skills/kuckit/references/MODULE-DEVELOPMENT.md +142 -0
  28. package/templates/base/.claude/skills/kuckit/references/PACKAGES.md +22 -17
  29. package/templates/base/.claude/skills/kuckit/references/PUBLISHING.md +92 -0
  30. package/templates/base/.claude/skills/module-testing/SKILL.md +1 -1
  31. package/templates/base/.claude/skills/planning/SKILL.md +26 -1
  32. package/templates/base/.env.example +1 -1
  33. package/templates/base/AGENTS.md +155 -418
  34. package/templates/base/apps/server/package.json +3 -3
  35. package/templates/base/apps/server/src/modules.ts +14 -1
  36. package/templates/base/apps/web/.env.example +1 -1
  37. package/templates/base/apps/web/package.json +2 -2
  38. package/templates/base/apps/web/src/components/dashboard/nav-user.tsx +3 -3
  39. package/templates/base/apps/web/src/components/ui/sidebar.tsx +2 -1
  40. package/templates/base/apps/web/src/routes/$.tsx +0 -1
  41. package/templates/base/apps/web/src/routes/__root.tsx +7 -1
  42. package/templates/base/apps/web/src/routes/dashboard.tsx +3 -1
  43. package/templates/base/apps/web/src/routes/index.tsx +17 -22
  44. package/templates/base/apps/web/src/routes/login.tsx +81 -50
  45. package/templates/base/apps/web/tsconfig.json +1 -0
  46. package/templates/base/docs/ARCHITECTURE.md +689 -0
  47. package/templates/base/docs/DEPENDENCY-INJECTION.md +871 -0
  48. package/templates/base/docs/DEPLOYMENT.md +573 -0
  49. package/templates/base/docs/INDEX.md +135 -0
  50. package/templates/base/docs/MIGRATION.md +989 -0
  51. package/templates/base/docs/MODULE_CSS.md +343 -0
  52. package/templates/base/docs/MODULE_TESTING.md +368 -0
  53. package/templates/base/docs/MULTI_AGENT_WORKFLOW.md +909 -0
  54. package/templates/base/docs/TESTING.md +579 -0
  55. package/templates/base/docs/TROUBLESHOOTING.md +360 -0
  56. package/templates/base/drizzle.config.ts +17 -1
  57. package/templates/base/package.json +8 -6
  58. package/templates/base/packages/items-module/AGENTS.md +3 -1
  59. package/templates/base/packages/items-module/package.json +4 -4
  60. package/templates/base/packages/items-module/src/server/adapters/{item.drizzle.ts → item.repository.ts} +1 -13
  61. package/templates/base/packages/items-module/src/server/module.ts +2 -1
  62. package/templates/base/packages/items-module/src/server/schema/item.ts +13 -0
@@ -0,0 +1,989 @@
1
+ # Migration Guide
2
+
3
+ This guide covers migrating Kuckit applications between major versions.
4
+
5
+ ---
6
+
7
+ ## Migrating from v2 to v3 (SDK v3.0.0 / CLI v4.0.0)
8
+
9
+ Kuckit v3.0 introduces a packages-first architecture inversion, new module patterns, and infrastructure improvements. This is a **major breaking release**.
10
+
11
+ ### Overview of Breaking Changes
12
+
13
+ | Area | v2 Pattern | v3 Pattern |
14
+ | ------------------- | ----------------------------------- | ------------------------------------------------------------- |
15
+ | Architecture | Apps contain logic, import packages | Packages contain all logic, apps are minimal bootstrap shells |
16
+ | Module Structure | Flat `src/` layout | `src/server/` + `src/client/` separation |
17
+ | Canonical Reference | `users-module` | `items-module` (users deprecated) |
18
+ | CSS Aggregation | Manual imports | `@source` scans `.js` files, `styles.css` → `dist/` |
19
+ | Schema Discovery | `src/server/schema` default | `src/server/adapters` default |
20
+ | Environment Vars | `VITE_API_URL` | `VITE_SERVER_URL` |
21
+ | Infrastructure | `kuckit-gcp-infra` project | `kuckit-infra` + per-env configs |
22
+
23
+ ---
24
+
25
+ ### 1. Architecture Inversion
26
+
27
+ v3.0 inverts the architecture: **packages are primary, apps are minimal bootstrap shells**.
28
+
29
+ #### Before (v2)
30
+
31
+ - `apps/server` contained ~400 lines of bootstrap, middleware, DI wiring
32
+ - `apps/web` contained provider setup, route configuration
33
+ - Packages provided utilities that apps consumed
34
+
35
+ #### After (v3)
36
+
37
+ - `apps/server` is ~10 lines calling `runKuckitServer()`
38
+ - `apps/web` is ~10 lines with `KuckitWebProvider`
39
+ - All logic lives in `packages/*` and SDK packages
40
+
41
+ **Impact**: Your apps should import bootstrap from SDK packages, not contain custom wiring.
42
+
43
+ ---
44
+
45
+ ### 2. Module Structure Migration
46
+
47
+ Modules now use a `src/server/` + `src/client/` split architecture.
48
+
49
+ #### Before (v2)
50
+
51
+ ```
52
+ my-module/
53
+ ├── src/
54
+ │ ├── domain/
55
+ │ ├── ports/
56
+ │ ├── adapters/
57
+ │ ├── usecases/
58
+ │ ├── api/
59
+ │ ├── ui/
60
+ │ ├── module.ts
61
+ │ └── client-module.ts
62
+ └── package.json
63
+ ```
64
+
65
+ #### After (v3)
66
+
67
+ ```
68
+ my-module/
69
+ ├── src/
70
+ │ ├── server/ # Server-side code
71
+ │ │ ├── domain/
72
+ │ │ ├── ports/
73
+ │ │ ├── adapters/
74
+ │ │ ├── usecases/
75
+ │ │ ├── api/
76
+ │ │ ├── config.ts # Zod config schema
77
+ │ │ ├── module.ts
78
+ │ │ └── index.ts # Server exports
79
+ │ └── client/ # Client-side code
80
+ │ ├── ui/
81
+ │ ├── client-module.ts
82
+ │ └── index.ts # Client exports
83
+ ├── package.json # With kuckit metadata
84
+ └── styles.css # Copied to dist/ for CSS aggregation
85
+ ```
86
+
87
+ #### Migration Steps
88
+
89
+ 1. Create `src/server/` and `src/client/` directories
90
+ 2. Move server code to `src/server/`
91
+ 3. Move client code to `src/client/`
92
+ 4. Update package.json exports:
93
+
94
+ ```json
95
+ {
96
+ "exports": {
97
+ ".": "./src/server/index.ts",
98
+ "./client": "./src/client/index.ts"
99
+ },
100
+ "kuckit": {
101
+ "id": "my-org.my-module",
102
+ "server": "src/server/index.ts",
103
+ "client": "src/client/index.ts"
104
+ }
105
+ }
106
+ ```
107
+
108
+ 5. Add Zod config schema in `src/server/config.ts`:
109
+
110
+ ```typescript
111
+ import { z } from 'zod'
112
+
113
+ export const myModuleConfigSchema = z.object({
114
+ myOption: z.string().optional().default('default'),
115
+ })
116
+
117
+ export type MyModuleConfig = z.infer<typeof myModuleConfigSchema>
118
+ ```
119
+
120
+ See [items-module](../packages/create-kuckit-app/templates/base/packages/items-module/) as the canonical reference.
121
+
122
+ ---
123
+
124
+ ### 3. CSS Aggregator Pattern
125
+
126
+ Tailwind v4 requires CSS `@source` directives to scan compiled `.js` files, not source `.tsx`.
127
+
128
+ #### Before (v2)
129
+
130
+ ```css
131
+ /* Manual @source directives pointing to tsx */
132
+ @source "../../node_modules/@my-org/my-module/src/**/*.tsx";
133
+ ```
134
+
135
+ #### After (v3)
136
+
137
+ ```css
138
+ /* @source directives scan compiled .js */
139
+ @source "../../node_modules/@my-org/my-module/dist/**/*.js";
140
+ ```
141
+
142
+ #### Module Migration
143
+
144
+ 1. Create `styles.css` in module root (or `src/styles.css`)
145
+ 2. Add build step to copy to `dist/`:
146
+
147
+ ```json
148
+ {
149
+ "scripts": {
150
+ "build": "tsup && cp styles.css dist/"
151
+ }
152
+ }
153
+ ```
154
+
155
+ 3. Add to package.json kuckit metadata:
156
+
157
+ ```json
158
+ {
159
+ "kuckit": {
160
+ "styles": "dist/styles.css"
161
+ }
162
+ }
163
+ ```
164
+
165
+ The CLI `add-module` command will automatically detect and inject CSS imports.
166
+
167
+ See [MODULE_CSS.md](./MODULE_CSS.md) for complete documentation.
168
+
169
+ ---
170
+
171
+ ### 4. Schema Discovery Path Change
172
+
173
+ The default schema directory changed from `src/server/schema` to `src/server/adapters`.
174
+
175
+ #### Before (v2)
176
+
177
+ Drizzle looked for schemas in `src/server/schema/`.
178
+
179
+ #### After (v3)
180
+
181
+ Priority-based discovery:
182
+
183
+ 1. Explicit `schemaDir` in `kuckit.config.ts`
184
+ 2. `kuckit.schemaDir` in module's `package.json`
185
+ 3. Default: `src/server/adapters`
186
+
187
+ #### Migration
188
+
189
+ If your schemas are in `src/server/schema`, either:
190
+
191
+ **Option A**: Move schemas to `src/server/adapters`
192
+
193
+ **Option B**: Configure explicit path in package.json:
194
+
195
+ ```json
196
+ {
197
+ "kuckit": {
198
+ "schemaDir": "src/server/schema"
199
+ }
200
+ }
201
+ ```
202
+
203
+ See [ARCHITECTURE.md#schema-discovery](./ARCHITECTURE.md#schema-discovery-v30) for details.
204
+
205
+ ---
206
+
207
+ ### 5. Environment Variable Rename
208
+
209
+ #### Before (v2)
210
+
211
+ ```env
212
+ VITE_API_URL=http://localhost:3000
213
+ ```
214
+
215
+ #### After (v3)
216
+
217
+ ```env
218
+ VITE_SERVER_URL=http://localhost:3000
219
+ POLAR_ENVIRONMENT=sandbox # If using Polar payments
220
+ ```
221
+
222
+ #### Migration
223
+
224
+ 1. Rename in all `.env*` files
225
+ 2. Update code references:
226
+
227
+ ```typescript
228
+ // Before
229
+ const baseURL = import.meta.env.VITE_API_URL
230
+
231
+ // After
232
+ const baseURL = import.meta.env.VITE_SERVER_URL
233
+ ```
234
+
235
+ ---
236
+
237
+ ### 6. Infrastructure Configuration
238
+
239
+ The Pulumi project was renamed and now supports per-environment configs.
240
+
241
+ #### Before (v2)
242
+
243
+ - Pulumi project name: `kuckit-gcp-infra`
244
+ - Single config file: `.kuckit/infra.json`
245
+
246
+ #### After (v3)
247
+
248
+ - Pulumi project name: `kuckit-infra`
249
+ - Per-environment configs: `infra.dev.json`, `infra.prod.json`
250
+
251
+ #### Migration
252
+
253
+ 1. Rename Pulumi project in existing stack:
254
+
255
+ ```bash
256
+ # In Pulumi.yaml
257
+ name: kuckit-infra # was kuckit-gcp-infra
258
+ ```
259
+
260
+ 2. Create per-environment configs:
261
+
262
+ ```bash
263
+ # infra.dev.json
264
+ {
265
+ "env": "dev",
266
+ "gcpProject": "my-project-dev",
267
+ "region": "us-central1"
268
+ }
269
+
270
+ # infra.prod.json
271
+ {
272
+ "env": "prod",
273
+ "gcpProject": "my-project-prod",
274
+ "region": "us-central1"
275
+ }
276
+ ```
277
+
278
+ 3. Use `--env` flag with infra commands:
279
+
280
+ ```bash
281
+ bunx kuckit infra deploy --env dev
282
+ bunx kuckit infra deploy --env prod
283
+ ```
284
+
285
+ See [DEPLOYMENT.md](./DEPLOYMENT.md) for complete infrastructure documentation.
286
+
287
+ ---
288
+
289
+ ### Step-by-Step Migration Checklist
290
+
291
+ #### Phase 1: Update Dependencies
292
+
293
+ - [ ] Update `@kuckit/sdk` to `^3.0.0`
294
+ - [ ] Update `@kuckit/cli` to `^4.0.0`
295
+ - [ ] Update all module packages to `^3.0.0`
296
+
297
+ #### Phase 2: Environment Variables
298
+
299
+ - [ ] Rename `VITE_API_URL` to `VITE_SERVER_URL` in all `.env*` files
300
+ - [ ] Add `POLAR_ENVIRONMENT` if using Polar payments
301
+ - [ ] Update code references to use new variable names
302
+
303
+ #### Phase 3: Module Structure (per module)
304
+
305
+ - [ ] Create `src/server/` and `src/client/` directories
306
+ - [ ] Move server code to `src/server/`
307
+ - [ ] Move client code to `src/client/`
308
+ - [ ] Add Zod config schema
309
+ - [ ] Update package.json exports and kuckit metadata
310
+ - [ ] Update relative imports
311
+
312
+ #### Phase 4: Schema Discovery
313
+
314
+ - [ ] Move schemas to `src/server/adapters/`, OR
315
+ - [ ] Add explicit `schemaDir` in package.json kuckit metadata
316
+
317
+ #### Phase 5: CSS Aggregation
318
+
319
+ - [ ] Create module `styles.css` if module has custom styles
320
+ - [ ] Add build step to copy CSS to `dist/`
321
+ - [ ] Add `styles` field to package.json kuckit metadata
322
+ - [ ] Update `@source` directives to scan `.js` not `.tsx`
323
+
324
+ #### Phase 6: Infrastructure (if applicable)
325
+
326
+ - [ ] Rename Pulumi project to `kuckit-infra`
327
+ - [ ] Create per-environment config files
328
+ - [ ] Update deployment scripts to use `--env` flag
329
+
330
+ #### Phase 7: Verification
331
+
332
+ - [ ] Run `bun run check-types` - all types pass
333
+ - [ ] Run `bun run build` - build succeeds
334
+ - [ ] Run `bunx kuckit doctor` - validates setup
335
+ - [ ] Run `bun run dev` - dev server starts
336
+ - [ ] Test module functionality
337
+
338
+ ---
339
+
340
+ ### Troubleshooting v3 Migration
341
+
342
+ #### "Cannot find module './server' or './client'"
343
+
344
+ Your package.json exports are incorrect. Update:
345
+
346
+ ```json
347
+ {
348
+ "exports": {
349
+ ".": "./src/server/index.ts",
350
+ "./client": "./src/client/index.ts"
351
+ }
352
+ }
353
+ ```
354
+
355
+ #### "Schema not found during migration"
356
+
357
+ Schema discovery now defaults to `src/server/adapters`. Either:
358
+
359
+ - Move your schemas there, or
360
+ - Set `kuckit.schemaDir` in package.json
361
+
362
+ #### "Tailwind not picking up module styles"
363
+
364
+ Ensure `@source` scans `.js` files in `dist/`, not `.tsx` in `src/`:
365
+
366
+ ```css
367
+ @source "../../node_modules/@my-org/my-module/dist/**/*.js";
368
+ ```
369
+
370
+ #### "Environment variable undefined"
371
+
372
+ `VITE_API_URL` was renamed to `VITE_SERVER_URL`. Update your `.env` files.
373
+
374
+ #### "Pulumi stack name mismatch"
375
+
376
+ The project was renamed from `kuckit-gcp-infra` to `kuckit-infra`. Update `Pulumi.yaml`.
377
+
378
+ ---
379
+
380
+ ## Migrating from v1 to v2
381
+
382
+ Kuckit v2 introduces significant architectural improvements including zero-bootstrap templates, factory patterns, and new hook APIs. This guide covers all breaking changes and migration steps.
383
+
384
+ ### Overview of Breaking Changes
385
+
386
+ | Area | v1 Pattern | v2 Pattern |
387
+ | ------------------- | ------------------------------- | ----------------------------------------- |
388
+ | Server Bootstrap | Custom `server.ts` (~400 lines) | `runKuckitServer()` (~12 lines) |
389
+ | Client Provider | Local `useKuckit` hook | `useKuckitWeb` from `@kuckit/app-web` |
390
+ | Auth Client | Global `authClient` import | `useAuth()` hook |
391
+ | Auth Setup | Singleton `auth` export | `createAuth()` factory |
392
+ | Database | Singleton `db` export | `createDb()` / `createDbPool()` factories |
393
+ | Module Dependencies | `workspace:*` references | Published npm versions |
394
+ | oRPC Routers | Dynamic wiring | Mutable root pattern |
395
+
396
+ ---
397
+
398
+ ### 1. Server Bootstrap Migration
399
+
400
+ The most significant change is the extraction of server bootstrap logic into `@kuckit/app-server`.
401
+
402
+ #### Before (v1)
403
+
404
+ ```typescript
405
+ // apps/server/src/server.ts - v1 (~400 lines)
406
+ import express from 'express'
407
+ import { createContainer, asValue, asFunction } from 'awilix'
408
+ import { auth } from '@kuckit/auth'
409
+ import { db } from '@kuckit/db'
410
+ // ... 350+ more lines of bootstrap code
411
+ ```
412
+
413
+ #### After (v2)
414
+
415
+ ```typescript
416
+ // apps/server/src/server.ts - v2 (~12 lines)
417
+ import 'dotenv/config'
418
+ import { runKuckitServer } from '@kuckit/app-server'
419
+ import { loadConfig } from './config/server'
420
+ import { getModuleSpecs } from './config/modules'
421
+
422
+ runKuckitServer({
423
+ loadConfig,
424
+ getModuleSpecs,
425
+ }).catch((error) => {
426
+ console.error('Failed to start server:', error)
427
+ process.exit(1)
428
+ })
429
+ ```
430
+
431
+ #### Migration Steps
432
+
433
+ 1. **Install bootstrap package**:
434
+
435
+ ```bash
436
+ bun add @kuckit/app-server
437
+ ```
438
+
439
+ 2. **Create config loader** (`apps/server/src/config/server.ts`):
440
+
441
+ ```typescript
442
+ import type { KuckitServerConfig } from '@kuckit/app-server'
443
+
444
+ export const loadConfig = (): KuckitServerConfig => ({
445
+ databaseUrl: process.env.DATABASE_URL!,
446
+ port: parseInt(process.env.PORT || '3000', 10),
447
+ corsOrigin: process.env.CORS_ORIGIN || '*',
448
+ env: process.env.NODE_ENV as 'development' | 'production',
449
+ logLevel: 'INFO',
450
+ enableFileLogging: false,
451
+ logDir: './logs',
452
+ })
453
+ ```
454
+
455
+ 3. **Create module specs** (`apps/server/src/config/modules.ts`):
456
+
457
+ ```typescript
458
+ import type { ModuleSpec } from '@kuckit/sdk'
459
+
460
+ export const getModuleSpecs = (): ModuleSpec[] => [
461
+ { package: '@kuckit/users-module' },
462
+ { package: '@kuckit/landing-module' },
463
+ ]
464
+ ```
465
+
466
+ 4. **Replace server.ts** with the minimal version shown above.
467
+
468
+ 5. **Move custom logic to hooks** (if needed):
469
+ ```typescript
470
+ runKuckitServer({
471
+ loadConfig,
472
+ getModuleSpecs,
473
+ hooks: {
474
+ onAppCreated: async (app) => {
475
+ app.use(customMiddleware)
476
+ },
477
+ onContainerReady: async (container) => {
478
+ // Custom initialization
479
+ },
480
+ },
481
+ })
482
+ ```
483
+
484
+ ---
485
+
486
+ ### 2. Client Provider Migration (`useKuckit` → `useKuckitWeb`)
487
+
488
+ The client-side provider has moved from a local implementation to `@kuckit/app-web`.
489
+
490
+ #### Before (v1)
491
+
492
+ ```typescript
493
+ // apps/web/src/providers/KuckitProvider.tsx - v1
494
+ import { createContext, useContext } from 'react'
495
+ import { authClient } from '@/lib/auth-client'
496
+
497
+ const KuckitContext = createContext(...)
498
+
499
+ export const useKuckit = () => useContext(KuckitContext)
500
+
501
+ // Usage in components
502
+ import { useKuckit } from '@/providers/KuckitProvider'
503
+ import { authClient } from '@/lib/auth-client'
504
+
505
+ function MyComponent() {
506
+ const { routeRegistry } = useKuckit()
507
+ const { data: session } = authClient.useSession()
508
+ // ...
509
+ }
510
+ ```
511
+
512
+ #### After (v2)
513
+
514
+ ```typescript
515
+ // apps/web/src/main.tsx - v2
516
+ import { createKuckitWebProvider } from '@kuckit/app-web'
517
+ import { createAuthClient } from 'better-auth/react'
518
+ import config from '../kuckit.config'
519
+
520
+ const authClient = createAuthClient({
521
+ baseURL: import.meta.env.VITE_SERVER_URL || 'http://localhost:3000',
522
+ })
523
+
524
+ const KuckitProvider = createKuckitWebProvider({
525
+ config,
526
+ authClient,
527
+ })
528
+
529
+ // Usage in components
530
+ import { useKuckitWeb, useAuth } from '@kuckit/app-web'
531
+
532
+ function MyComponent() {
533
+ const { routeRegistry } = useKuckitWeb()
534
+ const authClient = useAuth()
535
+ const { data: session } = authClient.useSession()
536
+ // ...
537
+ }
538
+ ```
539
+
540
+ #### Migration Steps
541
+
542
+ 1. **Install bootstrap package**:
543
+
544
+ ```bash
545
+ bun add @kuckit/app-web
546
+ ```
547
+
548
+ 2. **Update main.tsx**:
549
+
550
+ ```typescript
551
+ import { createKuckitWebProvider } from '@kuckit/app-web'
552
+
553
+ const KuckitProvider = createKuckitWebProvider({
554
+ config,
555
+ authClient,
556
+ })
557
+ ```
558
+
559
+ 3. **Find and replace imports** in all components:
560
+
561
+ ```typescript
562
+ // Before
563
+ import { useKuckit } from '@/providers/KuckitProvider'
564
+ import { authClient } from '@/lib/auth-client'
565
+
566
+ // After
567
+ import { useKuckitWeb, useAuth } from '@kuckit/app-web'
568
+ ```
569
+
570
+ 4. **Update hook usage**:
571
+
572
+ ```typescript
573
+ // Before
574
+ const { routeRegistry } = useKuckit()
575
+ // authClient was imported globally
576
+
577
+ // After
578
+ const { routeRegistry } = useKuckitWeb()
579
+ const authClient = useAuth()
580
+ ```
581
+
582
+ 5. **Delete old files**:
583
+ - `apps/web/src/providers/KuckitProvider.tsx`
584
+ - `apps/web/src/lib/auth-client.ts` (if only used for export)
585
+
586
+ ---
587
+
588
+ ### 3. Factory Pattern Migration
589
+
590
+ v2 replaces singleton exports with factory functions to prevent import-time side effects.
591
+
592
+ #### Auth Factory
593
+
594
+ ##### Before (v1)
595
+
596
+ ```typescript
597
+ // ❌ WRONG - Triggers DB connection at import time
598
+ import { auth } from '@kuckit/auth'
599
+ ```
600
+
601
+ ##### After (v2)
602
+
603
+ ```typescript
604
+ // ✅ CORRECT - Deferred initialization
605
+ import { createAuth } from '@kuckit/auth'
606
+
607
+ const auth = createAuth({
608
+ db,
609
+ config: {
610
+ trustedOrigins: ['http://localhost:5173'],
611
+ },
612
+ })
613
+ ```
614
+
615
+ #### Database Factory
616
+
617
+ ##### Before (v1)
618
+
619
+ ```typescript
620
+ // ❌ WRONG - Connects at import time
621
+ import { db } from '@kuckit/db'
622
+ ```
623
+
624
+ ##### After (v2)
625
+
626
+ ```typescript
627
+ // ✅ CORRECT - Explicit connection control
628
+ import { createDbPool, createDb } from '@kuckit/db'
629
+
630
+ const pool = createDbPool(process.env.DATABASE_URL!)
631
+ const db = createDb(pool)
632
+
633
+ // Or use the combined helper
634
+ import { createDatabase } from '@kuckit/db'
635
+ const { pool, db } = createDatabase(process.env.DATABASE_URL!)
636
+ ```
637
+
638
+ #### Why This Matters
639
+
640
+ The factory pattern solves the "import-time side effects" problem:
641
+
642
+ 1. **v1 Problem**: Importing `kuckit.config.ts` → imports SDK → imports auth → imports db → **triggers database connection**
643
+ 2. **v2 Solution**: Imports only load pure code; connections happen at runtime when you call factories
644
+
645
+ ---
646
+
647
+ ### 4. Module Dependencies Migration
648
+
649
+ Modules must now use published npm versions instead of `workspace:*` references.
650
+
651
+ #### Before (v1)
652
+
653
+ ```json
654
+ {
655
+ "dependencies": {
656
+ "@kuckit/sdk": "workspace:*",
657
+ "@kuckit/db": "workspace:*"
658
+ }
659
+ }
660
+ ```
661
+
662
+ #### After (v2)
663
+
664
+ ```json
665
+ {
666
+ "dependencies": {
667
+ "@kuckit/sdk": "^1.0.0",
668
+ "@kuckit/db": "^1.0.0"
669
+ }
670
+ }
671
+ ```
672
+
673
+ #### Migration Steps
674
+
675
+ 1. **Update package.json** in each module
676
+ 2. **Run the workspace protocol resolver** (for publishing):
677
+ ```bash
678
+ node scripts/resolve-workspace-protocols.cjs
679
+ ```
680
+ 3. **Verify no workspace references remain**:
681
+ ```bash
682
+ node scripts/check-no-workspace-protocol.cjs
683
+ ```
684
+
685
+ ---
686
+
687
+ ### 5. oRPC Router Wiring Pattern
688
+
689
+ Module routers must now follow the "mutable root pattern" to wire correctly.
690
+
691
+ #### Key Concept
692
+
693
+ oRPC's `RPCHandler` captures the router object at construction time. Module routers must be wired **before** the handler is created.
694
+
695
+ #### Correct Implementation
696
+
697
+ ```typescript
698
+ // 1. Create mutable root router from app router
699
+ const rpcRouter = { ...appRouter }
700
+
701
+ // 2. Wire module routers into it
702
+ onApiRegistrations((registrations) => {
703
+ for (const reg of registrations) {
704
+ if (reg.type === 'rpc-router') {
705
+ rpcRouter[reg.name] = reg.router // Mutate before RPCHandler
706
+ }
707
+ }
708
+ })
709
+
710
+ // 3. THEN create RPCHandler with the populated router
711
+ const rpcHandler = new RPCHandler(rpcRouter, {
712
+ /* ... */
713
+ })
714
+ ```
715
+
716
+ #### Common Mistakes
717
+
718
+ - ❌ Don't create a new router object after `RPCHandler` is constructed
719
+ - ❌ Don't call `setupRPC()` before modules are loaded
720
+ - ✅ Do mutate the same router object that `RPCHandler` holds
721
+ - ✅ Do ensure `loadKuckitModules()` completes before `setupRPC()`
722
+
723
+ ---
724
+
725
+ ### 6. Config Subpaths
726
+
727
+ v2 introduces side-effect-free subpath exports for configuration.
728
+
729
+ #### Usage
730
+
731
+ ```typescript
732
+ // Pure types and config helpers (no side effects)
733
+ import { defineConfig } from '@kuckit/sdk/config'
734
+ import { getModuleSchemaPaths } from '@kuckit/db/config'
735
+
736
+ // Safe to use in kuckit.config.ts and drizzle.config.ts
737
+ export default defineConfig({
738
+ modules: [{ package: '@kuckit/users-module' }],
739
+ })
740
+ ```
741
+
742
+ #### Why This Matters
743
+
744
+ These subpaths are safe to import in configuration files without triggering database connections or other side effects.
745
+
746
+ ---
747
+
748
+ ### Step-by-Step Migration Checklist
749
+
750
+ #### Phase 1: Install New Packages
751
+
752
+ - [ ] `bun add @kuckit/app-server` (server)
753
+ - [ ] `bun add @kuckit/app-web` (web)
754
+
755
+ #### Phase 2: Server Migration
756
+
757
+ - [ ] Create `apps/server/src/config/server.ts`
758
+ - [ ] Create `apps/server/src/config/modules.ts`
759
+ - [ ] Replace `apps/server/src/server.ts` with minimal `runKuckitServer()` call
760
+ - [ ] Move custom middleware to hooks if needed
761
+ - [ ] Delete old container setup files
762
+
763
+ #### Phase 3: Client Migration
764
+
765
+ - [ ] Update `apps/web/src/main.tsx` to use `createKuckitWebProvider`
766
+ - [ ] Find/replace `useKuckit` → `useKuckitWeb` in all components
767
+ - [ ] Find/replace `authClient` imports → `useAuth()` hook
768
+ - [ ] Delete `apps/web/src/providers/KuckitProvider.tsx`
769
+ - [ ] Delete `apps/web/src/lib/auth-client.ts`
770
+
771
+ #### Phase 4: Module Updates
772
+
773
+ - [ ] Update module dependencies from `workspace:*` to npm versions
774
+ - [ ] Verify module client components use `useKuckitWeb` + `useAuth`
775
+ - [ ] Test each module individually
776
+
777
+ #### Phase 5: Verification
778
+
779
+ - [ ] Run `bun run check-types` - all types pass
780
+ - [ ] Run `bun run build` - build succeeds
781
+ - [ ] Run `bun run dev` - server starts correctly
782
+ - [ ] Test authentication flows
783
+ - [ ] Test module routes and navigation
784
+
785
+ ---
786
+
787
+ ### Troubleshooting
788
+
789
+ #### "Cannot find module '@kuckit/app-server'"
790
+
791
+ Install the bootstrap packages:
792
+
793
+ ```bash
794
+ bun add @kuckit/app-server @kuckit/app-web
795
+ ```
796
+
797
+ #### "useKuckitWeb must be used within KuckitWebProvider"
798
+
799
+ Ensure your app is wrapped with the provider from `createKuckitWebProvider()`.
800
+
801
+ #### "Database connection failed at import time"
802
+
803
+ You're still using singleton imports. Update to factory pattern:
804
+
805
+ ```typescript
806
+ // Before
807
+ import { db } from '@kuckit/db'
808
+
809
+ // After
810
+ import { createDatabase } from '@kuckit/db'
811
+ const { db } = createDatabase(process.env.DATABASE_URL!)
812
+ ```
813
+
814
+ #### "Module router not appearing in API"
815
+
816
+ Ensure modules are loaded before RPC setup. The `@kuckit/app-server` handles this automatically with the mutable root pattern.
817
+
818
+ ---
819
+
820
+ ## Migrating from packages/infra to @kuckit/infra-gcp
821
+
822
+ If you have an existing Kuckit project with a `packages/infra` directory, follow this guide to migrate to the new provider-based infrastructure system.
823
+
824
+ ### Why Migrate?
825
+
826
+ The new provider-based system offers:
827
+
828
+ - **Simpler setup** - Install an npm package instead of managing Pulumi code
829
+ - **Automatic updates** - Get infrastructure improvements via package updates
830
+ - **Multi-cloud support** - Switch providers without rewriting infrastructure
831
+ - **Dockerfile generation** - Auto-generated, optimized Dockerfiles
832
+
833
+ ### Before You Start
834
+
835
+ 1. **Backup your Pulumi state** - Ensure your Pulumi state is saved (Pulumi Cloud or local backend)
836
+ 2. **Note your current stack name** - Run `cd packages/infra && pulumi stack ls`
837
+ 3. **Document customizations** - List any modifications to the default Pulumi program
838
+
839
+ ### Migration Steps
840
+
841
+ #### Step 1: Check Current State
842
+
843
+ ```bash
844
+ cd packages/infra
845
+ pulumi stack ls
846
+ pulumi stack output --json > ../outputs-backup.json
847
+ ```
848
+
849
+ #### Step 2: Install the Provider Package
850
+
851
+ ```bash
852
+ bun add -D @kuckit/infra-gcp
853
+ ```
854
+
855
+ #### Step 3: Initialize with Existing Stack
856
+
857
+ The CLI will detect your existing `.kuckit/infra.json` and migrate it:
858
+
859
+ ```bash
860
+ bunx kuckit infra init --provider gcp
861
+ ```
862
+
863
+ If you have customizations you want to keep, use the eject command after migration:
864
+
865
+ ```bash
866
+ bunx kuckit infra eject
867
+ ```
868
+
869
+ This copies the provider's Pulumi code to `infra/` where you can customize it.
870
+
871
+ #### Step 4: Verify Configuration
872
+
873
+ Check that `.kuckit/infra.json` contains the correct values:
874
+
875
+ ```json
876
+ {
877
+ "provider": "gcp",
878
+ "providerPackage": "@kuckit/infra-gcp",
879
+ "region": "us-central1",
880
+ "env": "dev",
881
+ "providerConfig": {
882
+ "gcpProject": "your-project-id"
883
+ },
884
+ "outputs": {
885
+ "registryUrl": "...",
886
+ "databaseConnectionName": "..."
887
+ }
888
+ }
889
+ ```
890
+
891
+ #### Step 5: Test Deployment
892
+
893
+ Run a preview to verify everything works:
894
+
895
+ ```bash
896
+ bunx kuckit infra deploy --preview
897
+ ```
898
+
899
+ If the preview looks correct, deploy:
900
+
901
+ ```bash
902
+ bunx kuckit infra deploy
903
+ ```
904
+
905
+ #### Step 6: Clean Up Legacy Directory
906
+
907
+ Once verified, you can remove the old infrastructure code:
908
+
909
+ ```bash
910
+ rm -rf packages/infra
911
+ ```
912
+
913
+ Update `package.json` to remove the workspace entry if applicable.
914
+
915
+ ### Handling Customizations
916
+
917
+ If you had custom Pulumi code in `packages/infra`:
918
+
919
+ #### Option 1: Eject and Customize
920
+
921
+ ```bash
922
+ # Eject provider code to local directory
923
+ bunx kuckit infra eject
924
+
925
+ # Your customizations go in infra/
926
+ # CLI will use local infra/ instead of node_modules provider
927
+ ```
928
+
929
+ #### Option 2: Create Custom Provider
930
+
931
+ For significant customizations, create your own provider package:
932
+
933
+ ```bash
934
+ # Copy @kuckit/infra-gcp as starting point
935
+ cp -r node_modules/@kuckit/infra-gcp packages/my-infra-provider
936
+
937
+ # Customize as needed
938
+ # Update .kuckit/infra.json to use your provider
939
+ ```
940
+
941
+ ### Troubleshooting
942
+
943
+ #### "Pulumi stack already exists"
944
+
945
+ The CLI reuses existing Pulumi stacks. If you see conflicts:
946
+
947
+ ```bash
948
+ cd packages/infra
949
+ pulumi stack select your-stack-name
950
+ pulumi stack export > stack-backup.json
951
+
952
+ # Then continue with migration
953
+ bunx kuckit infra init --provider gcp
954
+ ```
955
+
956
+ #### "Missing outputs after migration"
957
+
958
+ Run a deployment to regenerate outputs:
959
+
960
+ ```bash
961
+ bunx kuckit infra deploy
962
+ ```
963
+
964
+ #### "My customizations are lost"
965
+
966
+ Use `kuckit infra eject` to get a local copy of the infrastructure code, then reapply your customizations.
967
+
968
+ ### Legacy Command Compatibility
969
+
970
+ Some commands still support legacy `packages/infra` paths as a fallback:
971
+
972
+ | Command | Provider-based | Legacy fallback |
973
+ | --------------- | -------------- | --------------- |
974
+ | `infra up` | ✅ Yes | ❌ No |
975
+ | `infra init` | ✅ Yes | ❌ No |
976
+ | `infra deploy` | ✅ Yes | ❌ No |
977
+ | `infra destroy` | ⚠️ Partial | ✅ Yes |
978
+ | `infra status` | ⚠️ Partial | ✅ Yes |
979
+ | `infra outputs` | ⚠️ Partial | ✅ Yes |
980
+
981
+ Commands marked "Partial" will be updated in a future release to fully support the provider interface.
982
+
983
+ ### Getting Help
984
+
985
+ If you encounter issues during migration:
986
+
987
+ 1. Check the [Troubleshooting Guide](./TROUBLESHOOTING.md)
988
+ 2. Open an issue on [GitHub](https://github.com/draphonix/kuckit/issues)
989
+ 3. Include your `.kuckit/infra.json` and any error messages