create-claude-workspace 2.3.4 → 2.3.5

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.
@@ -63,304 +63,18 @@ Ensure these are in `.gitignore`:
63
63
 
64
64
  [Add any special tech from user answers]
65
65
 
66
- ### App Separation Principle
67
-
68
- - **`apps/` are thin shells** — each app is just configuration + routing + bootstrap. Minimal code.
69
- - **`libs/` contain all logic** — each domain/feature has its **own library group** with sub-libraries per layer. Apps import only from entry points.
70
- - **Feature-first library organization (STRICT)** — every distinct feature/domain gets its own group of libraries:
71
- ```
72
- libs/
73
- scan/ # feature: scan
74
- domain/ # scan types, schemas, interfaces
75
- ui/ # scan UI components
76
- feature/ # scan smart components
77
- data-access/ # scan HTTP/DB services
78
- streak/ # feature: streak
79
- domain/
80
- ui/
81
- feature/
82
- achievement/ # feature: achievement
83
- domain/
84
- feature/
85
- shared/ # ONLY truly cross-domain code
86
- ui/ # generic UI primitives (buttons, modals)
87
- domain/ # cross-domain types (if any)
88
- infrastructure/
89
- ```
90
- **NEVER dump multiple features into a single library** (e.g. `shared/types` with `scan.ts`, `streak.ts`, `achievement.ts`). Each feature owns its types in its own `domain/` library.
91
- - **Frontend and backend are separate apps** with separate build configurations per environment:
92
- - `apps/[APP_NAME]/` — Frontend application
93
- - `apps/api/` — Backend API (if applicable)
94
- - **Environment configs**: each app has per-target settings via Nx `configurations` in `project.json` (API URLs, feature flags, etc.)
95
- - **Entry point pattern**: each domain lib has a root `index.ts` that re-exports the public API. Apps and other libs import ONLY from `@[PREFIX]/<lib-name>`, never from deep paths like `@[PREFIX]/<lib-name>/src/lib/internal/...`
96
-
97
- ### CLI-First Principle
98
-
99
- **ALWAYS prioritize CLI commands and generators over manual file creation.** This applies to:
100
- - Nx workspace scaffolding (`create-nx-workspace`)
101
- - Libraries, components, applications (`nx generate`)
102
- - Adding plugins (`nx add`)
103
- - Package installation (package manager CLI)
104
- - Git operations (`gh`, `glab`)
105
-
106
- NEVER manually create `project.json`, `tsconfig.*`, or boilerplate files that a generator would produce. Generators configure dependencies, paths, and targets correctly.
107
-
108
- **NEVER use `nx:run-commands` executor** in project.json. Always use the proper built-in executor (`@nx/js:node` for serve, `@nx/vite:build` for build, `@nx/eslint:lint` for lint, etc.). `nx:run-commands` is an escape hatch for one-off scripts, not for standard targets.
109
-
110
- ### Nx Generators
111
-
112
- [If Nx monorepo:]
113
-
114
- **Generator defaults** are configured in `nx.json` — no need to repeat flags like `--unitTestRunner`, `--linter`, `--style` in every command. See `.claude/profiles/frontend.md` for framework-specific generator commands.
115
-
116
- **Creating libraries:**
117
- ```bash
118
- # Plain TypeScript library (for domain models, business logic, shared utils)
119
- nx g @nx/js:library --directory=libs/[domain]/[layer] --no-interactive
120
-
121
- # Framework-specific library — see frontend profile for the correct generator
122
- ```
123
-
124
- **Bundler rule (STRICT):** Internal monorepo libs do NOT need a bundler — Nx handles compilation. NEVER install or configure tsup, tsdown, rollup, or any standalone bundler for internal libs. Only add `--bundler=esbuild|tsc|swc` to `nx generate` for **publishable** libraries (npm packages). If `nx generate` created a lib without `--bundler`, do NOT retroactively add one.
66
+ ### Standards
125
67
 
