create-kuckit-app 0.3.4 → 0.4.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 (42) hide show
  1. package/dist/bin.js +1 -1
  2. package/dist/{create-project-CP-h4Ygi.js → create-project-geQBZ0Ru.js} +5 -0
  3. package/dist/index.js +1 -1
  4. package/package.json +1 -1
  5. package/templates/base/.claude/skills/kuckit/SKILL.md +22 -2
  6. package/templates/base/.claude/skills/kuckit/references/MODULE-DEVELOPMENT.md +39 -28
  7. package/templates/base/.claude/skills/kuckit/references/PACKAGES.md +94 -74
  8. package/templates/base/AGENTS.md +86 -15
  9. package/templates/base/apps/server/AGENTS.md +35 -10
  10. package/templates/base/apps/server/package.json +7 -7
  11. package/templates/base/apps/server/src/auth.ts +1 -1
  12. package/templates/base/apps/server/src/config/modules.ts +7 -8
  13. package/templates/base/apps/server/src/container.ts +3 -1
  14. package/templates/base/apps/server/src/module-rest-routes.ts +47 -0
  15. package/templates/base/apps/server/src/rest-router-registry.ts +32 -0
  16. package/templates/base/apps/server/src/rpc.ts +1 -1
  17. package/templates/base/apps/server/src/server.ts +2 -0
  18. package/templates/base/apps/server/tsdown.config.ts +8 -0
  19. package/templates/base/apps/web/package.json +9 -9
  20. package/templates/base/apps/web/src/services/auth-client.ts +1 -1
  21. package/templates/base/{packages/db/src/migrations → drizzle}/0000_init.sql +35 -30
  22. package/templates/base/{packages/db/src/migrations → drizzle}/meta/_journal.json +1 -1
  23. package/templates/base/drizzle.config.ts +38 -0
  24. package/templates/base/package.json +14 -9
  25. package/templates/base/packages/items-module/package.json +7 -7
  26. package/templates/base/packages/items-module/src/api/items.router.ts +1 -1
  27. package/templates/base/packages/api/AGENTS.md +0 -66
  28. package/templates/base/packages/api/package.json +0 -35
  29. package/templates/base/packages/api/src/context.ts +0 -48
  30. package/templates/base/packages/api/src/index.ts +0 -22
  31. package/templates/base/packages/api/tsconfig.json +0 -8
  32. package/templates/base/packages/auth/AGENTS.md +0 -61
  33. package/templates/base/packages/auth/package.json +0 -27
  34. package/templates/base/packages/auth/src/index.ts +0 -22
  35. package/templates/base/packages/auth/tsconfig.json +0 -8
  36. package/templates/base/packages/db/AGENTS.md +0 -74
  37. package/templates/base/packages/db/drizzle.config.ts +0 -19
  38. package/templates/base/packages/db/package.json +0 -36
  39. package/templates/base/packages/db/src/connection.ts +0 -40
  40. package/templates/base/packages/db/src/index.ts +0 -4
  41. package/templates/base/packages/db/src/schema/auth.ts +0 -51
  42. package/templates/base/packages/db/tsconfig.json +0 -8
package/dist/bin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as createProject } from "./create-project-CP-h4Ygi.js";
2
+ import { t as createProject } from "./create-project-geQBZ0Ru.js";
3
3
  import { program } from "commander";
4
4
  import { join } from "node:path";
5
5
  import { existsSync, readFileSync } from "node:fs";
@@ -73,6 +73,11 @@ Next steps:
73
73
  bun run db:migrate # Run database migrations
74
74
  bun run dev # Start development server
75
75
 
76
+ Deploy to GCP:
77
+
78
+ bun add -D @kuckit/infra-gcp
79
+ bunx kuckit infra up # One-command deploy
80
+
76
81
  Inside that directory, you can run:
77
82
 
78
83
  bun run dev Start the development server
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { t as createProject } from "./create-project-CP-h4Ygi.js";
1
+ import { t as createProject } from "./create-project-geQBZ0Ru.js";
2
2
 
