create-turbo-mono 1.0.7 → 1.0.9

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.
@@ -4,7 +4,8 @@
4
4
  "Bash(npm view:*)",
5
5
  "Bash(python3:*)",
6
6
  "Bash(npm install:*)",
7
- "Bash(npm run build:*)"
7
+ "Bash(npm run build:*)",
8
+ "Bash(npm publish:*)"
8
9
  ]
9
10
  }
10
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC1E"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC1E"}
package/dist/scaffold.js CHANGED
@@ -13,6 +13,7 @@ const shared_1 = require("./templates/shared");
13
13
  const docker_1 = require("./templates/docker");
14
14
  const cicd_1 = require("./templates/cicd");
15
15
  const docs_1 = require("./templates/docs");
16
+ const claude_1 = require("./templates/claude");
16
17
  async function scaffoldProject(config) {
17
18
  const { targetDir, backends, frontends } = config;
18
19
  // Create directory structure
@@ -38,5 +39,8 @@ async function scaffoldProject(config) {
38
39
  await (0, cicd_1.createCICDFiles)(config);
39
40
  // Create documentation
40
41
  await (0, docs_1.createDocumentation)(config);
42
+ // Create CLAUDE.md files (root + per-app + packages/) so Claude Code
43
+ // auto-loads project context every session.
44
+ await (0, claude_1.createClaudeFiles)(config);
41
45
  }
42
46
  //# sourceMappingURL=scaffold.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":";;;;;AAiBA,0CAiCC;AAlDD,wDAA0B;AAC1B,gDAAwB;AACxB,2CAAmD;AACnD,iDAAuD;AACvD,mDAAyD;AACzD,+CAA0D;AAC1D,+CAAuD;AACvD,2CAAmD;AACnD,2CAAuD;AAShD,KAAK,UAAU,eAAe,CAAC,MAAqB;IACzD,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAElD,6BAA6B;IAC7B,MAAM,kBAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,MAAM,kBAAE,CAAC,SAAS,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAC5D,MAAM,kBAAE,CAAC,SAAS,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC7D,MAAM,kBAAE,CAAC,SAAS,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAErD,kCAAkC;IAClC,MAAM,IAAA,sBAAe,EAAC,MAAM,CAAC,CAAC;IAE9B,sBAAsB;IACtB,KAAK,MAAM,WAAW,IAAI,QAAQ,EAAE,CAAC;QACnC,MAAM,IAAA,0BAAgB,EAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACjD,CAAC;IAED,uBAAuB;IACvB,KAAK,MAAM,YAAY,IAAI,SAAS,EAAE,CAAC;QACrC,MAAM,IAAA,4BAAiB,EAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACnD,CAAC;IAED,yBAAyB;IACzB,MAAM,IAAA,6BAAoB,EAAC,SAAS,CAAC,CAAC;IAEtC,sBAAsB;IACtB,MAAM,IAAA,0BAAiB,EAAC,MAAM,CAAC,CAAC;IAEhC,qBAAqB;IACrB,MAAM,IAAA,sBAAe,EAAC,MAAM,CAAC,CAAC;IAE9B,uBAAuB;IACvB,MAAM,IAAA,0BAAmB,EAAC,MAAM,CAAC,CAAC;AACpC,CAAC"}
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":";;;;;AAkBA,0CAqCC;AAvDD,wDAA0B;AAC1B,gDAAwB;AACxB,2CAAmD;AACnD,iDAAuD;AACvD,mDAAyD;AACzD,+CAA0D;AAC1D,+CAAuD;AACvD,2CAAmD;AACnD,2CAAuD;AACvD,+CAAuD;AAShD,KAAK,UAAU,eAAe,CAAC,MAAqB;IACzD,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAElD,6BAA6B;IAC7B,MAAM,kBAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,MAAM,kBAAE,CAAC,SAAS,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAC5D,MAAM,kBAAE,CAAC,SAAS,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC7D,MAAM,kBAAE,CAAC,SAAS,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAErD,kCAAkC;IAClC,MAAM,IAAA,sBAAe,EAAC,MAAM,CAAC,CAAC;IAE9B,sBAAsB;IACtB,KAAK,MAAM,WAAW,IAAI,QAAQ,EAAE,CAAC;QACnC,MAAM,IAAA,0BAAgB,EAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACjD,CAAC;IAED,uBAAuB;IACvB,KAAK,MAAM,YAAY,IAAI,SAAS,EAAE,CAAC;QACrC,MAAM,IAAA,4BAAiB,EAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACnD,CAAC;IAED,yBAAyB;IACzB,MAAM,IAAA,6BAAoB,EAAC,SAAS,CAAC,CAAC;IAEtC,sBAAsB;IACtB,MAAM,IAAA,0BAAiB,EAAC,MAAM,CAAC,CAAC;IAEhC,qBAAqB;IACrB,MAAM,IAAA,sBAAe,EAAC,MAAM,CAAC,CAAC;IAE9B,uBAAuB;IACvB,MAAM,IAAA,0BAAmB,EAAC,MAAM,CAAC,CAAC;IAElC,qEAAqE;IACrE,4CAA4C;IAC5C,MAAM,IAAA,0BAAiB,EAAC,MAAM,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { ProjectConfig } from '../scaffold';
2
+ export declare function createClaudeFiles(config: ProjectConfig): Promise<void>;
3
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/templates/claude.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAc5E"}
@@ -0,0 +1,318 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createClaudeFiles = createClaudeFiles;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ async function createClaudeFiles(config) {
10
+ const { targetDir, projectName, backends, frontends } = config;
11
+ await createRootClaudeMd(targetDir, projectName, backends, frontends);
12
+ for (const name of backends) {
13
+ await createBackendClaudeMd(targetDir, name);
14
+ }
15
+ for (const name of frontends) {
16
+ await createFrontendClaudeMd(targetDir, name);
17
+ }
18
+ await createSharedClaudeMd(targetDir);
19
+ }
20
+ async function createRootClaudeMd(targetDir, projectName, backends, frontends) {
21
+ const backendList = backends.length
22
+ ? backends.map((n, i) => ` - \`apps/backend/${n}\` — NestJS service (port ${4000 + i})`).join('\n')
23
+ : ' - _(none)_';
24
+ const frontendList = frontends.length
25
+ ? frontends.map((n, i) => ` - \`apps/frontend/${n}\` — Next.js app (port ${3000 + i})`).join('\n')
26
+ : ' - _(none)_';
27
+ const content = `# ${projectName}
28
+
29
+ > This file is auto-loaded by Claude Code at the start of every session.
30
+ > Keep it short, imperative, and pointed at where the truth lives in code.
31
+ > Long-form docs belong in \`docs/\` — link to them from here.
32
+
33
+ ## Project overview
34
+
35
+ ${projectName} is a Turborepo monorepo containing NestJS backends and Next.js frontends sharing
36
+ TypeScript packages, a single Prisma schema, and one Dockerfile with per-app build targets.
37
+
38
+ - Package manager: **pnpm** (workspaces). Never use \`npm\` or \`yarn\` in this repo.
39
+ - Build orchestrator: **Turborepo** (\`turbo.json\` defines the pipeline).
40
+ - Database: **PostgreSQL** via Prisma in \`packages/database\`.
41
+ - Cache/queues: **Redis**.
42
+
43
+ ## Repo map
44
+
45
+ \`\`\`
46
+ ${projectName}/
47
+ ├── apps/
48
+ │ ├── backend/ # NestJS services
49
+ ${backendList}
50
+ │ └── frontend/ # Next.js apps
51
+ ${frontendList}
52
+ ├── packages/
53
+ │ ├── database/ # Prisma schema, migrations, generated client
54
+ │ ├── shared-backend/ # Backend-only utilities (NestJS guards, pipes, types)
55
+ │ ├── shared-frontend/ # React components, hooks, client utilities
56
+ │ ├── shared-common/ # Isomorphic utilities (zod schemas, constants, types)
57
+ │ └── tsconfig/ # Shared tsconfig presets
58
+ ├── docs/ # Human docs — see @docs/ENVIRONMENT.md
59
+ └── Dockerfile # Multi-stage; one target per app
60
+ \`\`\`
61
+
62
+ ## Common commands
63
+
64
+ Run from the repo root unless noted.
65
+
66
+ \`\`\`bash
67
+ pnpm install # install all workspace deps
68
+ pnpm dev # turbo run dev — starts every app in watch mode
69
+ pnpm build # turbo run build — production builds
70
+ pnpm type-check # turbo run type-check
71
+ pnpm lint # turbo run lint
72
+
73
+ pnpm db:generate # regenerate Prisma client (run after schema changes)
74
+ pnpm db:migrate # prisma migrate dev — create + apply a new migration
75
+ pnpm db:studio # open Prisma Studio
76
+
77
+ # Run a single app
78
+ pnpm --filter <app-name> dev
79
+ pnpm --filter <app-name> build
80
+ \`\`\`
81
+
82
+ Docker (local infra only — Postgres + Redis):
83
+
84
+ \`\`\`bash
85
+ docker compose -f docker-compose.local.yml up -d
86
+ \`\`\`
87
+
88
+ Full stack in containers:
89
+
90
+ \`\`\`bash
91
+ docker compose -f docker-compose.dev.yml up --build
92
+ \`\`\`
93
+
94
+ ## Tech stack conventions
95
+
96
+ - **TypeScript strict mode** everywhere. No \`any\` without a comment explaining why.
97
+ - **ES modules**. Use \`import\`/\`export\`, not \`require\`.
98
+ - Path aliases resolve via \`@repo/*\` for workspace packages — import shared code as
99
+ \`import { x } from '@repo/shared-common'\`, never via relative \`../../packages/...\` paths.
100
+ - Validation at boundaries: **zod** schemas live in \`@repo/shared-common\` so frontend and
101
+ backend share one source of truth. Reuse them — do not redefine DTOs per app.
102
+ - Errors: throw typed errors from \`@repo/shared-backend\`. Don't throw raw \`Error\` strings
103
+ in HTTP paths.
104
+
105
+ ## Architecture rules
106
+
107
+ 1. **Database access only from backend apps.** Frontends call backend HTTP endpoints; they
108
+ never import \`@prisma/client\` or \`@repo/database\`.
109
+ 2. **Schema is one file.** \`packages/database/prisma/schema.prisma\` is the only Prisma
110
+ schema. Do not create per-app schemas.
111
+ 3. **No cross-app imports.** \`apps/backend/foo\` must not import from \`apps/backend/bar\`.
112
+ If two apps need the same code, lift it into \`packages/shared-*\`.
113
+ 4. **\`shared-frontend\` is React-only**, \`shared-backend\` is Node-only, \`shared-common\` is
114
+ isomorphic (no \`fs\`, no \`window\`). Pick the right one.
115
+ 5. Environment variables are read **once at startup** in a typed config module — not
116
+ sprinkled as \`process.env.X\` throughout business logic.
117
+
118
+ ## Adding things
119
+
120
+ - **New backend app** → \`apps/backend/<name>/\`, add a \`package.json\` named \`@app/<name>\`,
121
+ then add a Docker target in \`Dockerfile\` and services in the three compose files.
122
+ pnpm picks it up automatically via \`pnpm-workspace.yaml\`.
123
+ - **New frontend app** → same idea under \`apps/frontend/<name>/\`.
124
+ - **New shared package** → \`packages/<name>/\`, name it \`@repo/<name>\`, export a clean
125
+ public API from \`src/index.ts\`.
126
+ - **New env var** → add to \`.env.example\` AND document in [docs/ENVIRONMENT.md](docs/ENVIRONMENT.md).
127
+
128
+ ## Testing
129
+
130
+ - Unit tests live next to the code: \`foo.ts\` + \`foo.spec.ts\`.
131
+ - Integration tests that touch the DB use a real Postgres (the \`docker-compose.local.yml\`
132
+ one) — **do not mock Prisma**. Mocks have hidden divergence from real query behavior.
133
+ - Run a single app's tests: \`pnpm --filter <app-name> test\`.
134
+
135
+ ## Git & CI
136
+
137
+ - Default branch: \`main\`. Feature branches: \`feat/<short-name>\`, \`fix/<short-name>\`.
138
+ - Conventional commits (\`feat:\`, \`fix:\`, \`chore:\`, \`docs:\`, \`refactor:\`).
139
+ - CI runs \`type-check\`, \`lint\`, \`build\` on every PR (see \`.github/workflows/\`).
140
+ - **Never** commit \`.env\`, \`.env.local\`, \`*.pem\`, or anything under \`packages/database/prisma/migrations\`
141
+ that wasn't generated by \`pnpm db:migrate\`.
142
+
143
+ ## Don't
144
+
145
+ - Don't run \`npm install\` or \`yarn\` — use \`pnpm\`.
146
+ - Don't bypass Turbo by \`cd\`-ing into an app and running raw scripts unless debugging.
147
+ - Don't add a new top-level dependency to multiple apps individually — put it in the
148
+ appropriate \`packages/shared-*\` and re-export.
149
+ - Don't \`prisma db push\` against a shared/dev database — always go through \`prisma migrate\`.
150
+ - Don't edit generated files (\`packages/database/node_modules/.prisma\`, \`.next/\`, \`dist/\`).
151
+ - Don't skip git hooks (\`--no-verify\`) without an explicit reason in the commit body.
152
+
153
+ ## When you finish a task
154
+
155
+ 1. \`pnpm type-check && pnpm lint\` — both must pass.
156
+ 2. If you changed the Prisma schema: \`pnpm db:generate\` and create a migration.
157
+ 3. If you added an env var: update \`.env.example\` and \`docs/ENVIRONMENT.md\`.
158
+ 4. If you added/removed an app: update the Dockerfile and all three compose files.
159
+
160
+ ## Pointers
161
+
162
+ - Environment variables: @docs/ENVIRONMENT.md
163
+ - README (human-facing setup): @README.md
164
+ - Prisma schema: @packages/database/prisma/schema.prisma
165
+ - Turbo pipeline: @turbo.json
166
+
167
+ App-specific context lives in per-app \`CLAUDE.md\` files (e.g.
168
+ \`apps/backend/<name>/CLAUDE.md\`). Claude Code auto-discovers them when working inside
169
+ that subtree.
170
+ `;
171
+ await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'CLAUDE.md'), content);
172
+ }
173
+ async function createBackendClaudeMd(targetDir, name) {
174
+ const dir = path_1.default.join(targetDir, 'apps', 'backend', name);
175
+ await fs_extra_1.default.ensureDir(dir);
176
+ const content = `# ${name} (backend)
177
+
178
+ NestJS service. See the root [CLAUDE.md](../../../CLAUDE.md) for monorepo-wide rules;
179
+ this file only documents what is specific to \`${name}\`.
180
+
181
+ ## Layout
182
+
183
+ \`\`\`
184
+ src/
185
+ ├── main.ts # bootstrap — keep this minimal
186
+ ├── app.module.ts # root module
187
+ ├── modules/ # feature modules (one folder per domain concept)
188
+ │ └── <feature>/
189
+ │ ├── <feature>.controller.ts
190
+ │ ├── <feature>.service.ts
191
+ │ ├── <feature>.module.ts
192
+ │ └── dto/ # request/response shapes — prefer importing zod schemas
193
+ │ # from @repo/shared-common over redefining DTOs here
194
+ └── common/ # cross-cutting filters, guards, interceptors
195
+ \`\`\`
196
+
197
+ ## Conventions
198
+
199
+ - One feature = one module. Don't put unrelated controllers in the same module.
200
+ - Services are injectable and stateless. Persistent state goes in Prisma or Redis.
201
+ - Use \`@repo/shared-backend\` guards/pipes — don't reinvent them here.
202
+ - Validate request bodies with the zod schemas in \`@repo/shared-common\`. Pair them with
203
+ the shared \`ZodValidationPipe\`.
204
+ - Health check at \`GET /health\` is required (the prod compose file probes it).
205
+
206
+ ## Commands
207
+
208
+ \`\`\`bash
209
+ pnpm --filter ${name} dev # watch mode
210
+ pnpm --filter ${name} build
211
+ pnpm --filter ${name} test
212
+ pnpm --filter ${name} test:e2e
213
+ \`\`\`
214
+
215
+ ## Don't
216
+
217
+ - Don't import from another backend app (\`apps/backend/<other>\`). Lift shared code into
218
+ \`packages/shared-backend\` instead.
219
+ - Don't bypass the global validation pipe — every controller input must be validated.
220
+ `;
221
+ await fs_extra_1.default.writeFile(path_1.default.join(dir, 'CLAUDE.md'), content);
222
+ }
223
+ async function createFrontendClaudeMd(targetDir, name) {
224
+ const dir = path_1.default.join(targetDir, 'apps', 'frontend', name);
225
+ await fs_extra_1.default.ensureDir(dir);
226
+ const content = `# ${name} (frontend)
227
+
228
+ Next.js app (App Router). See the root [CLAUDE.md](../../../CLAUDE.md) for monorepo-wide
229
+ rules; this file documents only what is specific to \`${name}\`.
230
+
231
+ ## Layout
232
+
233
+ \`\`\`
234
+ app/ # App Router routes
235
+ layout.tsx
236
+ page.tsx
237
+ (group)/... # route groups
238
+ components/ # ${name}-specific components
239
+ ui/ # presentational, no data fetching
240
+ features/ # feature components that fetch / mutate
241
+ lib/ # ${name}-specific helpers (API client, hooks)
242
+ \`\`\`
243
+
244
+ Reusable cross-app components live in \`@repo/shared-frontend\`. If you find yourself
245
+ copying a component to another frontend app, move it there.
246
+
247
+ ## Conventions
248
+
249
+ - **Server Components by default.** Add \`'use client'\` only when you need state, effects,
250
+ or browser APIs.
251
+ - Data fetching: server components fetch directly; client components use the typed API
252
+ client from \`@repo/shared-frontend\`.
253
+ - Types and zod schemas come from \`@repo/shared-common\` — do not redefine API response
254
+ shapes here.
255
+ - All env vars referenced in client code must be prefixed \`NEXT_PUBLIC_\`. Anything else is
256
+ server-only.
257
+
258
+ ## Commands
259
+
260
+ \`\`\`bash
261
+ pnpm --filter ${name} dev
262
+ pnpm --filter ${name} build
263
+ pnpm --filter ${name} start # serve the production build locally
264
+ pnpm --filter ${name} lint
265
+ \`\`\`
266
+
267
+ ## Don't
268
+
269
+ - Don't import server-only modules (\`fs\`, \`@repo/database\`, \`@repo/shared-backend\`) into
270
+ client components — Next.js will fail the build.
271
+ - Don't fetch in a \`useEffect\` for data that could be fetched on the server.
272
+ - Don't hand-roll API types. Reuse zod schemas from \`@repo/shared-common\`.
273
+ `;
274
+ await fs_extra_1.default.writeFile(path_1.default.join(dir, 'CLAUDE.md'), content);
275
+ }
276
+ async function createSharedClaudeMd(targetDir) {
277
+ const dir = path_1.default.join(targetDir, 'packages');
278
+ await fs_extra_1.default.ensureDir(dir);
279
+ const content = `# packages/
280
+
281
+ Shared workspace packages. See the root [CLAUDE.md](../CLAUDE.md) for monorepo rules.
282
+
283
+ ## Which package does my code go in?
284
+
285
+ | Code uses... | Goes in |
286
+ | -------------------------------- | -------------------- |
287
+ | \`fs\`, \`process\`, NestJS, Prisma | \`shared-backend\` |
288
+ | \`react\`, \`window\`, \`document\` | \`shared-frontend\` |
289
+ | Pure TS, zod, no env coupling | \`shared-common\` |
290
+ | Prisma schema or DB client | \`database\` |
291
+ | tsconfig presets | \`tsconfig\` |
292
+
293
+ When in doubt, default to \`shared-common\` — it's the safest place because both sides
294
+ can import it.
295
+
296
+ ## Conventions
297
+
298
+ - Every package exports its public API from \`src/index.ts\`. Don't let consumers
299
+ deep-import (\`@repo/foo/src/internal/x\`) — that's a leak.
300
+ - Package names are \`@repo/<folder>\`. Keep them in sync with the folder name.
301
+ - Adding a new package: copy the structure of an existing one, add it to
302
+ \`pnpm-workspace.yaml\` (already covered by the \`packages/*\` glob), run \`pnpm install\`.
303
+
304
+ ## Database package
305
+
306
+ \`packages/database\` owns the Prisma schema and the generated client. After editing
307
+ \`schema.prisma\`:
308
+
309
+ \`\`\`bash
310
+ pnpm db:generate # regenerate the client (required before type-check passes)
311
+ pnpm db:migrate # create + apply a migration in dev
312
+ \`\`\`
313
+
314
+ Never run \`prisma db push\` against a shared database — it skips the migration history.
315
+ `;
316
+ await fs_extra_1.default.writeFile(path_1.default.join(dir, 'CLAUDE.md'), content);
317
+ }
318
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/templates/claude.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-turbo-mono",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "CLI tool to scaffold a monorepo with NestJS backends and Next.js frontends",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/scaffold.ts CHANGED
@@ -7,6 +7,7 @@ import { createSharedPackages } from './templates/shared';
7
7
  import { createDockerFiles } from './templates/docker';
