@claude-code-mastery/starter-kit 1.0.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 (70) hide show
  1. package/.claude/.starter-kit/profiles/clean.md +113 -0
  2. package/.claude/.starter-kit/profiles/go.md +458 -0
  3. package/.claude/.starter-kit/profiles/node.md +429 -0
  4. package/.claude/.starter-kit/profiles/python.md +475 -0
  5. package/.claude/.starter-kit/shared/analytics-rybbit.md +55 -0
  6. package/.claude/.starter-kit/shared/claude-md-base.md +93 -0
  7. package/.claude/.starter-kit/shared/deployment-dokploy.md +158 -0
  8. package/.claude/.starter-kit/shared/feature-manifest.md +43 -0
  9. package/.claude/.starter-kit/shared/mcp-and-pooler.md +38 -0
  10. package/.claude/.starter-kit/shared/mongo-setup.md +20 -0
  11. package/.claude/.starter-kit/shared/profile-config.md +65 -0
  12. package/.claude/.starter-kit/shared/seo.md +113 -0
  13. package/.claude/.starter-kit/shared/sql-setup.md +37 -0
  14. package/.claude/commands/add-feature.md +349 -0
  15. package/.claude/commands/add-project-setup.md +156 -0
  16. package/.claude/commands/architecture.md +27 -0
  17. package/.claude/commands/commit.md +61 -0
  18. package/.claude/commands/convert-project-to-starter-kit.md +508 -0
  19. package/.claude/commands/create-api.md +385 -0
  20. package/.claude/commands/create-e2e.md +230 -0
  21. package/.claude/commands/diagram.md +301 -0
  22. package/.claude/commands/help.md +120 -0
  23. package/.claude/commands/install-global.md +145 -0
  24. package/.claude/commands/new-project.md +244 -0
  25. package/.claude/commands/optimize-docker.md +352 -0
  26. package/.claude/commands/progress.md +61 -0
  27. package/.claude/commands/projects-created.md +79 -0
  28. package/.claude/commands/quickstart.md +105 -0
  29. package/.claude/commands/refactor.md +267 -0
  30. package/.claude/commands/remove-project.md +95 -0
  31. package/.claude/commands/review.md +59 -0
  32. package/.claude/commands/security-check.md +77 -0
  33. package/.claude/commands/set-project-profile-default.md +79 -0
  34. package/.claude/commands/setup.md +337 -0
  35. package/.claude/commands/show-user-guide.md +58 -0
  36. package/.claude/commands/starter-kit.md +90 -0
  37. package/.claude/commands/test-plan.md +118 -0
  38. package/.claude/commands/update-project.md +413 -0
  39. package/.claude/commands/what-is-my-ai-doing.md +42 -0
  40. package/.claude/commands/worktree.md +124 -0
  41. package/.claude/hooks/block-dangerous-bash.py +55 -0
  42. package/.claude/hooks/check-branch.sh +116 -0
  43. package/.claude/hooks/check-e2e.sh +71 -0
  44. package/.claude/hooks/check-env-sync.sh +41 -0
  45. package/.claude/hooks/check-file-length.py +47 -0
  46. package/.claude/hooks/check-ports.sh +59 -0
  47. package/.claude/hooks/check-rulecatch.sh +33 -0
  48. package/.claude/hooks/check-rybbit.sh +63 -0
  49. package/.claude/hooks/lint-on-save.sh +59 -0
  50. package/.claude/hooks/verify-no-secrets.sh +80 -0
  51. package/.claude/settings.json +34 -0
  52. package/.claude/skills/api-conventions/SKILL.md +34 -0
  53. package/.claude/skills/code-review/SKILL.md +87 -0
  54. package/.claude/skills/code-review/references/mongodb-checks.md +25 -0
  55. package/.claude/skills/code-review/references/project-checks.md +38 -0
  56. package/.claude/skills/create-service/SKILL.md +222 -0
  57. package/.claude/skills/debugger/SKILL.md +39 -0
  58. package/.claude/skills/dependency-vetting/SKILL.md +46 -0
  59. package/.claude/skills/design-review/SKILL.md +50 -0
  60. package/.claude/skills/mcp-builder/SKILL.md +57 -0
  61. package/.claude/skills/mongodb-rules/SKILL.md +62 -0
  62. package/.claude/skills/terminal-tui/SKILL.md +106 -0
  63. package/.claude/skills/test-writer/SKILL.md +78 -0
  64. package/LICENSE +21 -0
  65. package/README.md +2152 -0
  66. package/bin/cli.js +205 -0
  67. package/claude-mastery-project.conf +220 -0
  68. package/global-claude-md/CLAUDE.md +212 -0
  69. package/global-claude-md/settings.json +3 -0
  70. package/package.json +81 -0