126
- After generation, the architect's plan specifies what code to write IN the generated files. The generator handles project.json, tsconfig paths, and build targets.
127
-
128
- ### Onion Architecture (per domain)
129
-
130
- ```
131
- +-----------------------------------------------------+
132
- | apps/[app] |
133
- | App shell — assembles features into routing |
134
- +-----------------------------------------------------+
135
- | feature/ |
136
- | Smart components, orchestrate UI + data |
137
- +-----------------------------------------------------+
138
- | ui/ | data-access/ |
139
- | Presentational components | HTTP / DB services |
140
- | (dumb, input/output) | |
141
- +-----------------------------------------------------+
142
- | api/ |
143
- | API routes, validation (if backend) |
144
- +-----------------------------------------------------+
145
- | business/ |
146
- | Use cases, business logic |
147
- +-----------------------------------------------------+
148
- | domain/ |
149
- | TypeBox schemas (single source of truth), types, |
150
- | repository interfaces, value objects |
151
- +-----------------------------------------------------+
152
- | infrastructure/ |
153
- | Repository implementations (database, API, mock) |
154
- +-----------------------------------------------------+
155
- ```
156
-
157
- Dependency rules:
158
- - domain -> only shared/domain
159
- - business -> domain, shared/infrastructure/di
160
- - api -> business, domain
161
- - infrastructure -> domain, shared/infrastructure
162
- - data-access -> domain (for types)
163
- - ui -> shared/ui, domain (for types)
164
- - feature -> ui, data-access, shared/ui
165
-
166
- **TypeBox as single source of truth**: Define TypeBox schemas in `domain/` layer (`libs/[domain]/domain/`). These schemas are the canonical definition — derive everything from them:
167
- - **TypeScript types**: `Static<typeof MySchema>` — no separate interface definitions
168
- - **API validation**: `openAPIRouteHandler` uses the same schemas for request/response validation + OpenAPI spec
169
- - **Frontend types**: Frontend imports types from domain lib via `@[PREFIX]/[domain]-domain` — no copy-paste
170
- - **DB mapping**: Infrastructure layer maps between DB rows and domain types
171
- - NEVER duplicate type definitions. If a type exists as a TypeBox schema, use `Static<>` everywhere.
172
-
173
- ### @cibule/* Ecosystem (Preferred Libraries)
174
-
175
- [Include only if project uses backend or fullstack architecture]
176
-
177
- **ALWAYS prefer `@cibule/*` packages** over custom implementations or third-party alternatives for: DI, database access, file storage, image processing, and Nx workspace scaffolding. These are driver-agnostic abstractions designed for the onion architecture pattern.
178
-
179
- | Package | Purpose | Replaces |
180
- |---------|---------|----------|
181
- | `@cibule/di` | Dependency injection (InjectionToken, Injector, inject()) | Custom DI |
182
- | `@cibule/db` | Database abstraction (Kysely-based, driver-agnostic) | Raw Kysely |
183
- | `@cibule/db-d1` | Cloudflare D1 driver for @cibule/db | kysely-d1 |
184
- | `@cibule/db-sqlite` | SQLite driver for @cibule/db (better-sqlite3) | Direct better-sqlite3 |
185
- | `@cibule/db-migrate` | Migration orchestrator (Prisma + D1 PRAGMA fixes) | Manual migrations |
186
- | `@cibule/storage` | File storage abstraction (upload, download, presigned URLs) | Custom storage |
187
- | `@cibule/storage-r2` | Cloudflare R2 driver for @cibule/storage | Direct R2 API |
188
- | `@cibule/storage-s3` | AWS S3 driver for @cibule/storage | Direct AWS SDK |
189
- | `@cibule/image` | Image transformation abstraction | Custom image processing |
190
- | `@cibule/image-sharp` | Sharp-based driver with FileStorage caching (Node.js) | Direct Sharp |
191
- | `@cibule/image-cf` | Cloudflare Image Resizing driver | Direct CF API |
192
- | `@cibule/wiring` | Per-request DI middleware, AsyncLocalStorage helpers | Custom middleware |
193
- | `@cibule/devkit` | Nx generators for onion architecture scaffolding | Manual Nx setup |
194
-
195
- **DI core API** (`@cibule/di`):
196
- - `InjectionToken<T>` — typed token, `Injector.create({ providers, parent? })` — container
197
- - `inject<T>(token)` / `inject<T>(token, { optional: true })` — resolve from context
198
- - `runInInjectionContext(injector, fn)` — scoped execution
199
- - Provider types: `useValue`, `useClass`, `useFactory`, `multi: true`
200
-
201
- **Database pattern** (`@cibule/db` + driver):
202
- ```typescript
203
- // Domain layer — driver-agnostic
204
- import type { Db } from '@cibule/db';
205
- import { DB_ACCESSOR, UNIT_OF_WORK_FACTORY } from '@cibule/db';
206
-
207
- // Infrastructure — pick driver per platform
208
- import { provideD1Db } from '@cibule/db-d1'; // Cloudflare Workers
209
- import { provideSqliteDb } from '@cibule/db-sqlite'; // Node.js local dev
210
- ```
211
-
212
- **Workspace scaffolding** (`@cibule/devkit`):
213
- ```bash
214
- nx g @cibule/devkit:preset myorg # Initialize workspace with onion layers
215
- nx g @cibule/devkit:scope market --frontend # Create domain scope
216
- ```
217
-
218
- **Dependency bug handling**: If a bug is caused by a third-party dependency (not by project code), mark the task as `[~] BLOCKED` with the bug details and the package version. Continue with other tasks. The dependency freshness check at phase transitions will detect new versions — re-attempt blocked tasks after the package is updated.
68
+ Shared coding standards are in `.claude/standards/` agents read them on demand:
69
+ - `coding-standards.md` — file organization, TypeScript config, coding style, code cleanliness, modern JS/TS
70
+ - `architecture.md` app separation, CLI-first, Nx generators, onion architecture
71
+ - `backend-patterns.md` — @cibule/* ecosystem, platform-agnostic backend, Hono/OpenAPI patterns
72
+ - `testing-standards.md` — test coverage, VRT setup, code quality & linting
219
73
 
220
74
  ### Frontend Profile
221
75
 
222
76
  Framework-specific best practices, component architecture, state management, SSR patterns, theme system, and UI component library conventions are defined in `.claude/profiles/frontend.md`. This file is read by `ui-engineer`, `senior-code-reviewer`, and `test-engineer` agents — not by backend or infrastructure agents.
223
77
 
224
- ### File Organization & Size Limits
225
-
226
- **Single-purpose files (STRICT):**
227
- - Each `.ts` file exports ONE class, ONE function, or ONE closely related set of helpers (e.g., a type + its factory)
228
- - Name files after their single export: `get-image.ts`, `parse-html.ts`, `price-calculator.ts`
229
- - NEVER bundle unrelated exports into a barrel file like `utils.ts` or `helpers.ts` — split into individual files
230
- - Index files (`index.ts`) are the ONLY exception — they re-export the public API of a library
231
-
232
- **File size limits:**
233
- - MAX 200 lines per TypeScript file — split into types, utils, sub-components if larger
234
- - MAX 200 lines per SCSS file — split into partials
235
- - MAX 100 lines per HTML template — decompose into child components
236
-
237
- **Co-located tests:**
238
- - Test files live next to the source file: `price-calculator.spec.ts` beside `price-calculator.ts`
239
- - NEVER create `__tests__/` directories — tests are always co-located
240
- - One test file per source file — do NOT bundle multiple files' tests together
241
-
242
- ### TypeScript Config
243
-
244
- - `moduleResolution: "bundler"` in `tsconfig.base.json` — all code goes through a bundler, so use bundler-style resolution
245
- - NEVER add `.js` extensions to TypeScript imports — write `import { Foo } from './foo'`, not `'./foo.js'`
246
- - `module: "ESNext"` + `target: "ES2022"` (or as appropriate)
247
- - `strict: true`, `noUncheckedIndexedAccess: true`
248
- - Path aliases via `compilerOptions.paths` in `tsconfig.base.json` — managed by Nx generators, do not edit manually
249
-
250
- ### Coding Style
251
-
252
- - No comments in code — write self-explanatory code
253
- - Explicit access modifiers: `public` for API, `protected` for template-used, `private` for internal
254
- - Import order enforced by `eslint-plugin-simple-import-sort` (automatic)
255
- - Use `type` imports for type-only imports (`import type { Foo }`)
256
- - DRY: 3+ repeats = extract to shared utility/component/directive
257
- - Prefer composition over inheritance
258
- - `readonly` on all fields that don't need reassignment
259
- - No `any` — use `unknown` + type narrowing
260
- - No non-null assertions (`!`) — handle nullability explicitly with narrowing, `??`, or early returns
261
- - No `as unknown as T` double-casting — if types don't align, fix the types or use proper type guards
262
- - No `eslint-disable` comments — NEVER suppress linter rules. If ESLint flags an error, fix the code instead of disabling the rule. This includes `eslint-disable-next-line`, `eslint-disable-line`, and block `eslint-disable` comments.
263
-
264
- ### Code Cleanliness (STRICT — clean code enables high coverage)
265
-
266
- - **Pure functions first**: business logic and domain operations are pure — same input, same output, no side effects. This makes them trivially testable.
267
- - **Minimal branching**: avoid nested conditionals (max 2 levels). Prefer early returns, lookup maps/objects, `??`/`?.` chains, polymorphism. If a function has 4+ branches, split it.
268
- - **Side effects at boundaries**: I/O (HTTP, DB, logging, DOM) happens at the edges — infrastructure layer, entry points. Business and domain code stays pure.
269
- - **Data transformations over mutations**: prefer `map`/`filter`/spread/new objects over `push`/`splice`/`delete`/mutation. Immutable data is predictable and testable.
270
- - **Small focused functions**: each function does ONE thing. Max ~20 lines of logic. Extract complex expressions into named pure helpers.
271
- - **Declarative over imperative**: describe WHAT, not HOW. Prefer expressions over statement sequences.
272
-
273
- ### Modern JavaScript Syntax (STRICT — enforced by ESLint)
274
-
275
- - `for...of` over `.forEach()` — clearer, supports `break`/`continue`/`await`
276
- - `const` by default — `let` only when reassignment is needed, NEVER `var`
277
- - Arrow functions in callbacks — `array.map(x => x.id)`, not `array.map(function(x) { ... })`
278
- - Template literals — `` `Hello ${name}` ``, not `'Hello ' + name`
279
- - Object shorthand — `{ name, age }`, not `{ name: name, age: age }`
280
- - Destructuring — `const { id, name } = user`, not `const id = user.id`
281
- - Nullish coalescing `??` over `||` for defaults (avoids falsy pitfalls)
282
- - Optional chaining `?.` over nested `if` checks
283
- - `Promise.all()` for parallel async, `for await...of` for async iteration
284
-
285
- ### Test Coverage
286
-
287
- 80% minimum for statements, branches, functions, lines (enforced in CI).
288
-
289
- - **Config template**: `.claude/templates/vitest.coverage.ts` — merge into each project's `vite.config.ts` or `vitest.config.ts` during scaffolding. Replace `[PROJECT_NAME]` with actual name.
290
- - Reporters: `cobertura` (GitLab/GitHub MR coverage), `html` (browsable), `text-summary`
291
- - Coverage aggregated at workspace root under `coverage/` (add to `.gitignore`)
292
- - Run: `nx test [PROJECT] --coverage` or `nx affected --target=test -- --coverage`
293
-
294
- ### Visual Regression Testing
295
-
296
- Page-level VRT using Playwright `toHaveScreenshot()` at 3 viewports (375px, 768px, 1280px). Catches unintended visual regressions across pages.
297
-
298
- - **Files**: `*.vrt.spec.ts` in E2E project (co-located with functional E2E tests)
299
- - **Baselines**: `*-snapshots/` directories — committed to git
300
- - **Threshold**: `maxDiffPixelRatio: 0.01` (1%), animations disabled
301
- - **Update baselines**: `nx e2e [APP]-e2e -- --update-snapshots` after intentional visual changes
302
- - **CI**: use Playwright Docker image (`mcr.microsoft.com/playwright`) for consistent rendering
303
-
304
- ### Code Quality & Linting
305
-
306
- Config templates are in `.claude/templates/` — copy to project root during Phase 0 scaffolding:
307
- - **ESLint**: `.claude/templates/eslint.config.js` → `eslint.config.js` (flat config, `@typescript-eslint/strict-type-checked` + `@nx/eslint-plugin` + `eslint-plugin-simple-import-sort` + `eslint-plugin-prefer-arrow-functions`). Add framework-specific rules from `.claude/profiles/frontend.md`.
308
- - **Prettier**: `.claude/templates/.prettierrc` → `.prettierrc`, `.claude/templates/.prettierignore` → `.prettierignore`
309
- - **Stylelint**: `.claude/templates/.stylelintrc.json` → `.stylelintrc.json` (SCSS only, forces theme tokens over hardcoded colors)
310
- - **Pre-commit hooks**: `.claude/templates/.lefthook.yml` → `.lefthook.yml`
311
-
312
- Each library's `project.json` must declare tags: `"tags": ["type:domain", "scope:auth"]`
313
-
314
- Key rules enforced (do NOT weaken):
315
- - `prefer-arrow-functions/prefer-arrow-functions` — const arrow over function declarations
316
- - `max-classes-per-file: 1`, `max-depth: 4`
317
- - `@typescript-eslint/explicit-member-accessibility` — explicit public/private/protected
318
- - `@typescript-eslint/prefer-readonly` — readonly where possible
319
- - `@typescript-eslint/no-non-null-assertion`, `no-explicit-any`, `consistent-type-imports`, `strict-boolean-expressions`
320
- - `no-warning-comments: ['eslint-disable']` — no eslint-disable comments
321
- - `@nx/enforce-module-boundaries` — onion architecture layer constraints
322
- - `eslint-config-prettier` installed to disable conflicting rules. Do NOT use `eslint-plugin-prettier`.
323
-
324
- **Enforcement:**
325
- - All three tools run in CI pipeline (fail on violations)
326
- - `nx affected --target=lint` for incremental linting
327
- - Pre-commit hooks prevent committing violations
328
-
329
- ### Backend Patterns (if applicable)
330
-
331
- [Include only if the project has a backend]
332
-
333
- - Hono routes with validation (**TypeBox** — `typebox` for schema + type inference, `TypeCompiler` for runtime validation). **NEVER use `@sinclair/typebox`** — the correct package is `typebox`.
334
- - **OpenAPI-first**: Use `hono-openapi` with `openAPIRouteHandler` for all API routes — generates OpenAPI spec from TypeBox schemas automatically. API docs served via `@scalar/hono-api-reference` at `/reference`.
335
- - `@cibule/di` for dependency injection (see @cibule/* Ecosystem section above)
336
- - `@cibule/db` + driver for database access, UnitOfWork for atomic writes
337
- - `@cibule/storage` + driver for file storage, `@cibule/image` + driver for image processing
338
- - `@cibule/wiring` for per-request DI middleware
339
-
340
- **Platform-Agnostic Backend (STRICT):**
341
- - Backend code MUST run on both Node.js and Cloudflare Workers without modification
342
- - NEVER use Node.js-specific APIs (`fs`, `path`, `process`, `Buffer`) in business/domain/api layers
343
- - NEVER use Cloudflare-specific APIs (`env.DB`, `ctx.waitUntil()`) in business/domain layers
344
- - Platform-specific code lives ONLY in `infrastructure/` layer behind abstract interfaces
345
- - Use Web Standard APIs where possible: `fetch`, `Request`, `Response`, `URL`, `crypto`, `TextEncoder`/`TextDecoder`, `Headers`, `FormData`, `ReadableStream`
346
- - **Platform-specific code MUST be in separate libraries (STRICT)** — NEVER mix Node.js and Cloudflare code in the same library. Barrel exports (`index.ts`) would pull both platforms into the bundle, causing compilation errors (e.g. `better-sqlite3` in Cloudflare, or D1 bindings in Node.js):
347
- ```
348
- libs/[domain]/
349
- infrastructure-d1/ # Cloudflare D1 implementation ONLY
350
- infrastructure-sqlite/ # Node.js SQLite implementation ONLY
351
- libs/shared/
352
- infrastructure-d1/ # shared D1 providers (provideD1Database)
353
- infrastructure-sqlite/ # shared SQLite providers (provideSqliteDatabase)
354
- ```
355
- Each entry point imports ONLY its platform's library:
356
- - Worker entry → `@[PREFIX]/shared-infrastructure-d1`
357
- - Node entry → `@[PREFIX]/shared-infrastructure-sqlite`
358
- - Hono is inherently platform-agnostic — use its standard APIs, avoid `c.env` directly in routes (inject via DI)
359
- - Entry points handle platform wiring:
360
- - `apps/api/src/main.ts` — Node.js entry (optional, for local dev)
361
- - `apps/api/src/index.ts` — Cloudflare Worker entry (production)
362
- - Default deployment: **Cloudflare Workers** (production), **Node.js** (local development via `@nx/js:node` executor + Node.js entry point). Wrangler is deployment-only — NEVER used for local dev or in Nx targets.
363
-
364
78
  ### Project-Specific Details
365
79
 
366
80
  [Add critical implementation details, key patterns, special requirements from the discovery conversation and codebase exploration. This section is expanded by architect agents as they make technical decisions during development.]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-claude-workspace",
3
- "version": "2.3.4",
3
+ "version": "2.3.5",
4
4
  "author": "",
5
5
  "repository": {
6
6
  "type": "git",