8
8
  import { createCICDFiles } from './templates/cicd';
9
9
  import { createDocumentation } from './templates/docs';
10
+ import { createClaudeFiles } from './templates/claude';
10
11
 
11
12
  export interface ProjectConfig {
12
13
  projectName: string;
@@ -48,4 +49,8 @@ export async function scaffoldProject(config: ProjectConfig): Promise<void> {
48
49
 
49
50
  // Create documentation
50
51
  await createDocumentation(config);
52
+
53
+ // Create CLAUDE.md files (root + per-app + packages/) so Claude Code
54
+ // auto-loads project context every session.
55
+ await createClaudeFiles(config);
51
56
  }
@@ -0,0 +1,341 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { ProjectConfig } from '../scaffold';
4
+
5
+ export async function createClaudeFiles(config: ProjectConfig): Promise<void> {
6
+ const { targetDir, projectName, backends, frontends } = config;
7
+
8
+ await createRootClaudeMd(targetDir, projectName, backends, frontends);
9
+
10
+ for (const name of backends) {
11
+ await createBackendClaudeMd(targetDir, name);
12
+ }
13
+
14
+ for (const name of frontends) {
15
+ await createFrontendClaudeMd(targetDir, name);
16
+ }
17
+
18
+ await createSharedClaudeMd(targetDir);
19
+ }
20
+
21
+ async function createRootClaudeMd(
22
+ targetDir: string,
23
+ projectName: string,
24
+ backends: string[],
25
+ frontends: string[]
26
+ ): Promise<void> {
27
+ const backendList = backends.length
28
+ ? backends.map((n, i) => ` - \`apps/backend/${n}\` — NestJS service (port ${4000 + i})`).join('\n')
29
+ : ' - _(none)_';
30
+
31
+ const frontendList = frontends.length
32
+ ? frontends.map((n, i) => ` - \`apps/frontend/${n}\` — Next.js app (port ${3000 + i})`).join('\n')
33
+ : ' - _(none)_';
34
+
35
+ const content = `# ${projectName}
36
+
37
+ > This file is auto-loaded by Claude Code at the start of every session.
38
+ > Keep it short, imperative, and pointed at where the truth lives in code.
39
+ > Long-form docs belong in \`docs/\` — link to them from here.
40
+
41
+ ## Project overview
42
+
43
+ ${projectName} is a Turborepo monorepo containing NestJS backends and Next.js frontends sharing
44
+ TypeScript packages, a single Prisma schema, and one Dockerfile with per-app build targets.
45
+
46
+ - Package manager: **pnpm** (workspaces). Never use \`npm\` or \`yarn\` in this repo.
47
+ - Build orchestrator: **Turborepo** (\`turbo.json\` defines the pipeline).
48
+ - Database: **PostgreSQL** via Prisma in \`packages/database\`.
49
+ - Cache/queues: **Redis**.
50
+
51
+ ## Repo map
52
+
53
+ \`\`\`
54
+ ${projectName}/
55
+ ├── apps/
56
+ │ ├── backend/ # NestJS services
57
+ ${backendList}
58
+ │ └── frontend/ # Next.js apps
59
+ ${frontendList}
60
+ ├── packages/
61
+ │ ├── database/ # Prisma schema, migrations, generated client
62
+ │ ├── shared-backend/ # Backend-only utilities (NestJS guards, pipes, types)
63
+ │ ├── shared-frontend/ # React components, hooks, client utilities
64
+ │ ├── shared-common/ # Isomorphic utilities (zod schemas, constants, types)
65
+ │ └── tsconfig/ # Shared tsconfig presets
66
+ ├── docs/ # Human docs — see @docs/ENVIRONMENT.md
67
+ └── Dockerfile # Multi-stage; one target per app
68
+ \`\`\`
69
+
70
+ ## Common commands
71
+
72
+ Run from the repo root unless noted.
73
+
74
+ \`\`\`bash
75
+ pnpm install # install all workspace deps
76
+ pnpm dev # turbo run dev — starts every app in watch mode
77
+ pnpm build # turbo run build — production builds
78
+ pnpm type-check # turbo run type-check
79
+ pnpm lint # turbo run lint
80
+
81
+ pnpm db:generate # regenerate Prisma client (run after schema changes)
82
+ pnpm db:migrate # prisma migrate dev — create + apply a new migration
83
+ pnpm db:studio # open Prisma Studio
84
+
85
+ # Run a single app
86
+ pnpm --filter <app-name> dev
87
+ pnpm --filter <app-name> build
88
+ \`\`\`
89
+
90
+ Docker (local infra only — Postgres + Redis):
91
+
92
+ \`\`\`bash
93
+ docker compose -f docker-compose.local.yml up -d
94
+ \`\`\`
95
+
96
+ Full stack in containers:
97
+
98
+ \`\`\`bash
99
+ docker compose -f docker-compose.dev.yml up --build
100
+ \`\`\`
101
+
102
+ ## Tech stack conventions
103
+
104
+ - **TypeScript strict mode** everywhere. No \`any\` without a comment explaining why.
105
+ - **ES modules**. Use \`import\`/\`export\`, not \`require\`.
106
+ - Path aliases resolve via \`@repo/*\` for workspace packages — import shared code as
107
+ \`import { x } from '@repo/shared-common'\`, never via relative \`../../packages/...\` paths.
108
+ - Validation at boundaries: **zod** schemas live in \`@repo/shared-common\` so frontend and
109
+ backend share one source of truth. Reuse them — do not redefine DTOs per app.
110
+ - Errors: throw typed errors from \`@repo/shared-backend\`. Don't throw raw \`Error\` strings
111
+ in HTTP paths.
112
+
113
+ ## Architecture rules
114
+
115
+ 1. **Database access only from backend apps.** Frontends call backend HTTP endpoints; they
116
+ never import \`@prisma/client\` or \`@repo/database\`.
117
+ 2. **Schema is one file.** \`packages/database/prisma/schema.prisma\` is the only Prisma
118
+ schema. Do not create per-app schemas.
119
+ 3. **No cross-app imports.** \`apps/backend/foo\` must not import from \`apps/backend/bar\`.
120
+ If two apps need the same code, lift it into \`packages/shared-*\`.
121
+ 4. **\`shared-frontend\` is React-only**, \`shared-backend\` is Node-only, \`shared-common\` is
122
+ isomorphic (no \`fs\`, no \`window\`). Pick the right one.
123
+ 5. Environment variables are read **once at startup** in a typed config module — not
124
+ sprinkled as \`process.env.X\` throughout business logic.
125
+
126
+ ## Adding things
127
+
128
+ - **New backend app** → \`apps/backend/<name>/\`, add a \`package.json\` named \`@app/<name>\`,
129
+ then add a Docker target in \`Dockerfile\` and services in the three compose files.
130
+ pnpm picks it up automatically via \`pnpm-workspace.yaml\`.
131
+ - **New frontend app** → same idea under \`apps/frontend/<name>/\`.
132
+ - **New shared package** → \`packages/<name>/\`, name it \`@repo/<name>\`, export a clean
133
+ public API from \`src/index.ts\`.
134
+ - **New env var** → add to \`.env.example\` AND document in [docs/ENVIRONMENT.md](docs/ENVIRONMENT.md).
135
+
136
+ ## Testing
137
+
138
+ - Unit tests live next to the code: \`foo.ts\` + \`foo.spec.ts\`.
139
+ - Integration tests that touch the DB use a real Postgres (the \`docker-compose.local.yml\`
140
+ one) — **do not mock Prisma**. Mocks have hidden divergence from real query behavior.
141
+ - Run a single app's tests: \`pnpm --filter <app-name> test\`.
142
+
143
+ ## Git & CI
144
+
145
+ - Default branch: \`main\`. Feature branches: \`feat/<short-name>\`, \`fix/<short-name>\`.
146
+ - Conventional commits (\`feat:\`, \`fix:\`, \`chore:\`, \`docs:\`, \`refactor:\`).
147
+ - CI runs \`type-check\`, \`lint\`, \`build\` on every PR (see \`.github/workflows/\`).
148
+ - **Never** commit \`.env\`, \`.env.local\`, \`*.pem\`, or anything under \`packages/database/prisma/migrations\`
149
+ that wasn't generated by \`pnpm db:migrate\`.
150
+
151
+ ## Don't
152
+
153
+ - Don't run \`npm install\` or \`yarn\` — use \`pnpm\`.
154
+ - Don't bypass Turbo by \`cd\`-ing into an app and running raw scripts unless debugging.
155
+ - Don't add a new top-level dependency to multiple apps individually — put it in the
156
+ appropriate \`packages/shared-*\` and re-export.
157
+ - Don't \`prisma db push\` against a shared/dev database — always go through \`prisma migrate\`.
158
+ - Don't edit generated files (\`packages/database/node_modules/.prisma\`, \`.next/\`, \`dist/\`).
159
+ - Don't skip git hooks (\`--no-verify\`) without an explicit reason in the commit body.
160
+
161
+ ## When you finish a task
162
+
163
+ 1. \`pnpm type-check && pnpm lint\` — both must pass.
164
+ 2. If you changed the Prisma schema: \`pnpm db:generate\` and create a migration.
165
+ 3. If you added an env var: update \`.env.example\` and \`docs/ENVIRONMENT.md\`.
166
+ 4. If you added/removed an app: update the Dockerfile and all three compose files.
167
+
168
+ ## Pointers
169
+
170
+ - Environment variables: @docs/ENVIRONMENT.md
171
+ - README (human-facing setup): @README.md
172
+ - Prisma schema: @packages/database/prisma/schema.prisma
173
+ - Turbo pipeline: @turbo.json
174
+
175
+ App-specific context lives in per-app \`CLAUDE.md\` files (e.g.
176
+ \`apps/backend/<name>/CLAUDE.md\`). Claude Code auto-discovers them when working inside
177
+ that subtree.
178
+ `;
179
+
180
+ await fs.writeFile(path.join(targetDir, 'CLAUDE.md'), content);
181
+ }
182
+
183
+ async function createBackendClaudeMd(
184
+ targetDir: string,
185
+ name: string
186
+ ): Promise<void> {
187
+ const dir = path.join(targetDir, 'apps', 'backend', name);
188
+ await fs.ensureDir(dir);
189
+
190
+ const content = `# ${name} (backend)
191
+
192
+ NestJS service. See the root [CLAUDE.md](../../../CLAUDE.md) for monorepo-wide rules;
193
+ this file only documents what is specific to \`${name}\`.
194
+
195
+ ## Layout
196
+
197
+ \`\`\`
198
+ src/
199
+ ├── main.ts # bootstrap — keep this minimal
200
+ ├── app.module.ts # root module
201
+ ├── modules/ # feature modules (one folder per domain concept)
202
+ │ └── <feature>/
203
+ │ ├── <feature>.controller.ts
204
+ │ ├── <feature>.service.ts
205
+ │ ├── <feature>.module.ts
206
+ │ └── dto/ # request/response shapes — prefer importing zod schemas
207
+ │ # from @repo/shared-common over redefining DTOs here
208
+ └── common/ # cross-cutting filters, guards, interceptors
209
+ \`\`\`
210
+
211
+ ## Conventions
212
+
213
+ - One feature = one module. Don't put unrelated controllers in the same module.
214
+ - Services are injectable and stateless. Persistent state goes in Prisma or Redis.
215
+ - Use \`@repo/shared-backend\` guards/pipes — don't reinvent them here.
216
+ - Validate request bodies with the zod schemas in \`@repo/shared-common\`. Pair them with
217
+ the shared \`ZodValidationPipe\`.
218
+ - Health check at \`GET /health\` is required (the prod compose file probes it).
219
+
220
+ ## Commands
221
+
222
+ \`\`\`bash
223
+ pnpm --filter ${name} dev # watch mode
224
+ pnpm --filter ${name} build
225
+ pnpm --filter ${name} test
226
+ pnpm --filter ${name} test:e2e
227
+ \`\`\`
228
+
229
+ ## Don't
230
+
231
+ - Don't import from another backend app (\`apps/backend/<other>\`). Lift shared code into
232
+ \`packages/shared-backend\` instead.
233
+ - Don't bypass the global validation pipe — every controller input must be validated.
234
+ `;
235
+
236
+ await fs.writeFile(path.join(dir, 'CLAUDE.md'), content);
237
+ }
238
+
239
+ async function createFrontendClaudeMd(
240
+ targetDir: string,
241
+ name: string
242
+ ): Promise<void> {
243
+ const dir = path.join(targetDir, 'apps', 'frontend', name);
244
+ await fs.ensureDir(dir);
245
+
246
+ const content = `# ${name} (frontend)
247
+
248
+ Next.js app (App Router). See the root [CLAUDE.md](../../../CLAUDE.md) for monorepo-wide
249
+ rules; this file documents only what is specific to \`${name}\`.
250
+
251
+ ## Layout
252
+
253
+ \`\`\`
254
+ app/ # App Router routes
255
+ layout.tsx
256
+ page.tsx
257
+ (group)/... # route groups
258
+ components/ # ${name}-specific components
259
+ ui/ # presentational, no data fetching
260
+ features/ # feature components that fetch / mutate
261
+ lib/ # ${name}-specific helpers (API client, hooks)
262
+ \`\`\`
263
+
264
+ Reusable cross-app components live in \`@repo/shared-frontend\`. If you find yourself
265
+ copying a component to another frontend app, move it there.
266
+
267
+ ## Conventions
268
+
269
+ - **Server Components by default.** Add \`'use client'\` only when you need state, effects,
270
+ or browser APIs.
271
+ - Data fetching: server components fetch directly; client components use the typed API
272
+ client from \`@repo/shared-frontend\`.
273
+ - Types and zod schemas come from \`@repo/shared-common\` — do not redefine API response
274
+ shapes here.
275
+ - All env vars referenced in client code must be prefixed \`NEXT_PUBLIC_\`. Anything else is
276
+ server-only.
277
+
278
+ ## Commands
279
+
280
+ \`\`\`bash
281
+ pnpm --filter ${name} dev
282
+ pnpm --filter ${name} build
283
+ pnpm --filter ${name} start # serve the production build locally
284
+ pnpm --filter ${name} lint
285
+ \`\`\`
286
+
287
+ ## Don't
288
+
289
+ - Don't import server-only modules (\`fs\`, \`@repo/database\`, \`@repo/shared-backend\`) into
290
+ client components — Next.js will fail the build.
291
+ - Don't fetch in a \`useEffect\` for data that could be fetched on the server.
292
+ - Don't hand-roll API types. Reuse zod schemas from \`@repo/shared-common\`.
293
+ `;
294
+
295
+ await fs.writeFile(path.join(dir, 'CLAUDE.md'), content);
296
+ }
297
+
298
+ async function createSharedClaudeMd(targetDir: string): Promise<void> {
299
+ const dir = path.join(targetDir, 'packages');
300
+ await fs.ensureDir(dir);
301
+
302
+ const content = `# packages/
303
+
304
+ Shared workspace packages. See the root [CLAUDE.md](../CLAUDE.md) for monorepo rules.
305
+
306
+ ## Which package does my code go in?
307
+
308
+ | Code uses... | Goes in |
309
+ | -------------------------------- | -------------------- |
310
+ | \`fs\`, \`process\`, NestJS, Prisma | \`shared-backend\` |
311
+ | \`react\`, \`window\`, \`document\` | \`shared-frontend\` |
312
+ | Pure TS, zod, no env coupling | \`shared-common\` |
313
+ | Prisma schema or DB client | \`database\` |
314
+ | tsconfig presets | \`tsconfig\` |
315
+
316
+ When in doubt, default to \`shared-common\` — it's the safest place because both sides
317
+ can import it.
318
+
319
+ ## Conventions
320
+
321
+ - Every package exports its public API from \`src/index.ts\`. Don't let consumers
322
+ deep-import (\`@repo/foo/src/internal/x\`) — that's a leak.
323
+ - Package names are \`@repo/<folder>\`. Keep them in sync with the folder name.
324
+ - Adding a new package: copy the structure of an existing one, add it to
325
+ \`pnpm-workspace.yaml\` (already covered by the \`packages/*\` glob), run \`pnpm install\`.
326
+
327
+ ## Database package
328
+
329
+ \`packages/database\` owns the Prisma schema and the generated client. After editing
330
+ \`schema.prisma\`:
331
+
332
+ \`\`\`bash
333
+ pnpm db:generate # regenerate the client (required before type-check passes)
334
+ pnpm db:migrate # create + apply a migration in dev
335
+ \`\`\`
336
+
337
+ Never run \`prisma db push\` against a shared database — it skips the migration history.
338
+ `;
339
+
340
+ await fs.writeFile(path.join(dir, 'CLAUDE.md'), content);
341
+ }