3
3
  export { createProject };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-kuckit-app",
3
- "version": "0.3.4",
3
+ "version": "0.4.0",
4
4
  "description": "Create a new Kuckit application",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -193,14 +193,34 @@ export const kuckitClientModule = defineKuckitClientModule({
193
193
 
194
194
  ### Module package.json Metadata
195
195
 
196
+ Modules depend on `@kuckit/*` npm packages:
197
+
196
198
  ```json
197
199
  {
198
200
  "name": "@acme/billing-module",
201
+ "version": "0.1.0",
202
+ "type": "module",
203
+ "exports": {
204
+ ".": "./src/index.ts",
205
+ "./client": "./src/client-module.ts"
206
+ },
207
+ "peerDependencies": {
208
+ "@kuckit/sdk": "^1.0.0",
209
+ "@kuckit/sdk-react": "^1.0.0",
210
+ "typescript": "^5"
211
+ },
212
+ "dependencies": {
213
+ "@kuckit/api": "^1.0.0",
214
+ "@orpc/server": "^1.10.0",
215
+ "@orpc/zod": "^1.10.0",
216
+ "drizzle-orm": "^0.44.0",
217
+ "zod": "^3.23.0",
218
+ "react": "^19.0.0"
219
+ },
199
220
  "kuckit": {
200
221
  "id": "acme.billing",
201
222
  "server": "./dist/module.js",
202
- "client": "./dist/client/module.js",
203
- "schema": "./src/server/schema/index.ts"
223
+ "client": "./dist/client-module.js"
204
224
  }
205
225
  }
206
226
  ```
@@ -6,50 +6,61 @@ Complete guide for developing Kuckit modules.
6
6
 
7
7
  ### Generated Module Layout
8
8
 
9
+ Modules follow Clean Architecture internally with all layers self-contained:
10
+
9
11
  ```
10
12
  packages/billing-module/
11
13
  ├── src/
12
- │ ├── module.ts # Server module definition
13
- ├── index.ts # Public exports
14
- │ ├── client/
15
- │ │ ├── module.ts # Client module definition
16
- │ └── index.ts # Client exports
17
- │ └── server/
18
- ├── schema/
19
- └── index.ts # Drizzle schema
20
- ├── repositories/
21
- └── invoice.ts # Repository implementations
22
- └── use-cases/
23
- └── create-invoice.ts
24
- ├── package.json
14
+ │ ├── domain/
15
+ │ └── billing.entity.ts # Zod schema for entity
16
+ │ ├── ports/
17
+ │ │ └── billing.repository.ts # Repository interface
18
+ ├── adapters/
19
+ └── billing.drizzle.ts # Drizzle implementation
20
+ ├── usecases/
21
+ ├── list-billings.ts
22
+ ├── get-billing.ts
23
+ ├── create-billing.ts
24
+ └── delete-billing.ts
25
+ ├── api/
26
+ │ │ └── billings.router.ts # oRPC router
27
+ │ ├── ui/
28
+ │ │ └── BillingsPage.tsx # React component
29
+ │ ├── module.ts # Server module
30
+ │ ├── client-module.ts # Client module
31
+ │ └── index.ts
32
+ ├── package.json # Uses @kuckit/* from npm
25
33
  └── tsconfig.json
26
34
  ```
27
35
 
28
36
  ### package.json Metadata
29
37
 
38
+ Modules depend on `@kuckit/*` npm packages:
39
+
30
40
  ```json
31
41
  {
32
42
  "name": "@acme/billing-module",
33
43
  "version": "1.0.0",
34
44
  "type": "module",
35
- "kuckit": {
36
- "id": "acme.billing",
37
- "server": "./dist/module.js",
38
- "client": "./dist/client/module.js",
39
- "schema": "./src/server/schema/index.ts"
40
- },
41
45
  "exports": {
42
- ".": {
43
- "import": "./dist/index.js",
44
- "types": "./dist/index.d.ts"
45
- },
46
- "./client": {
47
- "import": "./dist/client/index.js",
48
- "types": "./dist/client/index.d.ts"
49
- }
46
+ ".": "./src/index.ts",
47
+ "./client": "./src/client-module.ts"
50
48
  },
51
49
  "peerDependencies": {
52
- "@kuckit/sdk": ">=0.1.0"
50
+ "@kuckit/sdk": "^1.0.0",
51
+ "@kuckit/sdk-react": "^1.0.0",
52
+ "typescript": "^5"
53
+ },
54
+ "dependencies": {
55
+ "@kuckit/api": "^1.0.0",
56
+ "@orpc/server": "^1.10.0",
57
+ "drizzle-orm": "^0.44.0",
58
+ "zod": "^3.23.0"
59
+ },
60
+ "kuckit": {
61
+ "id": "acme.billing",
62
+ "server": "./dist/module.js",
63
+ "client": "./dist/client-module.js"
53
64
  }
54
65
  }
55
66
  ```
@@ -1,67 +1,82 @@
1
1
  # Kuckit Package Reference
2
2
 
3
- Quick reference for all packages in the Kuckit monorepo.
4
-
5
- ## Package Locations
6
-
7
- | Package | Path | Description |
8
- | ----------------------- | -------------------------------------------------------------------- | ------------------------------------ |
9
- | @kuckit/sdk | `/Users/themrb/Documents/personal/kuckit/packages/sdk` | Backend DI container & module system |
10
- | @kuckit/sdk-react | `/Users/themrb/Documents/personal/kuckit/packages/sdk-react` | Frontend module system |
11
- | @kuckit/cli | `/Users/themrb/Documents/personal/kuckit/packages/kuckit-cli` | CLI tooling |
12
- | create-kuckit-app | `/Users/themrb/Documents/personal/kuckit/packages/create-kuckit-app` | Project scaffolding |
13
- | @kuckit/domain | `/Users/themrb/Documents/personal/kuckit/packages/domain` | Business entities |
14
- | @kuckit/application | `/Users/themrb/Documents/personal/kuckit/packages/application` | Use cases |
15
- | @kuckit/contracts | `/Users/themrb/Documents/personal/kuckit/packages/contracts` | DTOs & Zod schemas |
16
- | @kuckit/infrastructure | `/Users/themrb/Documents/personal/kuckit/packages/infrastructure` | Repository implementations |
17
- | @kuckit/api | `/Users/themrb/Documents/personal/kuckit/packages/api` | oRPC procedures |
18
- | @kuckit/db | `/Users/themrb/Documents/personal/kuckit/packages/db` | Drizzle ORM schemas |
19
- | @kuckit/auth | `/Users/themrb/Documents/personal/kuckit/packages/auth` | Better-Auth config |
20
- | @kuckit/infra | `/Users/themrb/Documents/personal/kuckit/packages/infra` | Pulumi infrastructure |
21
- | @kuckit/users-module | `/Users/themrb/Documents/personal/kuckit/packages/users-module` | Reference module |
22
- | @kuckit/landing-module | `/Users/themrb/Documents/personal/kuckit/packages/landing-module` | Landing page module |
23
- | @kuckit/cli-auth-module | `/Users/themrb/Documents/personal/kuckit/packages/cli-auth-module` | CLI auth module |
24
-
25
- ## Key Files Per Package
3
+ Quick reference for all `@kuckit/*` packages from npm.
4
+
5
+ ## Framework Packages
6
+
7
+ These are installed from npm as dependencies, not copied into your project:
8
+
9
+ | Package | Description |
10
+ | ------------------- | ------------------------------------------------------ |
11
+ | `@kuckit/sdk` | Server-side module system, DI container, core services |
12
+ | `@kuckit/sdk-react` | Client-side module system, hooks, providers |
13
+ | `@kuckit/api` | oRPC procedures (publicProcedure, protectedProcedure) |
14
+ | `@kuckit/db` | Drizzle ORM utilities and connection |
15
+ | `@kuckit/auth` | Better-Auth configuration |
16
+ | `@kuckit/domain` | Base types, Logger, Clock interfaces |
17
+ | `@kuckit/contracts` | Shared DTOs and Zod schemas |
18
+
19
+ ## Your Project Structure
20
+
21
+ ```
22
+ your-app/
23
+ ├── apps/
24
+ │ ├── server/ # Express bootstrap (imports @kuckit/* from npm)
25
+ │ └── web/ # React bootstrap (imports @kuckit/* from npm)
26
+ ├── packages/
27
+ │ └── your-module/ # Your modules with Clean Architecture
28
+ ├── node_modules/
29
+ │ └── @kuckit/ # Framework packages from npm
30
+ ├── package.json # Lists @kuckit/* deps
31
+ └── drizzle.config.ts # Points to @kuckit/db + module schemas
32
+ ```
33
+
34
+ ## Key Files Per Framework Package
26
35
 
27
36
  ### @kuckit/sdk
28
37
 
29
- | File | Purpose |
30
- | ------------------------------ | ----------------------------- |
31
- | `src/index.ts` | Public exports |
32
- | `src/core/container.ts` | DI container creation |
33
- | `src/core/core.module.ts` | Core services registration |
34
- | `src/modules/define-module.ts` | `defineKuckitModule()` helper |
35
- | `src/modules/loader.ts` | Module loading logic |
36
- | `src/modules/types.ts` | Module type definitions |
37
- | `src/config/loader.ts` | Configuration loading |
38
- | `src/schema/registry.ts` | Schema registry |
39
-
40
- ### @kuckit/cli
41
-
42
- | File | Purpose |
43
- | --------------------------------- | ------------------------------ |
44
- | `src/bin.ts` | CLI entry point (Commander.js) |
45
- | `src/commands/generate-module.ts` | Module scaffolding |
46
- | `src/commands/add-module.ts` | Module installation |
47
- | `src/commands/discover-module.ts` | Module discovery |
48
- | `src/commands/doctor.ts` | Project validation |
49
- | `src/commands/auth.ts` | Authentication commands |
50
- | `src/commands/db.ts` | Database commands |
51
- | `src/commands/infra/*.ts` | Infrastructure commands |
52
- | `src/lib/credentials.ts` | Token storage |
53
- | `src/lib/sdk-loader.ts` | Dynamic SDK loading |
38
+ | Export | Purpose |
39
+ | ----------------------- | ------------------------ |
40
+ | `createKuckitContainer` | DI container creation |
41
+ | `loadKuckitModules` | Module loading |
42
+ | `defineKuckitModule` | Server module definition |
43
+ | `disposeContainer` | Container cleanup |
44
+ | `asClass`, `asFunction` | DI registration helpers |
45
+ | `asValue` | DI value registration |
54
46
 
55
47
  ### @kuckit/sdk-react
56
48
 
57
- | File | Purpose |
58
- | ------------------------------------- | ------------------------ |
59
- | `src/modules/define-client-module.ts` | Client module definition |
60
- | `src/modules/loader.ts` | Client module loading |
61
- | `src/registries/route-registry.ts` | Route management |
62
- | `src/registries/nav-registry.ts` | Navigation management |
63
- | `src/registries/slot-registry.ts` | UI slot management |
64
- | `src/context/*.ts` | React context providers |
49
+ | Export | Purpose |
50
+ | -------------------------- | ------------------------ |
51
+ | `defineKuckitClientModule` | Client module definition |
52
+ | `loadKuckitClientModules` | Client module loading |
53
+ | `KuckitNavProvider` | Navigation provider |
54
+ | `useKuckitNav` | Navigation hook |
55
+ | `useRpc` | RPC client hook |
56
+
57
+ ### @kuckit/api
58
+
59
+ | Export | Purpose |
60
+ | -------------------- | ----------------------- |
61
+ | `publicProcedure` | Public oRPC procedure |
62
+ | `protectedProcedure` | Auth-required procedure |
63
+ | `createContext` | oRPC context factory |
64
+ | `appRouter` | Base app router |
65
+
66
+ ### @kuckit/db
67
+
68
+ | Export | Purpose |
69
+ | ------------ | -------------------------- |
70
+ | `createDb` | Drizzle instance factory |
71
+ | `createPool` | PostgreSQL pool factory |
72
+ | `authSchema` | Better-Auth schema exports |
73
+
74
+ ### @kuckit/auth
75
+
76
+ | Export | Purpose |
77
+ | ------------ | --------------------- |
78
+ | `auth` | Better-Auth instance |
79
+ | `authClient` | Client auth utilities |
65
80
 
66
81
  ## Import Patterns
67
82
 
@@ -83,30 +98,35 @@ import {
83
98
  loadKuckitClientModules,
84
99
  KuckitNavProvider,
85
100
  useKuckitNav,
101
+ useRpc,
86
102
  } from '@kuckit/sdk-react'
87
103
 
88
- // CLI programmatic usage
89
- import { generateModule, addModule, discoverModules } from '@kuckit/cli'
104
+ // API imports (for modules)
105
+ import { protectedProcedure, publicProcedure } from '@kuckit/api'
90
106
 
91
- // Domain imports (from within the monorepo)
92
- import { User, type UserPort } from '@kuckit/domain'
93
-
94
- // Contracts imports
95
- import { CreateUserInput, UserDTO, createUserSchema } from '@kuckit/contracts'
107
+ // Database imports
108
+ import { createDb, createPool } from '@kuckit/db/connection'
96
109
  ```
97
110
 
98
111
  ## Package Dependencies
99
112
 
100
113
  ### What Each Package Can Import
101
114
 
102
- | Package | Allowed Imports |
103
- | -------------- | ------------------------------ |
104
- | domain | (none - pure business logic) |
105
- | contracts | zod |
106
- | application | domain |
107
- | infrastructure | domain, external libs |
108
- | api | domain, application, contracts |
109
- | sdk | all core packages, awilix |
110
- | sdk-react | sdk types |
111
- | server | ALL packages |
112
- | web | sdk-react, contracts |
115
+ | Package | Allowed Imports |
116
+ | ------------ | ------------------------------- |
117
+ | Your modules | @kuckit/\* packages, zod |
118
+ | apps/server | @kuckit/\*, your modules |
119
+ | apps/web | @kuckit/sdk-react, your modules |
120
+
121
+ ### Module Internal Layers
122
+
123
+ Within your modules, follow Clean Architecture:
124
+
125
+ | Layer | Can Import |
126
+ | -------- | ----------------------------- |
127
+ | domain | (none - pure Zod schemas) |
128
+ | ports | domain |
129
+ | usecases | domain, ports |
130
+ | adapters | domain, drizzle-orm |
131
+ | api | domain, usecases, @kuckit/api |
132
+ | ui | @kuckit/sdk-react, react |
@@ -5,7 +5,7 @@
5
5
  ```bash
6
6
  bun install # Install dependencies
7
7
  docker compose up -d # Start PostgreSQL
8
- bun run db:migrate # Run database migrations
8
+ bun run db:push # Sync schema to database (dev) or db:migrate (prod)
9
9
  bun run dev # Start dev servers (web + server)
10
10
  ```
11
11
 
@@ -17,15 +17,15 @@ __APP_NAME_KEBAB__/
17
17
  │ ├── server/ # Express + oRPC backend (port 3000)
18
18
  │ └── web/ # React + TanStack Router frontend (port 3001)
19
19
  ├── packages/
20
- │ ├── api/ # Shared API context and types
21
- │ ├── auth/ # Better-Auth configuration
22
- │ ├── db/ # Drizzle ORM, migrations, schema
23
20
  │ └── items-module/ # Example Kuckit module (reference implementation)
24
21
  ├── .env.example # Environment template
25
22
  ├── docker-compose.yml # PostgreSQL container
23
+ ├── drizzle.config.ts # Drizzle pointing to @kuckit/db + module schemas
26
24
  └── turbo.json # Turborepo configuration
27
25
  ```
28
26
 
27
+ **Note:** Core packages (`api`, `auth`, `db`, `domain`, `contracts`) are installed from npm as `@kuckit/*` dependencies, not copied into your project.
28
+
29
29
  ## Module Development
30
30
 
31
31
  Kuckit uses a **module-based architecture** where each module contains its own Clean Architecture layers internally.
@@ -47,15 +47,21 @@ packages/your-module/
47
47
 
48
48
  ### Creating a New Module
49
49
 
50
- 1. Copy `packages/items-module` as a template
51
- 2. Rename and update `package.json`
52
- 3. Implement your domain entities in `domain/`
53
- 4. Define repository interfaces in `ports/`
54
- 5. Implement adapters in `adapters/`
55
- 6. Create use cases in `usecases/`
56
- 7. Expose API in `api/` via oRPC router
57
- 8. Register module in `apps/server/src/config/modules.ts`
58
- 9. Add client module to `apps/web/src/modules.client.ts`
50
+ ```bash
51
+ bunx kuckit generate module your-module
52
+ ```
53
+
54
+ This scaffolds a full Clean Architecture module. Then:
55
+
56
+ 1. Implement your domain entities in `domain/`
57
+ 2. Define repository interfaces in `ports/`
58
+ 3. Implement adapters in `adapters/`
59
+ 4. Create use cases in `usecases/`
60
+ 5. Expose API in `api/` via oRPC router
61
+ 6. Register module in `apps/server/src/config/modules.ts`
62
+ 7. Add client module to `apps/web/src/modules.client.ts`
63
+ 8. Add schema path to `drizzle.config.ts` in project root
64
+ 9. Run `bun run db:push` to create the table
59
65
 
60
66
  ### Dependency Rules
61
67
 
@@ -256,6 +262,26 @@ export const wireModuleRpcRouters = (registrations: ApiRegistration[]) => {
256
262
  }
257
263
  ```
258
264
 
265
+ ### REST Router Pattern
266
+
267
+ For modules that need direct Express response access (e.g., AI streaming with `pipeUIMessageStreamToResponse`), use REST routers instead of oRPC:
268
+
269
+ ```typescript
270
+ // In your module's registerApi()
271
+ ctx.addApiRegistration({
272
+ type: 'rest-router',
273
+ name: 'ai',
274
+ router: createAiRouter(),
275
+ prefix: '/ai', // Optional, defaults to /<name>
276
+ })
277
+ ```
278
+
279
+ REST routers are mounted at `/api<prefix>` (e.g., `/api/ai/chat`). They receive:
280
+
281
+ - Per-request scoped container via `req.scope`
282
+ - Session via `req.scope.cradle.session`
283
+ - Full Express `Request` and `Response` objects
284
+
259
285
  ### Typing DI in Routers
260
286
 
261
287
  Use a module-local interface to type `context.di.cradle`:
@@ -284,14 +310,14 @@ export const invoicesRouter = {
284
310
 
285
311
  ### Add a new database table
286
312
 
287
- 1. Define schema in your module's `adapters/` or `packages/db/src/schema/`
313
+ 1. Define schema in your module's `adapters/` directory
288
314
  2. Run `bun run db:generate`
289
315
  3. Run `bun run db:migrate`
290
316
 
291
317
  ### Add authentication to an endpoint
292
318
 
293
319
  ```typescript
294
- import { protectedProcedure } from '@__APP_NAME_KEBAB__/api'
320
+ import { protectedProcedure } from '@kuckit/api'
295
321
 
296
322
  export const myRouter = {
297
323
  protectedRoute: protectedProcedure.input(mySchema).handler(async ({ input, context }) => {
@@ -342,6 +368,51 @@ See `.env.example` for required variables:
342
368
  - `PORT` - Server port (default: 3000)
343
369
  - `VITE_API_URL` - API URL for frontend
344
370
 
371
+ ## Troubleshooting
372
+
373
+ ### 404 Errors on API Calls
374
+
375
+ **Symptom**: `POST /rpc/items/list 404 (Not Found)` with multiple retries
376
+
377
+ **Cause**: Server and client modules are out of sync. The client has a module registered but the server doesn't.
378
+
379
+ **Fix**: Ensure both files register the same modules:
380
+
381
+ - `apps/server/src/config/modules.ts` - Server modules
382
+ - `apps/web/src/modules.client.ts` - Client modules
383
+
384
+ **Prevention**: Run `bunx kuckit doctor` to detect mismatches.
385
+
386
+ ### "Relation does not exist" Database Errors
387
+
388
+ **Symptom**: `error: relation "items" does not exist`
389
+
390
+ **Cause**: Module schema not registered in `drizzle.config.ts`.
391
+
392
+ **Fix**: Add the module's schema path to `drizzle.config.ts` (in project root):
393
+
394
+ ```typescript
395
+ schema: [
396
+ './node_modules/@kuckit/db/dist/schema/auth.js',
397
+ './packages/your-module/src/adapters',
398
+ ],
399
+ ```
400
+
401
+ Then run:
402
+
403
+ ```bash
404
+ bun run db:generate
405
+ bun run db:migrate
406
+ ```
407
+
408
+ ### Module Not Appearing in Navigation
409
+
410
+ **Symptom**: Module pages work but nav items don't show.
411
+
412
+ **Cause**: Client module not registered or missing `navItems`.
413
+
414
+ **Fix**: Verify module is in `apps/web/src/modules.client.ts` and defines `navItems` in `defineKuckitClientModule()`.
415
+
345
416
  ## Related Documentation
346
417
 
347
418
  - [Kuckit SDK](https://github.com/draphonix/kuckit)
@@ -8,14 +8,16 @@ Express backend hosting oRPC API, Better-Auth authentication, and the Kuckit mod
8
8
 
9
9
  ## Key Files
10
10
 
11
- | File | Purpose |
12
- | ------------------------ | -------------------------- |
13
- | `server.ts` | Entry point, bootstrap |
14
- | `container.ts` | DI container setup |
15
- | `config/modules.ts` | Module registration |
16
- | `rpc.ts` | oRPC handler setup |
17
- | `rpc-router-registry.ts` | Mutable router for modules |
18
- | `auth.ts` | Better-Auth configuration |
11
+ | File | Purpose |
12
+ | ------------------------- | -------------------------- |
13
+ | `server.ts` | Entry point, bootstrap |
14
+ | `container.ts` | DI container setup |
15
+ | `config/modules.ts` | Module registration |
16
+ | `rpc.ts` | oRPC handler setup |
17
+ | `rpc-router-registry.ts` | Mutable router for modules |
18
+ | `rest-router-registry.ts` | REST router collection |
19
+ | `module-rest-routes.ts` | REST router wiring |
20
+ | `auth.ts` | Better-Auth configuration |
19
21
 
20
22
  ## Module Loading Sequence
21
23
 
@@ -26,10 +28,11 @@ The server bootstraps in this order:
26
28
  2. loadKuckitModules() with onApiRegistrations callback:
27
29
  ├─► register() hooks run (DI bindings)
28
30
  ├─► registerApi() hooks run (routers collected)
29
- ├─► onApiRegistrations() - Wire routers to rootRpcRouter
31
+ ├─► onApiRegistrations() - Wire RPC and REST routers
30
32
  └─► onBootstrap() hooks run (startup logic)
31
33
  3. setupRPC() - Create RPCHandler AFTER modules loaded
32
- 4. Express listens
34
+ 4. setupModuleRestRouters() - Mount REST routers to Express
35
+ 5. Express listens
33
36
  ```
34
37
 
35
38
  ## Router Registry Pattern
@@ -56,12 +59,34 @@ await loadKuckitModules({
56
59
  modules: getModuleSpecs(),
57
60
  onApiRegistrations: (registrations) => {
58
61
  wireModuleRpcRouters(registrations) // Wire BEFORE setupRPC()
62
+ collectModuleRestRouters(registrations) // Collect REST routers
59
63
  },
60
64
  })
61
65
 
62
66
  setupRPC(app) // Now create handler with fully-wired router
67
+ setupModuleRestRouters(app) // Mount REST routers at /api/<name>
63
68
  ```
64
69
 
70
+ ## REST Router Pattern
71
+
72
+ For modules that need direct Express response access (e.g., AI streaming), use REST routers:
73
+
74
+ ```typescript
75
+ // In your module's registerApi()
76
+ ctx.addApiRegistration({
77
+ type: 'rest-router',
78
+ name: 'ai',
79
+ router: createAiRouter(),
80
+ prefix: '/ai', // Optional, defaults to /<name>
81
+ })
82
+ ```
83
+
84
+ REST routers are mounted at `/api<prefix>` (e.g., `/api/ai/chat`). They receive:
85
+
86
+ - Per-request scoped container via `req.scope`
87
+ - Session via `req.scope.cradle.session`
88
+ - Full Express `Request` and `Response` objects
89
+
65
90
  ## Per-Request Scoping
66
91
 
67
92
  Each HTTP request gets a scoped container with:
@@ -10,17 +10,17 @@
10
10
  "dependencies": {
11
11
  "express": "^5.1.0",
12
12
  "cors": "^2.8.5",
13
- "dotenv": "^17.2.2",
13
+ "dotenv": "^17.0.0",
14
14
  "awilix": "^12.0.5",
15
15
  "pg": "^8.14.1",
16
16
  "@orpc/server": "^1.10.0",
17
17
  "@orpc/zod": "^1.10.0",
18
- "better-auth": "^1.3.28",
19
- "zod": "^4.1.11",
20
- "@kuckit/sdk": "^1.0.0",
21
- "@__APP_NAME_KEBAB__/api": "workspace:*",
22
- "@__APP_NAME_KEBAB__/auth": "workspace:*",
23
- "@__APP_NAME_KEBAB__/db": "workspace:*"
18
+ "better-auth": "^1.3.0",
19
+ "zod": "^3.23.0",
20
+ "@kuckit/sdk": "^2.0.0",
21
+ "@kuckit/api": "^2.0.0",
22
+ "@kuckit/auth": "^2.0.0",
23
+ "@kuckit/db": "^2.0.0"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@types/express": "^5.0.1",
@@ -1,4 +1,4 @@
1
- import { auth } from '@__APP_NAME_KEBAB__/auth'
1
+ import { auth } from '@kuckit/auth'
2
2
  import { toNodeHandler } from 'better-auth/node'
3
3
  import type { Express } from 'express'
4
4
 
@@ -1,21 +1,20 @@
1
1
  import type { ModuleSpec } from '@kuckit/sdk'
2
-
3
- // Import your modules here
4
- // import { kuckitModule as itemsModule } from '@__APP_NAME_KEBAB__/items-module'
2
+ import { kuckitModule as itemsModule } from '@__APP_NAME_KEBAB__/items-module'
5
3
 
6
4
  /**
7
5
  * Module specifications for the server application
8
6
  *
9
7
  * Add modules here to configure the server's functionality.
10
8
  * Modules are loaded in order, with dependencies resolved automatically.
9
+ *
10
+ * IMPORTANT: Server and client modules must be kept in sync!
11
+ * If you add/remove a module here, also update apps/web/src/modules.client.ts
11
12
  */
12
13
  export const getModuleSpecs = (): ModuleSpec[] => {
13
14
  const modules: ModuleSpec[] = [
14
- // Add your modules here:
15
- // {
16
- // module: itemsModule,
17
- // config: { ... },
18
- // },
15
+ // KUCKIT_SERVER_MODULES_START
16
+ { module: itemsModule },
17
+ // KUCKIT_SERVER_MODULES_END
19
18
  ]
20
19
 
21
20
  return modules