@@ -0,0 +1,429 @@
1
+ <!-- Part of /new-project scaffolding. Read via .claude/commands/new-project.md when the selection requires it; not a standalone command. -->
2
+
3
+ > This profile builds its CLAUDE.md from `../shared/claude-md-base.md` (the universal rules) plus the profile-specific rules below. Read the base first.
4
+
5
+ ## Step 1 — Ask the User (skip questions answered by arguments)
6
+
7
+ For any choices NOT provided via arguments, ask the user (use AskUserQuestion):
8
+
9
+ ### Question 1: Project Type
10
+ "What type of project are you building?"
11
+ - **Web App** — Frontend with UI (SPA or SSR)
12
+ - **API** — Backend REST/GraphQL service
13
+ - **Full-Stack** — Frontend + backend in one repo
14
+ - **CLI Tool** — Command-line application
15
+
16
+ ### Question 2: Framework (based on project type)
17
+
18
+ **If Web App or Full-Stack:**
19
+ "Which framework do you want to use?"
20
+ - **Vite + React** — Fastest HMR, lightweight, great for SPAs (Recommended)
21
+ - **Next.js (App Router)** — SSR, server components, built-in routing
22
+ - **Vue 3** — Composition API, progressive framework, reactive
23
+ - **Nuxt** — Vue with SSR, auto-imports, file-based routing
24
+ - **Svelte** — Compiled, minimal runtime, reactive by default
25
+ - **SvelteKit** — Svelte with SSR, file-based routing, form actions
26
+ - **Angular** — Enterprise, standalone components, signals
27
+ - **Astro** — Content-first, island architecture, great for marketing/docs sites
28
+
29
+ **If API:**
30
+ "Which framework do you want to use?"
31
+ - **Fastify** — Fastest Node.js HTTP framework, built-in validation (Recommended)
32
+ - **Express** — Most popular, largest ecosystem
33
+ - **Hono** — Ultra-lightweight, edge-ready
34
+
35
+ **If CLI Tool:**
36
+ - Use **Commander.js** + **TypeScript** (no framework question needed)
37
+
38
+ ### Question 3: SSR Requirement (Web App / Full-Stack only, skip if Next.js or Astro already chosen)
39
+ "Do you need server-side rendering (SSR)?"
40
+ - **No (SPA)** — Client-side only, simpler deployment (Recommended for dashboards/apps)
41
+ - **Yes (SSR)** — SEO-critical pages, faster first paint (Recommended for public-facing sites)
42
+
43
+ If they chose Vite + React and want SSR, switch to **Next.js (App Router)** or add **vite-plugin-ssr**.
44
+
45
+ ### Question 4: Package Manager
46
+ "Which package manager?"
47
+ - **pnpm** — Fast, disk-efficient (Recommended)
48
+ - **npm** — Default, universal
49
+ - **bun** — Fastest, newer ecosystem
50
+
51
+ ### Question 5: Hosting / Deployment
52
+ "Where will this be deployed?" (skip if `dokploy`, `vercel`, or `static` in arguments)
53
+ - **Dokploy on Hostinger VPS** — Self-hosted Docker containers with Dokploy management (Recommended for full control)
54
+ - **Vercel** — Zero-config for Next.js / static sites
55
+ - **Static hosting** — GitHub Pages, Netlify, Cloudflare Pages
56
+ - **None / Decide later** — Skip deployment scaffolding
57
+
58
+ ### Question 6: Extras (multi-select)
59
+ "What extras do you want to include?"
60
+ - **Tailwind CSS** — Utility-first CSS framework
61
+ - **Prisma** — Type-safe database ORM
62
+ - **Docker** — Containerized deployment (auto-included with Dokploy)
63
+ - **GitHub Actions CI** — Automated testing pipeline
64
+ - **Multi-region** — US + EU deployment (Dokploy only)
65
+
66
+ ### Question 7: MongoDB Connection String (only if `mongo` database selected)
67
+ "Do you want to configure your MongoDB connection now?"
68
+ - **Yes, I have a connection string** — User pastes their full `mongodb+srv://...` or `mongodb://...` URI. Write it to `.env` as `STRICTDB_URI=<their-value>`.
69
+ - **No, I'll set it up later** — Skip. Leave `STRICTDB_URI` placeholder in `.env.example` only.
70
+
71
+ If the user provides a connection string:
72
+ 1. Write `STRICTDB_URI=<value>` to the project's `.env`
73
+ 2. If no database name in URI, ask: "What should the database be called?" and append it to the URI
74
+
75
+ ## Step 2 — Create the Project
76
+
77
+ Based on answers, scaffold the project.
78
+
79
+ ### Default Profile Batch Script
80
+
81
+ **If the resolved choices exactly match the default profile** (fullstack + next + mongo + tailwind + docker + pnpm), use the batch scaffold script for maximum speed:
82
+
83
+ ```bash
84
+ bash "$(pwd)/scripts/scaffold-default.sh" "$PROJECT_PATH" "$PROJECT_NAME" "$(pwd)"
85
+ ```
86
+
87
+ The script handles ALL of the following in one execution with progress indicators:
88
+ - Creates all directories (src/, .claude/, project-docs/, tests/, scripts/, .github/)
89
+ - Copies project-scoped commands, all skills, and all hooks
90
+ - Writes settings.json (full 9-hook config)
91
+ - Installs StrictDB (npm package) + query system
92
+ - Creates Next.js app structure (layout, page, API health route, instrumentation)
93
+ - Creates TypeScript, Next.js, Tailwind, PostCSS, Vitest, Playwright configs
94
+ - Creates package.json with all deps/scripts
95
+ - Creates Dockerfile (multi-stage standalone)
96
+ - Creates GitHub Actions CI workflow
97
+ - Creates CLAUDE.md (all rules), CLAUDE.local.md
98
+ - Creates project-docs templates, test templates, SEO files
99
+ - Creates .env, .env.example, .gitignore, .dockerignore, README.md
100
+ - Creates populated features.json manifest
101
+ - Runs pnpm install, initializes git, registers project
102
+
103
+ **Do NOT create files individually when using the default profile — the script handles everything.**
104
+
105
+ After the script completes, display the verification checklist (the script output includes a summary).
106
+
107
+ ### Manual Scaffolding (non-default profiles)
108
+
109
+ For profiles other than `default` and `clean`, scaffold manually:
110
+
111
+ 1. Create project directory
112
+ 2. Initialize with chosen framework and package manager
113
+ 3. Install TypeScript + Vitest (ALWAYS, non-negotiable)
114
+ 4. Create ALL required files (see below)
115
+ 5. Apply framework-specific rules
116
+ 6. Apply SEO requirements (if web project)
117
+ 7. Initialize git repository
118
+ 8. Create initial commit: "Initial project scaffold"
119
+ 9. Display verification checklist
120
+
121
+ ## Required Files (EVERY Project)
122
+
123
+ - `.env` — Empty, for secrets (NEVER commit)
124
+ - `.env.example` — Template with placeholder values
125
+ - `.gitignore` — Must include: .env, .env.*, node_modules/, dist/, CLAUDE.local.md
126
+ - `.dockerignore` — Must include: .env, .git/, node_modules/
127
+ - `README.md` — Project overview (reference env vars, don't hardcode)
128
+ - `CLAUDE.md` — Must include: project overview, tech stack, build/test/dev commands, architecture, port assignments
129
+ - `tsconfig.json` — Strict mode enabled, `noUncheckedIndexedAccess: true`
130
+
131
+ ## Required Directory Structure
132
+
133
+ ```
134
+ project/
135
+ ├── src/
136
+ ├── tests/
137
+ ├── project-docs/
138
+ │ ├── ARCHITECTURE.md
139
+ │ ├── INFRASTRUCTURE.md
140
+ │ └── DECISIONS.md
141
+ ├── .claude/
142
+ │ ├── commands/
143
+ │ ├── skills/
144
+ └── scripts/
145
+ ├── db-query.ts # (StrictDB/MongoDB only) Test Query Master
146
+ └── queries/ # (StrictDB/MongoDB only) Individual dev/test query files
147
+ ```
148
+
149
+
150
+ > Database setup: if a SQL database was selected, read and apply `../shared/sql-setup.md`; if `mongo`, read and apply `../shared/mongo-setup.md`. Then continue below.
151
+
152
+ ## TypeScript + Vitest + Playwright (ALWAYS)
153
+
154
+ Every project MUST have Vitest for unit tests and Playwright for E2E tests.
155
+
156
+ ### vitest.config.ts
157
+ ```typescript
158
+ import { defineConfig } from 'vitest/config';
159
+
160
+ export default defineConfig({
161
+ test: {
162
+ globals: true,
163
+ environment: 'node', // or 'jsdom' for web
164
+ include: ['tests/unit/**/*.test.ts', 'tests/integration/**/*.test.ts'],
165
+ exclude: ['tests/e2e/**/*'],
166
+ },
167
+ });
168
+ ```
169
+
170
+ ### playwright.config.ts
171
+ ```typescript
172
+ import { defineConfig, devices } from '@playwright/test';
173
+
174
+ export default defineConfig({
175
+ testDir: './tests/e2e',
176
+ fullyParallel: true,
177
+ forbidOnly: !!process.env.CI,
178
+ retries: process.env.CI ? 2 : 0,
179
+ reporter: [['html'], ['list']],
180
+ use: {
181
+ baseURL: 'http://localhost:4000', // TEST port, not dev port
182
+ trace: 'on-first-retry',
183
+ screenshot: 'only-on-failure',
184
+ },
185
+ projects: [
186
+ { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
187
+ ],
188
+ webServer: [
189
+ {
190
+ command: 'pnpm dev:test:website',
191
+ port: 4000,
192
+ reuseExistingServer: !process.env.CI,
193
+ timeout: 30_000,
194
+ },
195
+ ],
196
+ });
197
+ ```
198
+
199
+ ### package.json test scripts (REQUIRED in every project)
200
+ ```json
201
+ {
202
+ "scripts": {
203
+ "dev:test:website": "PORT=4000 tsx watch src/index.ts",
204
+ "dev:test:api": "PORT=4010 tsx watch src/index.ts",
205
+ "test": "pnpm test:unit && pnpm test:e2e",
206
+ "test:unit": "vitest run",
207
+ "test:unit:watch": "vitest",
208
+ "test:coverage": "vitest run --coverage",
209
+ "test:e2e": "pnpm test:kill-ports && playwright test",
210
+ "test:e2e:ui": "pnpm test:kill-ports && playwright test --ui",
211
+ "test:e2e:headed": "pnpm test:kill-ports && playwright test --headed",
212
+ "test:e2e:report": "playwright show-report",
213
+ "test:kill-ports": "lsof -ti:4000,4010,4020 | xargs kill -9 2>/dev/null || true"
214
+ }
215
+ }
216
+ ```
217
+
218
+ **CRITICAL: `test:kill-ports` runs BEFORE every E2E test command.** This prevents "port already in use" failures. Never skip this step.
219
+
220
+ ### tsconfig.json (minimum)
221
+ ```json
222
+ {
223
+ "compilerOptions": {
224
+ "target": "ES2022",
225
+ "module": "ESNext",
226
+ "moduleResolution": "bundler",
227
+ "strict": true,
228
+ "noUncheckedIndexedAccess": true,
229
+ "noImplicitOverride": true,
230
+ "esModuleInterop": true,
231
+ "skipLibCheck": true
232
+ }
233
+ }
234
+ ```
235
+
236
+ ## Node.js Entry Point Requirements
237
+
238
+ Add to EVERY Node.js entry point. If the project uses StrictDB, use `gracefulShutdown` to close pools before exit:
239
+
240
+ ```typescript
241
+ // WITH StrictDB (projects using StrictDB)
242
+ import { gracefulShutdown } from 'strictdb';
243
+
244
+ process.on('SIGTERM', () => gracefulShutdown(0));
245
+ process.on('SIGINT', () => gracefulShutdown(0));
246
+ process.on('uncaughtException', (err) => {
247
+ console.error('Uncaught Exception:', err);
248
+ gracefulShutdown(1);
249
+ });
250
+ process.on('unhandledRejection', (reason) => {
251
+ console.error('Unhandled Rejection:', reason);
252
+ gracefulShutdown(1);
253
+ });
254
+ ```
255
+
256
+ ```typescript
257
+ // WITHOUT StrictDB (no database projects)
258
+ process.on('unhandledRejection', (reason, promise) => {
259
+ console.error('Unhandled Rejection:', reason);
260
+ process.exit(1);
261
+ });
262
+
263
+ process.on('uncaughtException', (error) => {
264
+ console.error('Uncaught Exception:', error);
265
+ process.exit(1);
266
+ });
267
+ ```
268
+
269
+
270
+ > SEO: for any web (HTML-serving) project, read and apply `../shared/seo.md` before the framework-specific rules below.
271
+
272
+ ## Framework-Specific Rules
273
+
274
+ ### Vite + React
275
+ - Use Vite's built-in HMR (no config needed)
276
+ - Add `@vitejs/plugin-react` or `@vitejs/plugin-react-swc` (SWC is faster)
277
+ - Use path aliases: `"@/*": ["./src/*"]` in tsconfig
278
+ - Vitest shares Vite config — zero extra setup
279
+
280
+ ### Next.js (App Router)
281
+ - Use App Router (NOT Pages Router)
282
+ - Create `src/app/` directory structure
283
+ - Use Server Components by default, `"use client"` only when needed
284
+ - Strict mode in next.config
285
+ - Use `metadata` export for SEO (not `<Head>`)
286
+
287
+ ### Fastify
288
+ - Use `@fastify/type-provider-typebox` for schema validation
289
+ - Register routes as plugins for encapsulation
290
+ - Use `fastify-swagger` for auto-generated API docs
291
+ - All routes under `/api/v1/` prefix
292
+
293
+ ### Vue 3
294
+
295
+ **CLI scaffold:** `npm create vue@latest PROJECT -- --typescript --router --pinia`
296
+
297
+ After scaffold:
298
+ - Copy `.claude/` — only commands with `scope: project` in frontmatter (skills, hooks, settings.json copied in full)
299
+ - Add `project-docs/`, CLAUDE.md, CLAUDE.local.md, `.env` files
300
+ - Vitest is included by default from `create vue`
301
+
302
+ **CLAUDE.md rules for Vue 3 projects:**
303
+ ```markdown
304
+ ### Vue 3 Rules
305
+ - Composition API ONLY — never use Options API in new code
306
+ - ALWAYS use `<script setup>` syntax (not `setup()` function)
307
+ - Type defineProps and defineEmits: `defineProps<{ title: string }>()`
308
+ - Use `ref()` for primitives, `reactive()` for objects
309
+ - Prefer `computed()` over methods for derived state
310
+ - Use `watchEffect()` over `watch()` when watching all dependencies
311
+ ```
312
+
313
+ ### Nuxt
314
+
315
+ **CLI scaffold:** `npx nuxi@latest init PROJECT --package-manager pnpm`
316
+
317
+ After scaffold:
318
+ - Copy `.claude/` — only commands with `scope: project` in frontmatter (skills, hooks, settings.json copied in full)
319
+ - Add `project-docs/`, CLAUDE.md, CLAUDE.local.md, `.env` files
320
+ - Vitest and Playwright added via `npx nuxi module add @nuxt/test-utils`
321
+
322
+ **CLAUDE.md rules for Nuxt projects:**
323
+ ```markdown
324
+ ### Nuxt Rules
325
+ - Use auto-imports — do NOT manually import Vue composables or Nuxt utils
326
+ - Use `useFetch()` / `useAsyncData()` for data fetching — NEVER raw `fetch` in components
327
+ - API routes go in `server/api/` — file-based routing, no manual route registration
328
+ - Use `definePageMeta()` for page-level metadata (layout, middleware)
329
+ - `useState()` for shared reactive state across components
330
+ ```
331
+
332
+ ### Svelte / SvelteKit
333
+
334
+ **CLI scaffold:** `npx sv create PROJECT` (select TypeScript skeleton)
335
+
336
+ After scaffold:
337
+ - Copy `.claude/` — only commands with `scope: project` in frontmatter (skills, hooks, settings.json copied in full)
338
+ - Add `project-docs/`, CLAUDE.md, CLAUDE.local.md, `.env` files
339
+ - `sv create` includes Vitest + Playwright if selected during setup
340
+
341
+ **CLAUDE.md rules for Svelte/SvelteKit projects:**
342
+ ```markdown
343
+ ### Svelte Rules
344
+ - Use Runes syntax: `$state()`, `$derived()`, `$effect()` — not legacy `$:` reactive statements
345
+ - Use `$props()` for component props
346
+ - SvelteKit: use `+page.ts` / `+page.server.ts` load functions for data fetching
347
+ - SvelteKit: use form actions (`+page.server.ts` `actions`) for mutations
348
+ - SvelteKit: use `$app/environment` for environment detection, NOT `process.env`
349
+ ```
350
+
351
+ ### Angular
352
+
353
+ **CLI scaffold:** `npx @angular/cli new PROJECT --style=scss --routing --ssr=false`
354
+
355
+ After scaffold:
356
+ - Copy `.claude/` — only commands with `scope: project` in frontmatter (skills, hooks, settings.json copied in full)
357
+ - Add `project-docs/`, CLAUDE.md, CLAUDE.local.md, `.env` files
358
+ - Angular includes Jasmine by default — optionally add Vitest with `@analogjs/vitest-angular`
359
+ - Add Playwright for E2E: `npm init playwright@latest`
360
+
361
+ **CLAUDE.md rules for Angular projects:**
362
+ ```markdown
363
+ ### Angular Rules
364
+ - Standalone components ONLY — never use NgModule for new components
365
+ - Use Angular Signals (`signal()`, `computed()`, `effect()`) for reactive state
366
+ - Use `inject()` for dependency injection — not constructor injection
367
+ - Use `@defer` for lazy loading heavy components
368
+ - Template syntax: use `@if`/`@for`/`@switch` (new control flow) — not `*ngIf`/`*ngFor`
369
+ ```
370
+
371
+ ### Astro
372
+ - Use content collections for structured content
373
+ - Islands architecture: interactive components only where needed
374
+ - Built-in image optimization with `<Image>` component
375
+
376
+ ### Python
377
+ - Create `pyproject.toml` (not setup.py)
378
+ - Use `src/` layout
379
+ - Include `requirements.txt` AND `requirements-dev.txt`
380
+
381
+ ### Docker
382
+ - Multi-stage builds ALWAYS
383
+ - Never run as root (create service-specific user)
384
+ - Include health checks
385
+ - COPY package.json first for layer caching
386
+ - For monorepos: build shared packages first, copy dist into deployed node_modules
387
+
388
+ ### Docker Multi-Stage Template
389
+ ```dockerfile
390
+ # Stage 1: Builder
391
+ FROM node:20-alpine AS builder
392
+ WORKDIR /app
393
+
394
+ # Install package manager
395
+ RUN corepack enable && corepack prepare pnpm@latest --activate
396
+
397
+ # Install dependencies (cached layer)
398
+ COPY package.json pnpm-lock.yaml ./
399
+ RUN pnpm install --frozen-lockfile
400
+
401
+ # Build args for Next.js (baked at build time)
402
+ ARG NEXT_PUBLIC_RYBBIT_SITE_ID
403
+ ARG NEXT_PUBLIC_RYBBIT_URL
404
+ ENV NEXT_PUBLIC_RYBBIT_SITE_ID=$NEXT_PUBLIC_RYBBIT_SITE_ID
405
+ ENV NEXT_PUBLIC_RYBBIT_URL=$NEXT_PUBLIC_RYBBIT_URL
406
+
407
+ # Copy source and build
408
+ COPY . .
409
+ RUN pnpm build
410
+
411
+ # Stage 2: Runner
412
+ FROM node:20-alpine AS runner
413
+ WORKDIR /app
414
+ ENV NODE_ENV=production
415
+
416
+ # Non-root user
417
+ RUN addgroup --system --gid 1001 appgroup && \
418
+ adduser --system --uid 1001 appuser
419
+ USER appuser
420
+
421
+ # Copy built artifacts
422
+ COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
423
+ COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
424
+ COPY --from=builder --chown=appuser:appgroup /app/package.json ./
425
+
426
+ EXPOSE 3000
427
+ CMD ["node", "dist/server.js"]
428
+ ```
429
+