create-carlonicora-app 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 (149) hide show
  1. package/LICENSE +675 -0
  2. package/README.md +104 -0
  3. package/bin/cli.js +3 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +92 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/git.d.ts +7 -0
  9. package/dist/git.d.ts.map +1 -0
  10. package/dist/git.js +80 -0
  11. package/dist/git.js.map +1 -0
  12. package/dist/index.d.ts +5 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +5 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/prompts.d.ts +5 -0
  17. package/dist/prompts.d.ts.map +1 -0
  18. package/dist/prompts.js +30 -0
  19. package/dist/prompts.js.map +1 -0
  20. package/dist/replacer.d.ts +9 -0
  21. package/dist/replacer.d.ts.map +1 -0
  22. package/dist/replacer.js +11 -0
  23. package/dist/replacer.js.map +1 -0
  24. package/dist/scaffold.d.ts +3 -0
  25. package/dist/scaffold.d.ts.map +1 -0
  26. package/dist/scaffold.js +79 -0
  27. package/dist/scaffold.js.map +1 -0
  28. package/dist/types/index.d.ts +16 -0
  29. package/dist/types/index.d.ts.map +1 -0
  30. package/dist/types/index.js +2 -0
  31. package/dist/types/index.js.map +1 -0
  32. package/dist/utils/files.d.ts +6 -0
  33. package/dist/utils/files.d.ts.map +1 -0
  34. package/dist/utils/files.js +103 -0
  35. package/dist/utils/files.js.map +1 -0
  36. package/dist/utils/logger.d.ts +12 -0
  37. package/dist/utils/logger.d.ts.map +1 -0
  38. package/dist/utils/logger.js +35 -0
  39. package/dist/utils/logger.js.map +1 -0
  40. package/dist/utils/validation.d.ts +6 -0
  41. package/dist/utils/validation.d.ts.map +1 -0
  42. package/dist/utils/validation.js +63 -0
  43. package/dist/utils/validation.js.map +1 -0
  44. package/package.json +52 -0
  45. package/template/.env.example +159 -0
  46. package/template/.github/workflows/check-library-updates.yml +71 -0
  47. package/template/.github/workflows/dev.yml +63 -0
  48. package/template/.github/workflows/pull-request.yml +55 -0
  49. package/template/.gitmodules +6 -0
  50. package/template/.husky/pre-commit +1 -0
  51. package/template/.husky/pre-push +1 -0
  52. package/template/.prettierignore +1 -0
  53. package/template/.prettierrc +13 -0
  54. package/template/.releaserc +134 -0
  55. package/template/.vscode/settings.json +16 -0
  56. package/template/CHANGELOG.md +0 -0
  57. package/template/CLAUDE.md +34 -0
  58. package/template/DOCKER.md +1591 -0
  59. package/template/Dockerfile +228 -0
  60. package/template/README.md +1 -0
  61. package/template/apps/api/.prettierrc +12 -0
  62. package/template/apps/api/eslint.config.mjs +54 -0
  63. package/template/apps/api/jest.config.js +29 -0
  64. package/template/apps/api/nest-cli.json +15 -0
  65. package/template/apps/api/package.json +155 -0
  66. package/template/apps/api/src/config/config.ts +17 -0
  67. package/template/apps/api/src/config/enums/job.name.ts +6 -0
  68. package/template/apps/api/src/config/enums/queue.id.ts +3 -0
  69. package/template/apps/api/src/config/interfaces/config.interface.ts +3 -0
  70. package/template/apps/api/src/features/features.modules.ts +6 -0
  71. package/template/apps/api/src/i18n/en/notifications.json +3 -0
  72. package/template/apps/api/src/main.ts +23 -0
  73. package/template/apps/api/src/neo4j.migrations/20250901_001.ts +33 -0
  74. package/template/apps/api/src/neo4j.migrations/20250901_002.ts +90 -0
  75. package/template/apps/api/src/neo4j.migrations/20250901_003.ts +57 -0
  76. package/template/apps/api/src/neo4j.migrations/20250901_004.ts +32 -0
  77. package/template/apps/api/src/neo4j.migrations/queries/migration.queries.ts +49 -0
  78. package/template/apps/api/src/types/langchain.d.ts +56 -0
  79. package/template/apps/api/tsconfig.build.json +4 -0
  80. package/template/apps/api/tsconfig.json +38 -0
  81. package/template/apps/web/.swcrc +26 -0
  82. package/template/apps/web/components.json +21 -0
  83. package/template/apps/web/eslint.config.mjs +33 -0
  84. package/template/apps/web/global.d.ts +7 -0
  85. package/template/apps/web/messages/en.json +249 -0
  86. package/template/apps/web/next.config.js +50 -0
  87. package/template/apps/web/package.json +146 -0
  88. package/template/apps/web/playwright.config.ts +86 -0
  89. package/template/apps/web/postcss.config.mjs +5 -0
  90. package/template/apps/web/public/sw.js +32 -0
  91. package/template/apps/web/src/app/[locale]/(admin)/administration/companies/[id]/page.tsx +46 -0
  92. package/template/apps/web/src/app/[locale]/(admin)/administration/companies/page.tsx +23 -0
  93. package/template/apps/web/src/app/[locale]/(admin)/layout.tsx +49 -0
  94. package/template/apps/web/src/app/[locale]/(auth)/activation/[code]/page.tsx +13 -0
  95. package/template/apps/web/src/app/[locale]/(auth)/auth/page.tsx +11 -0
  96. package/template/apps/web/src/app/[locale]/(auth)/invitation/[code]/page.tsx +7 -0
  97. package/template/apps/web/src/app/[locale]/(auth)/layout.tsx +9 -0
  98. package/template/apps/web/src/app/[locale]/(auth)/login/page.tsx +6 -0
  99. package/template/apps/web/src/app/[locale]/(auth)/logout/page.tsx +5 -0
  100. package/template/apps/web/src/app/[locale]/(auth)/register/page.tsx +6 -0
  101. package/template/apps/web/src/app/[locale]/(auth)/reset/[code]/page.tsx +7 -0
  102. package/template/apps/web/src/app/[locale]/(main)/(foundations)/notifications/page.tsx +9 -0
  103. package/template/apps/web/src/app/[locale]/(main)/(foundations)/roles/[id]/page.tsx +23 -0
  104. package/template/apps/web/src/app/[locale]/(main)/(foundations)/roles/page.tsx +12 -0
  105. package/template/apps/web/src/app/[locale]/(main)/(foundations)/users/[id]/error.tsx +14 -0
  106. package/template/apps/web/src/app/[locale]/(main)/(foundations)/users/[id]/loading.tsx +21 -0
  107. package/template/apps/web/src/app/[locale]/(main)/(foundations)/users/[id]/page.tsx +46 -0
  108. package/template/apps/web/src/app/[locale]/(main)/(foundations)/users/page.tsx +17 -0
  109. package/template/apps/web/src/app/[locale]/(main)/error.tsx +62 -0
  110. package/template/apps/web/src/app/[locale]/(main)/layout.tsx +40 -0
  111. package/template/apps/web/src/app/[locale]/(main)/page.tsx +41 -0
  112. package/template/apps/web/src/app/[locale]/layout.tsx +54 -0
  113. package/template/apps/web/src/app/globals.css +256 -0
  114. package/template/apps/web/src/config/BootstrapProvider.tsx +13 -0
  115. package/template/apps/web/src/config/Bootstrapper.ts +77 -0
  116. package/template/apps/web/src/config/env.ts +51 -0
  117. package/template/apps/web/src/config/middleware-env.ts +14 -0
  118. package/template/apps/web/src/enums/feature.ids.ts +3 -0
  119. package/template/apps/web/src/features/common/components/containers/IndexContainer.tsx +11 -0
  120. package/template/apps/web/src/features/common/components/details/LayoutDetails.tsx +33 -0
  121. package/template/apps/web/src/features/common/components/navigations/CommonSidebar.tsx +233 -0
  122. package/template/apps/web/src/features/common/components/navigations/CreationDropDown.tsx +117 -0
  123. package/template/apps/web/src/features/common/components/navigations/UserSidebarFooter.tsx +115 -0
  124. package/template/apps/web/src/features/common/components/navigations/VersionDisplay.tsx +18 -0
  125. package/template/apps/web/src/features/common/contexts/ErrorContext.tsx +62 -0
  126. package/template/apps/web/src/i18n/request.ts +13 -0
  127. package/template/apps/web/src/i18n/routing.ts +9 -0
  128. package/template/apps/web/src/i18n/useDateFnsLocale.ts +15 -0
  129. package/template/apps/web/src/proxy.ts +107 -0
  130. package/template/apps/web/src/server-actions/auth-cookies.ts +134 -0
  131. package/template/apps/web/src/types/modules.d.ts +10 -0
  132. package/template/apps/web/src/utils/metadata.ts +50 -0
  133. package/template/apps/web/src/utils/revalidation.ts +7 -0
  134. package/template/apps/web/tsconfig.json +51 -0
  135. package/template/docker-compose.yml +211 -0
  136. package/template/package.json +72 -0
  137. package/template/packages/nestjs-neo4jsonapi/.gitkeep +0 -0
  138. package/template/packages/nextjs-jsonapi/.gitkeep +0 -0
  139. package/template/packages/shared/package.json +23 -0
  140. package/template/packages/shared/src/const/roles.id.ts +5 -0
  141. package/template/packages/shared/src/const/system.roles.id.ts +4 -0
  142. package/template/packages/shared/src/index.ts +1 -0
  143. package/template/packages/shared/tsconfig.json +10 -0
  144. package/template/packages/shared/tsup.config.ts +16 -0
  145. package/template/pnpm-workspace.yaml +3 -0
  146. package/template/tsconfig.base.json +62 -0
  147. package/template/tsconfig.json +12 -0
  148. package/template/turbo.json +88 -0
  149. package/template/versions.production.json +4 -0
@@ -0,0 +1,1591 @@
1
+ # Docker Setup Guide
2
+
3
+ Complete guide for running {{name}} with Docker Compose, including both development and production configurations.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Overview](#overview)
8
+ - [Service Architecture](#service-architecture)
9
+ - [Prerequisites](#prerequisites)
10
+ - [Quick Start](#quick-start)
11
+ - [Development Mode](#development-mode)
12
+ - [Production Mode](#production-mode)
13
+ - [Deployment Strategies](#deployment-strategies)
14
+ - [Horizontal Scaling Guide](#horizontal-scaling-guide)
15
+ - [Architecture](#architecture)
16
+ - [Critical Configuration](#critical-configuration)
17
+ - [Environment Variables](#environment-variables)
18
+ - [Troubleshooting](#troubleshooting)
19
+ - [Advanced Topics](#advanced-topics)
20
+
21
+ ## Overview
22
+
23
+ The {{name}} monorepo uses Docker Compose to run three application services:
24
+
25
+ - **API** (NestJS) - Backend API server on port 3400
26
+ - **Worker** (NestJS) - Background job processor
27
+ - **Web** (Next.js) - Frontend application on port 3401
28
+
29
+ **Infrastructure Services:** Neo4j, Redis, and MinIO are expected to run **externally** and are configured via environment variables in `.env`. They are NOT included in the docker-compose.yml by default.
30
+
31
+ ## Service Architecture
32
+
33
+ {{name}} is designed as a microservices architecture with three independent services that can be deployed together or separately based on your scaling needs.
34
+
35
+ ### Service Responsibilities
36
+
37
+ #### API Service (NestJS)
38
+ **What it does:**
39
+ - REST API endpoints for all business logic
40
+ - User authentication and authorization (JWT)
41
+ - Real-time database queries (Neo4j)
42
+ - Request validation and rate limiting
43
+ - CORS handling
44
+ - Caching frequently accessed data (Redis)
45
+
46
+ **When to scale:**
47
+ - High number of concurrent users
48
+ - Slow API response times (>200ms)
49
+ - CPU usage consistently >80%
50
+ - Many requests per second (>500 req/sec)
51
+
52
+ **Resource profile:** CPU-intensive, stateless (easy to scale horizontally)
53
+
54
+ #### Worker Service (NestJS)
55
+ **What it does:**
56
+ - Background job processing (BullMQ via Redis)
57
+ - Email sending (notifications, reports)
58
+ - Data processing and transformations
59
+ - Scheduled tasks (cron jobs)
60
+ - Heavy computations that shouldn't block API responses
61
+ - Bulk operations (imports, exports)
62
+
63
+ **When to scale:**
64
+ - Redis queue backlog growing
65
+ - Jobs taking longer to start
66
+ - Email delivery delays
67
+ - Background tasks timing out
68
+
69
+ **Resource profile:** Mixed workload, stateless, processes jobs from shared Redis queue
70
+
71
+ #### Web Service (Next.js)
72
+ **What it does:**
73
+ - Server-Side Rendering (SSR) for dynamic pages
74
+ - Static Site Generation (SSG) for cached pages
75
+ - Frontend React application
76
+ - Serving static assets (images, JS, CSS)
77
+ - API proxy for browser requests
78
+
79
+ **When to scale:**
80
+ - High website traffic
81
+ - Slow page load times
82
+ - Server timeouts during traffic spikes
83
+ - Geographic distribution needs
84
+
85
+ **Resource profile:** Memory-intensive (SSR), stateless (can be cached with CDN)
86
+
87
+ ### Why Separate Services?
88
+
89
+ **Independent Scaling**
90
+ - Scale only the service experiencing load
91
+ - API can handle 1000s of requests while Workers process heavy jobs
92
+ - Web can scale for traffic without affecting API capacity
93
+
94
+ **Resource Optimization**
95
+ - API needs more CPU for request processing
96
+ - Workers need steady CPU for long-running jobs
97
+ - Web needs memory for SSR but can be cached with CDN
98
+ - Deploy services on appropriately-sized servers
99
+
100
+ **Fault Isolation**
101
+ - Worker crash doesn't affect API availability
102
+ - API issues don't block background job processing
103
+ - Web server problems don't impact API-to-API communication
104
+
105
+ **Geographic Distribution**
106
+ - Deploy Web servers closer to users (multiple regions)
107
+ - Keep API + Workers near database (low latency)
108
+ - Reduce costs by not replicating heavy backend services
109
+
110
+ **Cost Efficiency**
111
+ - Run fewer Workers during low-activity hours
112
+ - Scale API during business hours
113
+ - Keep Web instances minimal with CDN for static content
114
+
115
+ ### Shared Infrastructure
116
+
117
+ All three services share access to:
118
+ - **Neo4j** (Database) - All services read/write data
119
+ - **Redis** (Cache & Queue) - API caches data, Workers consume job queue
120
+ - **MinIO/S3** (Storage) - All services store/retrieve files
121
+
122
+ This shared infrastructure must be:
123
+ - Highly available (avoid single point of failure)
124
+ - Network-accessible from all service instances
125
+ - Properly secured (firewalls, authentication)
126
+
127
+ ## Prerequisites
128
+
129
+ 1. **Docker Desktop** or **Docker Engine + Docker Compose**
130
+ 2. **External Infrastructure** running:
131
+ - Neo4j (Graph Database)
132
+ - Redis (Cache & Queue)
133
+ - MinIO or S3 (Object Storage)
134
+ 3. **Configured .env file** with all connection strings
135
+
136
+ ## Quick Start
137
+
138
+ ### 1. Configure Environment
139
+
140
+ Create/edit your `.env` file in the project root with these **REQUIRED** variables:
141
+
142
+ ```bash
143
+ # API Configuration (REQUIRED)
144
+ API_PORT=3400
145
+ API_URL=http://localhost:3400/
146
+
147
+ # Web Configuration (REQUIRED)
148
+ PORT=3401
149
+ APP_URL=http://localhost:3401/
150
+ NEXT_PUBLIC_API_URL=http://localhost:3400/
151
+ NEXT_PUBLIC_ADDRESS=http://localhost:3401
152
+
153
+ # Database (REQUIRED)
154
+ NEO4J_URI=bolt://localhost:7687
155
+ NEO4J_USER=neo4j
156
+ NEO4J_PASSWORD=your-password
157
+ NEO4J_DATABASE=your-database
158
+
159
+ # Cache & Queue (REQUIRED)
160
+ REDIS_HOST=localhost
161
+ REDIS_PORT=6379
162
+ REDIS_PASSWORD=your-redis-password
163
+
164
+ # Object Storage (REQUIRED)
165
+ S3_ENDPOINT=your-endpoint
166
+ S3_BUCKET=your-bucket
167
+ S3_ACCESS_KEY_ID=your-access-key
168
+ S3_SECRET_ACCESS_KEY=your-secret-key
169
+ S3_REGION=your-region
170
+
171
+ # Authentication (REQUIRED)
172
+ JWT_SECRET=your-jwt-secret-min-32-chars
173
+
174
+ # VAPID for Web Push (REQUIRED)
175
+ VAPID_PUBLIC_KEY=your-public-key
176
+ VAPID_PRIVATE_KEY=your-private-key
177
+ NEXT_PUBLIC_VAPID_PUBLIC_KEY=your-public-key
178
+ ```
179
+
180
+ **Note:** See the [Environment Variables](#environment-variables) section below for complete reference including optional variables.
181
+
182
+ ### 2. Build and Start
183
+
184
+ #### Option A: All Services (Monolithic - Recommended for Development)
185
+
186
+ Run all three services together on a single machine:
187
+
188
+ ```bash
189
+ # Build dev-stage images (ensures development targets)
190
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml build --pull
191
+
192
+ # Start all services with development overrides (adds source + shared mounts)
193
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
194
+
195
+ # Or start in background
196
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build
197
+ ```
198
+
199
+ **Use this when:**
200
+ - Local development
201
+ - Testing full stack
202
+ - Small deployments (<1000 users)
203
+ - Single server production
204
+
205
+ #### Option B: Individual Services (Distributed - Recommended for Production)
206
+
207
+ Run specific services for horizontal scaling and distributed deployment. Use only the base `docker-compose.yml` so the container keeps the compiled packages from the image:
208
+
209
+ ```bash
210
+ # API only
211
+ docker compose up --build api
212
+
213
+ # Worker only
214
+ docker compose up --build worker
215
+
216
+ # Web only
217
+ docker compose up --build web
218
+
219
+ # API + Worker (common for backend server)
220
+ docker compose up --build api worker
221
+
222
+ # Multiple instances (scale workers)
223
+ docker compose up --build --scale worker=3
224
+ ```
225
+
226
+ **Use this when:**
227
+ - Scaling specific services based on load
228
+ - Multi-server deployment
229
+ - Independent service updates
230
+ - Resource optimization
231
+
232
+ ### 3. Verify
233
+
234
+ - API: http://localhost:3400
235
+ - Web: http://localhost:3401
236
+ - Workers: Check logs with `docker compose logs worker`
237
+
238
+ ## Development Mode
239
+
240
+ Development mode enables hot-reload for rapid development with live code changes. Combine the base compose file with `docker-compose.dev.yml` to add the necessary source and shared bind mounts.
241
+
242
+ ### Features
243
+
244
+ - **Hot Reload**: Source code is mounted from host, changes reflect immediately
245
+ - **Development Server**: Runs `pnpm dev` with Turbopack
246
+ - **Verbose Logging**: Detailed error messages and stack traces
247
+ - **Source Maps**: Enabled for debugging
248
+
249
+ ### Volume Mounts
250
+
251
+ The following directories are mounted for hot-reload:
252
+
253
+ These mounts are defined in `docker-compose.dev.yml`:
254
+
255
+ ```yaml
256
+ # Web Service
257
+ ./apps/web/src -> /app/apps/web/src
258
+ ./apps/web/public -> /app/apps/web/public
259
+ ./packages/shared -> /app/packages/shared
260
+
261
+ # API Service
262
+ ./apps/api/src -> /app/apps/api/src
263
+ ./packages/shared -> /app/packages/shared
264
+ ```
265
+
266
+ ### Commands
267
+
268
+ ```bash
269
+ # Build development images
270
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml build --pull
271
+
272
+ # Start in development mode (adds dev overrides)
273
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
274
+
275
+ # View logs
276
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f web
277
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f api
278
+
279
+ # Stop services
280
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml down
281
+ ```
282
+
283
+ ### Code Changes
284
+
285
+ When running in development mode:
286
+ - ✅ Code changes in `src/` directories are picked up automatically
287
+ - ✅ No rebuild needed for most changes
288
+ - ⚠️ Changes to `package.json`, `Dockerfile`, or dependencies require rebuild:
289
+ ```bash
290
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml down
291
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml build --no-cache
292
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
293
+ ```
294
+
295
+ ## Production Mode
296
+
297
+ Production mode creates optimized builds with minimal runtime footprint. The base compose file is now production-oriented by default (no override required).
298
+
299
+ ### Features
300
+
301
+ - **Optimized Build**: Pre-built, minified production bundles
302
+ - **No Source Code**: Only compiled output included
303
+ - **Smaller Images**: No development dependencies
304
+ - **Production Runtime**: Runs `pnpm start` for Next.js, optimized NestJS build for API
305
+
306
+ ### Build Process
307
+
308
+ The production build:
309
+ 1. Installs all dependencies
310
+ 2. Builds shared packages
311
+ 3. Builds Next.js application with environment variables
312
+ 4. Builds NestJS API with optimizations
313
+ 5. Creates final image with only production dependencies and built output
314
+
315
+ ### Commands
316
+
317
+ ```bash
318
+ # Build production images (base compose only)
319
+ docker compose build --pull
320
+
321
+ # Start in production mode (do NOT include docker-compose.dev.yml)
322
+ docker compose up --build -d
323
+
324
+ # Check status
325
+ docker compose ps
326
+
327
+ # View logs
328
+ docker compose logs -f
329
+
330
+ # Stop services
331
+ docker compose down
332
+ ```
333
+
334
+ ### Important Notes
335
+
336
+ ⚠️ **Volume Mounts**: No `node_modules` or `.next` volumes are mounted in production; everything ships inside the image to avoid dependency drift.
337
+
338
+ ⚠️ **Environment Variables**: Next.js requires build-time environment variables. If you change `NEXT_PUBLIC_*` variables, you must rebuild:
339
+ ```bash
340
+ docker compose build --no-cache web
341
+ ```
342
+
343
+ ## Deployment Strategies
344
+
345
+ Choose your deployment strategy based on your traffic, budget, and scalability needs.
346
+
347
+ ### Scenario 1: Development (Single Machine)
348
+
349
+ **Setup:** All services on local development machine
350
+
351
+ **Services:** API + Worker + Web (all running)
352
+
353
+ **Use case:**
354
+ - Local development and testing
355
+ - Feature development
356
+ - Debugging full stack
357
+
358
+ **Commands:**
359
+ ```bash
360
+ docker compose up
361
+ ```
362
+
363
+ **Pros:**
364
+ - Simple setup
365
+ - Easy debugging
366
+ - Fast iteration
367
+
368
+ **Cons:**
369
+ - Resource intensive on single machine
370
+ - Not representative of production architecture
371
+
372
+ ---
373
+
374
+ ### Scenario 2: Small Production (Single Server, <1000 Users)
375
+
376
+ **Setup:** All services on one production server
377
+
378
+ **Services:** API + Worker + Web
379
+
380
+ **Architecture:**
381
+ ```
382
+ ┌──────────────────────┐
383
+ │ Single Server │
384
+ │ │
385
+ │ ┌────────────────┐ │
386
+ Users ──────────────┼─►│ Web (3401) │ │
387
+ │ └────────┬───────┘ │
388
+ │ │ │
389
+ │ ┌────────▼───────┐ │
390
+ │ │ API (3400) │ │
391
+ │ └────────┬───────┘ │
392
+ │ │ │
393
+ │ ┌────────▼───────┐ │
394
+ │ │ Worker x1 │ │
395
+ │ └────────┬───────┘ │
396
+ └───────────┼──────────┘
397
+
398
+ ┌───────────▼──────────┐
399
+ │ Neo4j + Redis + MinIO│
400
+ │ (External/Local) │
401
+ └──────────────────────┘
402
+ ```
403
+
404
+ **Commands:**
405
+ ```bash
406
+ docker compose up -d
407
+ ```
408
+
409
+ **Pros:**
410
+ - Simple deployment
411
+ - Low infrastructure cost
412
+ - Easy to manage
413
+
414
+ **Cons:**
415
+ - Limited scalability
416
+ - Single point of failure
417
+ - Resource contention between services
418
+
419
+ **Recommended server:** 4 CPU, 8GB RAM
420
+
421
+ ---
422
+
423
+ ### Scenario 3: Medium Production (Multiple Servers, 1k-10k Users)
424
+
425
+ **Setup:** Backend and frontend on separate servers
426
+
427
+ **Services:**
428
+ - **Server 1:** API + Worker (2-3 worker instances)
429
+ - **Server 2:** Web (with CDN)
430
+
431
+ **Architecture:**
432
+ ```
433
+ ┌──────────────────┐
434
+ │ Load Balancer │
435
+ │ or Nginx │
436
+ └────────┬─────────┘
437
+
438
+ ┌──────────────┼──────────────┐
439
+ │ │ │
440
+ ┌────────▼────────┐ │ ┌───────▼────────┐
441
+ │ Server 1 │ │ │ Server 2 │
442
+ │ (Backend) │ │ │ (Frontend) │
443
+ │ │ │ │ │
444
+ │ ┌─────────────┐ │ │ │ ┌────────────┐ │
445
+ │ │ API (3400) │◄┼─────┼─────┼─│ Web (3401) │ │
446
+ │ └──────┬──────┘ │ │ │ └────────────┘ │
447
+ │ │ │ │ └────────────────┘
448
+ │ ┌──────▼──────┐ │ │
449
+ │ │ Worker x3 │ │ │
450
+ │ └──────┬──────┘ │ │
451
+ └────────┼────────┘ │
452
+ │ │
453
+ ┌────────▼──────────────▼──────────┐
454
+ │ Neo4j + Redis + MinIO │
455
+ │ (Managed/External Services) │
456
+ └──────────────────────────────────┘
457
+ ```
458
+
459
+ **Server 1 Commands:**
460
+ ```bash
461
+ # Backend server
462
+ docker compose up api --scale worker=3 -d
463
+ ```
464
+
465
+ **Server 2 Commands:**
466
+ ```bash
467
+ # Frontend server (configure API_INTERNAL_URL to point to Server 1)
468
+ docker compose up web -d
469
+ ```
470
+
471
+ **Pros:**
472
+ - Better resource allocation
473
+ - Independent scaling
474
+ - Web can use CDN
475
+ - Backend stays near database
476
+
477
+ **Cons:**
478
+ - More complex networking
479
+ - Multiple servers to manage
480
+ - Higher infrastructure cost
481
+
482
+ **Recommended:**
483
+ - Server 1: 4 CPU, 8GB RAM (Backend)
484
+ - Server 2: 2 CPU, 4GB RAM (Frontend + CDN)
485
+
486
+ ---
487
+
488
+ ### Scenario 4: Large Production (High Availability, 10k+ Users)
489
+
490
+ **Setup:** Multiple instances of each service with load balancing
491
+
492
+ **Services:**
493
+ - **API Cluster:** 3+ API instances behind load balancer
494
+ - **Worker Pool:** 5+ workers for parallel processing
495
+ - **Web Cluster:** 2+ web instances with CDN
496
+ - **Infrastructure:** Managed Neo4j cluster, Redis cluster, S3
497
+
498
+ **Architecture:**
499
+ ```
500
+ ┌──────────────────┐
501
+ │ CDN (Cloudflare)│
502
+ └────────┬─────────┘
503
+
504
+ ┌────────▼─────────┐
505
+ │ Load Balancer │
506
+ │ (HAProxy/Nginx) │
507
+ └────────┬─────────┘
508
+
509
+ ┌───────────────┼───────────────┐
510
+ │ │ │
511
+ ┌───────▼──────┐ ┌────▼──────┐ ┌────▼──────┐
512
+ │ Web-1 │ │ Web-2 │ │ Web-3 │
513
+ │ (3401) │ │ (3401) │ │ (3401) │
514
+ └───────┬──────┘ └────┬──────┘ └────┬──────┘
515
+ │ │ │
516
+ └───────────────┼───────────────┘
517
+
518
+ ┌────────▼─────────┐
519
+ │ API Load Bal. │
520
+ └────────┬─────────┘
521
+
522
+ ┌───────────────┼───────────────┐
523
+ │ │ │
524
+ ┌───────▼──────┐ ┌────▼──────┐ ┌────▼──────┐
525
+ │ API-1 │ │ API-2 │ │ API-3 │
526
+ │ (3400) │ │ (3400) │ │ (3400) │
527
+ └───────┬──────┘ └────┬──────┘ └────┬──────┘
528
+ │ │ │
529
+ └───────────────┼───────────────┘
530
+
531
+ ┌───────────────────────┼───────────────┐
532
+ │ │ │
533
+ ┌────▼─────┐ ┌──────────▼──────┐ ┌───────▼──────┐
534
+ │Worker x5 │ │Worker Pool x5 │ │Worker Pool x5│
535
+ │ (Srv 1) │ │ (Srv 2) │ │ (Srv 3) │
536
+ └────┬─────┘ └──────────┬──────┘ └───────┬──────┘
537
+ │ │ │
538
+ └───────────────────┼──────────────────┘
539
+
540
+ ┌───────────────────▼───────────────────┐
541
+ │ Managed Infrastructure │
542
+ │ ┌──────────┐ ┌───────┐ ┌────────┐ │
543
+ │ │Neo4j │ │ Redis │ │ S3 │ │
544
+ │ │ Cluster │ │Cluster│ │ Bucket │ │
545
+ │ └──────────┘ └───────┘ └────────┘ │
546
+ └────────────────────────────────────────┘
547
+ ```
548
+
549
+ **Setup Commands:**
550
+ ```bash
551
+ # Web servers (Server 1-3)
552
+ docker compose up web -d
553
+
554
+ # API servers (Server 4-6)
555
+ docker compose up api -d
556
+
557
+ # Worker servers (Server 7-9)
558
+ docker compose up --scale worker=5 -d
559
+ ```
560
+
561
+ **Pros:**
562
+ - High availability (no single point of failure)
563
+ - Horizontal scalability
564
+ - Geographic distribution possible
565
+ - Fault tolerance
566
+
567
+ **Cons:**
568
+ - Complex setup and management
569
+ - Higher costs
570
+ - Requires load balancer configuration
571
+ - More monitoring needed
572
+
573
+ **Recommended:**
574
+ - Web servers: 2 CPU, 4GB RAM each
575
+ - API servers: 4 CPU, 8GB RAM each
576
+ - Worker servers: 2 CPU, 4GB RAM each
577
+ - Use managed database services
578
+
579
+ ---
580
+
581
+ ### Deployment Decision Matrix
582
+
583
+ | Users | Requests/sec | Jobs/day | Recommended Setup | Estimated Cost |
584
+ |------------|--------------|----------|-----------------------------|-----------------|
585
+ | <1,000 | <100 | <1,000 | Scenario 1: Single Server | $50-100/month |
586
+ | 1k-10k | 100-500 | 1k-10k | Scenario 2: 2 Servers | $200-400/month |
587
+ | 10k-50k | 500-2000 | 10k-100k | Scenario 3: Clustered | $800-1500/month |
588
+ | 50k+ | 2000+ | 100k+ | Scenario 4: Full HA | $2000+/month |
589
+
590
+ ## Horizontal Scaling Guide
591
+
592
+ ### Understanding Service Load Patterns
593
+
594
+ Each service has different scaling characteristics:
595
+
596
+ #### API Service Scaling
597
+
598
+ **Bottleneck Indicators:**
599
+ - Response time >200ms
600
+ - CPU usage >80%
601
+ - High request queue
602
+ - Connection timeouts
603
+
604
+ **Scaling Strategy:**
605
+ ```bash
606
+ # Add more API instances behind load balancer
607
+ # Server 1
608
+ docker compose up api -d
609
+
610
+ # Server 2
611
+ docker compose up api -d
612
+
613
+ # Server 3
614
+ docker compose up api -d
615
+
616
+ # Configure load balancer to distribute across all three
617
+ ```
618
+
619
+ **How it works:**
620
+ - Each API instance is stateless
621
+ - All connect to same Neo4j/Redis/MinIO
622
+ - Load balancer distributes requests (round-robin, least-connections, etc.)
623
+ - Share same JWT_SECRET for authentication
624
+ - No session stickiness needed
625
+
626
+ **When to scale:**
627
+ - CPU consistently >80%
628
+ - Response times degrading
629
+ - >500 requests per second per instance
630
+
631
+ ---
632
+
633
+ #### Worker Service Scaling
634
+
635
+ **Bottleneck Indicators:**
636
+ - Redis queue length growing (>100 jobs)
637
+ - Job wait time increasing
638
+ - Jobs timing out
639
+ - Background tasks delayed
640
+
641
+ **Scaling Strategy:**
642
+ ```bash
643
+ # Scale workers on same server
644
+ docker compose up --scale worker=5 -d
645
+
646
+ # Or distribute across multiple servers
647
+ # Server 1
648
+ docker compose up worker -d
649
+
650
+ # Server 2
651
+ docker compose up worker -d
652
+
653
+ # All workers automatically share the Redis queue
654
+ ```
655
+
656
+ **How it works:**
657
+ - BullMQ (via Redis) automatically distributes jobs
658
+ - Workers pull jobs from shared queue
659
+ - No coordination needed between workers
660
+ - Can run different numbers of workers per server
661
+ - Jobs processed in parallel
662
+
663
+ **When to scale:**
664
+ - Queue length >50 jobs consistently
665
+ - Job processing time >5 minutes average
666
+ - Email/notification delays
667
+ - Scheduled tasks missing deadlines
668
+
669
+ ---
670
+
671
+ #### Web Service Scaling
672
+
673
+ **Bottleneck Indicators:**
674
+ - Slow page loads (>2 seconds)
675
+ - High memory usage (>80%)
676
+ - Server errors during traffic spikes
677
+ - Geographic latency issues
678
+
679
+ **Scaling Strategy:**
680
+ ```bash
681
+ # Add web instances behind load balancer
682
+ # Server 1 (US East)
683
+ docker compose up web -d
684
+
685
+ # Server 2 (US West)
686
+ docker compose up web -d
687
+
688
+ # Server 3 (EU)
689
+ docker compose up web -d
690
+
691
+ # Use CDN (Cloudflare/CloudFront) in front
692
+ ```
693
+
694
+ **How it works:**
695
+ - Each web instance is stateless
696
+ - All call same API endpoint
697
+ - CDN caches static assets
698
+ - Load balancer with optional sticky sessions
699
+ - Geographic distribution reduces latency
700
+
701
+ **When to scale:**
702
+ - Memory usage >80%
703
+ - Page load time >1 second
704
+ - >100 concurrent users per instance
705
+ - Geographic distribution needed
706
+
707
+ ---
708
+
709
+ ### Capacity Planning Table
710
+
711
+ | Service | Per Instance Capacity | When to Add Instance | Resource per Instance |
712
+ |---------|----------------------|---------------------|----------------------|
713
+ | API | ~500 req/sec | CPU >80% or latency >200ms | 2 CPU, 4GB RAM |
714
+ | Worker | ~10-50 jobs/min | Queue >100 or delay >5min | 1 CPU, 2GB RAM |
715
+ | Web | ~100-200 concurrent users | Memory >80% or load time >1s | 2 CPU, 4GB RAM |
716
+
717
+ ### Multi-Server Configuration Examples
718
+
719
+ #### Backend Server (API + Workers)
720
+
721
+ ```bash
722
+ # Server 1: backend.example.com
723
+ # .env configuration
724
+
725
+ # Point to actual infrastructure
726
+ NEO4J_URI=bolt://neo4j-cluster.internal:7687
727
+ REDIS_HOST=redis-cluster.internal
728
+ S3_ENDPOINT=https://s3.amazonaws.com
729
+
730
+ # API configuration
731
+ API_PORT=3400
732
+ API_URL=https://api.example.com/
733
+
734
+ # Start backend services (production stages baked into image)
735
+ docker compose up --build api --scale worker=3 -d
736
+ ```
737
+
738
+ #### Frontend Server (Web Only)
739
+
740
+ ```bash
741
+ # Server 2: web.example.com
742
+ # .env configuration
743
+
744
+ # Point to backend API
745
+ NEXT_PUBLIC_API_URL=https://api.example.com/
746
+ API_INTERNAL_URL=https://api.example.com/ # External since on different server
747
+
748
+ # Same infrastructure (for session storage, file uploads)
749
+ NEO4J_URI=bolt://neo4j-cluster.internal:7687
750
+ REDIS_HOST=redis-cluster.internal
751
+ S3_ENDPOINT=https://s3.amazonaws.com
752
+
753
+ # Web configuration
754
+ PORT=3401
755
+ APP_URL=https://app.example.com/
756
+ NEXT_PUBLIC_ADDRESS=https://app.example.com
757
+
758
+ # Google API key
759
+ NEXT_PUBLIC_GOOGLE_MAPS_API_KEY="YOUR PLACES(New) API KEY"
760
+
761
+ # Start web service
762
+ docker compose up --build web -d
763
+ ```
764
+
765
+ #### Load Balancer Configuration
766
+
767
+ **Nginx Load Balancer for API:**
768
+ ```nginx
769
+ upstream api_backend {
770
+ least_conn; # Send to server with fewest connections
771
+ server api-server-1.internal:3400;
772
+ server api-server-2.internal:3400;
773
+ server api-server-3.internal:3400;
774
+ }
775
+
776
+ server {
777
+ listen 443 ssl http2;
778
+ server_name api.example.com;
779
+
780
+ ssl_certificate /etc/ssl/api.example.com.crt;
781
+ ssl_certificate_key /etc/ssl/api.example.com.key;
782
+
783
+ location / {
784
+ proxy_pass http://api_backend;
785
+ proxy_set_header Host $host;
786
+ proxy_set_header X-Real-IP $remote_addr;
787
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
788
+ proxy_set_header X-Forwarded-Proto $scheme;
789
+
790
+ # Timeouts
791
+ proxy_connect_timeout 30s;
792
+ proxy_send_timeout 30s;
793
+ proxy_read_timeout 30s;
794
+ }
795
+ }
796
+ ```
797
+
798
+ **Nginx Load Balancer for Web:**
799
+ ```nginx
800
+ upstream web_backend {
801
+ # ip_hash for sticky sessions (optional - depends on your SSR needs)
802
+ server web-server-1.internal:3401;
803
+ server web-server-2.internal:3401;
804
+ }
805
+
806
+ server {
807
+ listen 443 ssl http2;
808
+ server_name app.example.com;
809
+
810
+ ssl_certificate /etc/ssl/app.example.com.crt;
811
+ ssl_certificate_key /etc/ssl/app.example.com.key;
812
+
813
+ location / {
814
+ proxy_pass http://web_backend;
815
+ proxy_set_header Host $host;
816
+ proxy_set_header X-Real-IP $remote_addr;
817
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
818
+ proxy_set_header X-Forwarded-Proto $scheme;
819
+
820
+ # WebSocket support (if needed)
821
+ proxy_http_version 1.1;
822
+ proxy_set_header Upgrade $http_upgrade;
823
+ proxy_set_header Connection "upgrade";
824
+ }
825
+ }
826
+ ```
827
+
828
+ ### Monitoring and Auto-Scaling
829
+
830
+ **Key Metrics to Monitor:**
831
+
832
+ **API:**
833
+ - Request rate (req/sec)
834
+ - Response time (p50, p95, p99)
835
+ - Error rate (5xx responses)
836
+ - CPU and memory usage
837
+
838
+ **Worker:**
839
+ - Queue length (Redis)
840
+ - Job processing time
841
+ - Failed job count
842
+ - Active workers
843
+
844
+ **Web:**
845
+ - Page load time
846
+ - Memory usage
847
+ - Concurrent connections
848
+ - Cache hit rate
849
+
850
+ **Auto-scaling Triggers:**
851
+ - Scale up API when: CPU >75% for 5 minutes
852
+ - Scale up Workers when: Queue length >50 for 10 minutes
853
+ - Scale up Web when: Memory >75% for 5 minutes
854
+ - Scale down: When metrics drop below 40% for 15 minutes
855
+
856
+ ## Architecture
857
+
858
+ ```
859
+ ┌─────────────────────────────────────────────────────────────────┐
860
+ │ Docker Compose Service │
861
+ │ │
862
+ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
863
+ │ │ API │◄────────│ Worker │ │ Web │ │
864
+ │ │ (NestJS) │ │ (NestJS) │ │ (Next.js)│ │
865
+ │ │ Port 3400│ │ │ │ Port 3401│ │
866
+ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
867
+ │ │ │ │ │
868
+ │ │ | │ │
869
+ │ │ │ │ │
870
+ └───────┼────────────────────┼─────────────────────┼──────────────┘
871
+ │ │ │
872
+ └────────────────────┴─────────────────────┘
873
+
874
+ ┌────────────────────┴────────────────────┐
875
+ │ | │
876
+ ┌────▼────┐ ┌──────▼────┐ ┌────▼────┐
877
+ │ Neo4j │ │ Redis │ │ MinIO │
878
+ │Database │ │Cache/Queue│ │ Storage │
879
+ │External │ │ External │ │External │
880
+ └─────────┘ └───────────┘ └─────────┘
881
+ ```
882
+
883
+ ### Request Flow
884
+
885
+ **Browser Request (Client-Side):**
886
+ ```
887
+ Browser → http://localhost:3401 → Web Container → http://localhost:3400 → API Container
888
+ ```
889
+
890
+ **Server-Side Rendering (SSR):**
891
+ ```
892
+ Web Container → http://api:3400 (internal Docker network) → API Container
893
+ ```
894
+
895
+ ## Docker Build Architecture
896
+
897
+ ### Unified Dockerfile Strategy
898
+
899
+ {{name}} uses a **unified Dockerfile** ([Dockerfile](Dockerfile)) that builds all services from a single file. This approach provides significant benefits over separate Dockerfiles:
900
+
901
+ **Benefits:**
902
+ - **Shared Package Built Once**: The `@{{name}}/shared` package is built in a single stage and reused by both API and Web services
903
+ - **Faster CI/CD**: When building multiple services, Docker reuses cached layers from the shared build stages
904
+ - **Consistent Dependencies**: All services use the exact same base image and dependency versions
905
+ - **Reduced Maintenance**: Single source of truth for build configuration
906
+
907
+ **Build Stage Flow:**
908
+ ```
909
+ base
910
+
911
+ workspace-deps (install all dependencies)
912
+
913
+ shared-builder (build @{{name}}/shared ONCE)
914
+ ├→ api-builder → api-production
915
+ └→ web-builder → web-production
916
+ ```
917
+
918
+ **Previous Problem:**
919
+ Before the unified approach, each Dockerfile independently built the shared package:
920
+ - API Dockerfile: Built shared package
921
+ - Web Dockerfile: Built shared package again (duplicate work!)
922
+
923
+ As the shared package grows with more utilities, types, and constants, this duplication becomes increasingly wasteful.
924
+
925
+ **Build Targets:**
926
+ - `api-development`: API with hot-reload for development
927
+ - `api-production`: Optimized API for production
928
+ - `web-development`: Web with hot-reload for development
929
+ - `web-production`: Optimized Web for production
930
+
931
+ **Build Commands:**
932
+ ```bash
933
+ # Build all services (shared package built once, reused)
934
+ docker compose build
935
+
936
+ # Build specific service (still benefits from shared caching)
937
+ docker compose build api
938
+ docker compose build web
939
+ ```
940
+
941
+ ### Shared Package (@{{name}}/shared)
942
+
943
+ The shared package contains common code used by both frontend and backend:
944
+ - TypeScript types and interfaces
945
+ - Enums and constants
946
+ - Utility functions
947
+ - Validation schemas
948
+
949
+ **Development Mode:**
950
+ - Source files are mounted via volumes ([docker-compose.dev.yml](docker-compose.dev.yml))
951
+ - TypeScript path mapping resolves to source: `./packages/shared/src`
952
+ - Changes to shared package require container restart
953
+ - Hot-reload works for app-specific code (API/Web src directories)
954
+
955
+ **Production Mode:**
956
+ - Shared package is built during Docker build
957
+ - Compiled output is included in final images
958
+ - No source files in production containers
959
+
960
+ **Import Strategy:**
961
+ ```typescript
962
+ // Both API and Web import from the package
963
+ import { EquipmentStatus } from '@{{name}}/shared';
964
+
965
+ // TypeScript resolves via tsconfig paths during development
966
+ // Runtime uses built package.json main field in production
967
+ ```
968
+
969
+ ### .dockerignore Explanation
970
+
971
+ The [.dockerignore](.dockerignore) file excludes certain directories from the Docker build context:
972
+
973
+ ```dockerignore
974
+ dist/
975
+ **/dist/
976
+ node_modules/
977
+ **/node_modules/
978
+ .next/
979
+ **/.next/
980
+ ```
981
+
982
+ **Why this is correct:**
983
+ - ✅ `dist/` folders are **created during the Docker build**, not copied from host
984
+ - ✅ Multi-stage builds preserve `dist/` between stages (COPY --from=builder)
985
+ - ✅ Excluding these from the initial context reduces build context size
986
+ - ✅ Prevents stale local builds from interfering with container builds
987
+
988
+ **What gets excluded:**
989
+ - Host `node_modules/` (will be rebuilt inside container)
990
+ - Host `dist/` folders (will be built fresh inside container)
991
+ - Host `.next/` build output (rebuilt during container build)
992
+
993
+ **What gets preserved:**
994
+ - `dist/` folders created inside Docker during build stages
995
+ - COPY commands between stages work regardless of .dockerignore
996
+
997
+ ### Health Checks
998
+
999
+ All services have health checks configured to ensure proper orchestration:
1000
+
1001
+ **API Service:**
1002
+ ```yaml
1003
+ healthcheck:
1004
+ test: ["CMD", "node", "-e", "require('http').get({host:'localhost',port:process.env.API_PORT||3400,path:'/version'},(r)=>process.exit(r.statusCode>=200&&r.statusCode<500?0:1))"]
1005
+ interval: 10s
1006
+ timeout: 5s
1007
+ retries: 3
1008
+ start_period: 40s
1009
+ ```
1010
+
1011
+ **Web Service:**
1012
+ ```yaml
1013
+ healthcheck:
1014
+ test: ["CMD", "node", "-e", "require('http').get({host:'localhost',port:process.env.PORT||3401,path:'/'},(r)=>process.exit(r.statusCode>=200&&r.statusCode<500?0:1))"]
1015
+ interval: 10s
1016
+ timeout: 5s
1017
+ retries: 3
1018
+ start_period: 40s
1019
+ ```
1020
+
1021
+ **Worker Service:**
1022
+ ```yaml
1023
+ healthcheck:
1024
+ test: ["CMD", "pgrep", "-f", "node.*dist/main.*worker"]
1025
+ interval: 10s
1026
+ timeout: 5s
1027
+ retries: 3
1028
+ start_period: 30s
1029
+ ```
1030
+
1031
+ **Benefits:**
1032
+ - Docker knows when services are actually ready (not just running)
1033
+ - `docker compose ps` shows health status
1034
+ - Orchestration tools (Kubernetes, Coolify) can use health checks for:
1035
+ - Rolling updates
1036
+ - Load balancer registration
1037
+ - Automatic restarts
1038
+ - Readiness probes
1039
+
1040
+ **Checking Health:**
1041
+ ```bash
1042
+ # View health status
1043
+ docker compose ps
1044
+
1045
+ # Should show: (healthy) next to running services
1046
+ ```
1047
+
1048
+ ### Runtime Dependencies
1049
+
1050
+ **Image Processing Libraries:**
1051
+ Both API and Web services include image processing dependencies:
1052
+
1053
+ ```dockerfile
1054
+ RUN apk add --no-cache cairo jpeg pango giflib libwebp
1055
+ ```
1056
+
1057
+ **Why both need them:**
1058
+ - **API**: Backend image processing, file uploads, document generation
1059
+ - **Web**: Next.js Image Optimization (sharp) for server-side image resizing
1060
+
1061
+ **Next.js Image Optimization:**
1062
+ Next.js uses `sharp` at runtime for optimizing images during server-side rendering. Without these dependencies, image optimization would fail with:
1063
+ ```
1064
+ Error: Cannot find module 'sharp'
1065
+ ```
1066
+
1067
+ **Size Impact:**
1068
+ - Combined size: ~15-20MB per image
1069
+ - Required for production functionality
1070
+ - Cannot be removed without breaking features
1071
+
1072
+ ## Critical Configuration
1073
+
1074
+ ### Docker Networking for Next.js SSR
1075
+
1076
+ **THE PROBLEM:**
1077
+ When Next.js performs server-side rendering inside a Docker container, `localhost` refers to the web container itself, NOT the API container.
1078
+
1079
+ **THE SOLUTION:**
1080
+ The configuration uses different URLs for client-side vs server-side requests:
1081
+
1082
+ ```bash
1083
+ # In .env
1084
+ NEXT_PUBLIC_API_URL=http://localhost:3400/ # Used by browser
1085
+ API_INTERNAL_URL=http://api:3400/ # Used by SSR (defaults to this)
1086
+ ```
1087
+
1088
+ **How It Works:**
1089
+ - `apps/web/src/config/env.ts` checks if code is running server-side (`typeof window === 'undefined'`)
1090
+ - If server-side: Uses `API_INTERNAL_URL` (Docker service name `api`)
1091
+ - If client-side: Uses `NEXT_PUBLIC_API_URL` (localhost for browser)
1092
+
1093
+ ### ⚠️ CRITICAL: API_INTERNAL_URL for Multi-Server Deployments
1094
+
1095
+ **When services run on the SAME server (single docker-compose):**
1096
+ ```bash
1097
+ API_INTERNAL_URL=http://api:3400/ # Docker service name works
1098
+ ```
1099
+ The web container can reach the API container via Docker's internal network using the service name.
1100
+
1101
+ **When services run on DIFFERENT servers (distributed):**
1102
+ ```bash
1103
+ # WRONG - This will NOT work:
1104
+ API_INTERNAL_URL=http://api:3400/ # Docker service name doesn't exist across servers
1105
+
1106
+ # CORRECT - Use external URL:
1107
+ API_INTERNAL_URL=https://api.example.com/ # Actual API server URL
1108
+ # OR
1109
+ API_INTERNAL_URL=http://10.0.1.50:3400/ # Internal IP address
1110
+ ```
1111
+
1112
+ **Why This Matters:**
1113
+ - SSR requests from Web service MUST be able to reach the API
1114
+ - If Web is on Server A and API is on Server B, they're on different Docker networks
1115
+ - Docker service names (`api`) only work within the same Docker network
1116
+ - You MUST use the external URL or internal IP address
1117
+
1118
+ **Testing Multi-Server API_INTERNAL_URL:**
1119
+ ```bash
1120
+ # From your web server, test if Web container can reach API
1121
+ docker compose exec web wget -O- --timeout=5 $API_INTERNAL_URL
1122
+
1123
+ # Should return API response, not timeout or connection refused
1124
+ # If it fails, your API_INTERNAL_URL is wrong
1125
+ ```
1126
+
1127
+ **Common Mistakes:**
1128
+ - ❌ Using `http://localhost:3400/` - wrong, localhost is the web container
1129
+ - ❌ Using `http://api:3400/` when services are on different servers
1130
+ - ✅ Using `https://api.example.com/` - correct for distributed
1131
+ - ✅ Using `http://10.0.1.50:3400/` - correct for same network, different servers
1132
+
1133
+ **If you get 500 errors or timeouts on page load:**
1134
+ 1. Verify `API_INTERNAL_URL` is correctly configured for your deployment
1135
+ 2. Check web container can reach API: `docker compose exec web wget -O- $API_INTERNAL_URL`
1136
+ 3. For multi-server: Ensure firewall rules allow web server to reach API server
1137
+ 4. Check both containers have network connectivity to shared infrastructure (Neo4j, Redis, MinIO)
1138
+
1139
+ ### Build Targets
1140
+
1141
+ The compose workflow now selects build targets automatically:
1142
+
1143
+ - **Base file (`docker-compose.yml`)** builds the `production` stage of each Dockerfile. Dependencies are baked into the image and the containers run the compiled output (`node dist/...`, `pnpm ... start`).
1144
+ - **Development override (`docker-compose.dev.yml`)** switches all services to the `development` stage when layered with the base file. The images include dev dependencies and expose hot-reload commands (`pnpm ... dev`, `nodemon`).
1145
+
1146
+ Switch between modes by including or omitting the dev override file, and always rebuild (`--build`) when you change modes so Docker picks the correct stage.
1147
+
1148
+ ### Volume Mounting Strategy
1149
+
1150
+ **For Development (compose + dev override):**
1151
+ ```yaml
1152
+ volumes:
1153
+ - ./apps/web/src:/app/apps/web/src # ✅ Hot reload
1154
+ - ./apps/web/public:/app/apps/web/public
1155
+ - ./packages/shared:/app/packages/shared
1156
+ ```
1157
+
1158
+ **For Production (base compose only):**
1159
+ ```yaml
1160
+ volumes:
1161
+ # No application volumes mounted – everything runs from the image
1162
+ ```
1163
+
1164
+ ⚠️ **Critical:** Avoid mounting `node_modules` or `.next` in either mode. The base image now carries the full dependency tree; mounting volumes would mask the image contents and lead to stale or empty directories.
1165
+
1166
+ ## Environment Variables
1167
+
1168
+ ### Complete Reference
1169
+
1170
+ All variables with their REQUIRED/OPTIONAL status:
1171
+
1172
+ ```bash
1173
+ # =============================================================================
1174
+ # API CONFIGURATION (REQUIRED)
1175
+ # =============================================================================
1176
+ API_PORT=3400 # REQUIRED: Port for API server
1177
+ API_URL=http://localhost:3400/ # REQUIRED: External API URL
1178
+ API_NODE_OPTIONS=--max-old-space-size=6144 # OPTIONAL: Extra Node.js flags for the API container
1179
+
1180
+ # =============================================================================
1181
+ # WEB CONFIGURATION (REQUIRED)
1182
+ # =============================================================================
1183
+ PORT=3401 # REQUIRED: Port for web server
1184
+ APP_URL=http://localhost:3401/ # REQUIRED: External web URL
1185
+ NEXT_PUBLIC_API_URL=http://localhost:3400/ # REQUIRED: API URL for browser
1186
+ NEXT_PUBLIC_ADDRESS=http://localhost:3401 # REQUIRED: Web address for browser
1187
+ WEB_NODE_OPTIONS=--max-old-space-size=4096 # OPTIONAL: Extra Node.js flags for the web container
1188
+
1189
+ # =============================================================================
1190
+ # WORKER CONFIGURATION (OPTIONAL)
1191
+ # =============================================================================
1192
+ WORKER_NODE_OPTIONS=--max-old-space-size=6144 # OPTIONAL: Extra Node.js flags for worker containers
1193
+
1194
+ # =============================================================================
1195
+ # DOCKER INTERNAL NETWORKING (CRITICAL FOR MULTI-SERVER)
1196
+ # =============================================================================
1197
+ # SINGLE SERVER: Use Docker service name (default)
1198
+ API_INTERNAL_URL=http://api:3400/ # Works when all services on same docker-compose
1199
+
1200
+ # MULTI-SERVER: MUST use external URL or IP
1201
+ # API_INTERNAL_URL=https://api.example.com/ # Use actual domain
1202
+ # API_INTERNAL_URL=http://10.0.1.50:3400/ # Or internal IP
1203
+ #
1204
+ # ⚠️ CRITICAL: If Web and API are on different servers, you MUST set this
1205
+ # to the actual API server URL, NOT the Docker service name!
1206
+
1207
+ # =============================================================================
1208
+ # DATABASE (REQUIRED)
1209
+ # =============================================================================
1210
+ NEO4J_URI=your-neo4j-url # REQUIRED: Neo4j connection URI
1211
+ NEO4J_USER=neo4j # REQUIRED: Neo4j username
1212
+ NEO4J_PASSWORD=your-password # REQUIRED: Neo4j password
1213
+ NEO4J_DATABASE=your-databse # REQUIRED: Neo4j database name
1214
+
1215
+ # =============================================================================
1216
+ # CACHE & QUEUE (REQUIRED)
1217
+ # =============================================================================
1218
+ REDIS_HOST=localhost # REQUIRED: Redis host
1219
+ REDIS_PORT=6379 # REQUIRED: Redis port
1220
+ REDIS_PASSWORD=your-password # REQUIRED: Redis password
1221
+ REDIS_USERNAME=default # OPTIONAL: Redis username (default: "default")
1222
+ REDIS_QUEUE=your-queue # REQUIRED: Queue name for BullMQ
1223
+
1224
+ # =============================================================================
1225
+ # OBJECT STORAGE (REQUIRED)
1226
+ # =============================================================================
1227
+ S3_TYPE=your-type # REQUIRED: minio/s3/digitaloean/hetzner
1228
+ S3_ENDPOINT=your-endpoint # REQUIRED: S3/MinIO endpoint
1229
+ S3_BUCKET=your-bucket-name # REQUIRED: Bucket name
1230
+ S3_ACCESS_KEY_ID=your-access-key # REQUIRED: Access key
1231
+ S3_SECRET_ACCESS_KEY=your-secret # REQUIRED: Secret key
1232
+ S3_REGION=your-region # REQUIRED: Region
1233
+
1234
+ # =============================================================================
1235
+ # AUTHENTICATION (REQUIRED)
1236
+ # =============================================================================
1237
+ JWT_SECRET=your-jwt-secret # REQUIRED: JWT secret (min 32 characters)
1238
+ JWT_EXPIRES_IN=7d # OPTIONAL: JWT expiration (default: 7d)
1239
+
1240
+ # =============================================================================
1241
+ # WEB PUSH - VAPID (REQUIRED)
1242
+ # =============================================================================
1243
+ VAPID_PUBLIC_KEY=your-public-key # REQUIRED: VAPID public key
1244
+ VAPID_PRIVATE_KEY=your-private-key # REQUIRED: VAPID private key
1245
+ VAPID_EMAIL=your-email@example.com # OPTIONAL: Contact email for VAPID
1246
+ NEXT_PUBLIC_VAPID_PUBLIC_KEY=your-public-key # REQUIRED: Public key for browser
1247
+
1248
+ # =============================================================================
1249
+ # CORS CONFIGURATION (OPTIONAL)
1250
+ # =============================================================================
1251
+ CORS_ORIGINS=http://localhost:3401 # OPTIONAL: Allowed CORS origins
1252
+
1253
+ # =============================================================================
1254
+ # EMAIL CONFIGURATION (OPTIONAL)
1255
+ # =============================================================================
1256
+ EMAIL_PROVIDER=smtp # OPTIONAL: Email provider
1257
+ EMAIL_API_KEY=your-api-key # OPTIONAL: API key for email provider
1258
+ EMAIL_FROM=noreply@example.com # OPTIONAL: From email address
1259
+ EMAIL_HOST=smtp.example.com # OPTIONAL: SMTP host
1260
+ EMAIL_PORT=587 # OPTIONAL: SMTP port
1261
+ EMAIL_SECURE=false # OPTIONAL: Use TLS/SSL
1262
+ EMAIL_USERNAME=your-username # OPTIONAL: SMTP username
1263
+ EMAIL_PASSWORD=your-password # OPTIONAL: SMTP password
1264
+
1265
+ # =============================================================================
1266
+ # CACHING (OPTIONAL)
1267
+ # =============================================================================
1268
+ CACHE_ENABLED=true # OPTIONAL: Enable/disable caching (default: true)
1269
+ CACHE_DEFAULT_TTL=3600 # OPTIONAL: Default cache TTL in seconds
1270
+
1271
+ # =============================================================================
1272
+ # RATE LIMITING (OPTIONAL)
1273
+ # =============================================================================
1274
+ RATE_LIMIT_ENABLED=true # OPTIONAL: Enable rate limiting (default: true)
1275
+ RATE_LIMIT_TTL=60 # OPTIONAL: Rate limit window in seconds
1276
+ RATE_LIMIT_REQUESTS=100 # OPTIONAL: Max requests per window
1277
+ ```
1278
+
1279
+ ### Environment Variable Hierarchy
1280
+
1281
+ Docker Compose resolves variables in this order:
1282
+ 1. Environment variables set in shell
1283
+ 2. `.env` file in project root
1284
+ 3. Default values in docker-compose.yml (e.g., `${API_PORT:-3400}`)
1285
+
1286
+ ### Verifying Environment Variables
1287
+
1288
+ ```bash
1289
+ # Check resolved docker-compose configuration
1290
+ docker compose config
1291
+
1292
+ # Check variables inside running container
1293
+ docker compose exec web printenv | grep API
1294
+ docker compose exec api printenv | grep NEO4J
1295
+ ```
1296
+
1297
+ ## Troubleshooting
1298
+
1299
+ ### Issue: 500 Error on Page Load (Timeout)
1300
+
1301
+ **Symptoms:**
1302
+ - Page loads after 30+ second timeout
1303
+ - Browser shows: `Error: 500:`
1304
+ - No logs in API container
1305
+
1306
+ **Cause:** Web container can't reach API via Docker network
1307
+
1308
+ **Solution:**
1309
+ 1. Verify `API_INTERNAL_URL` environment variable:
1310
+ ```bash
1311
+ docker compose exec web printenv | grep API_INTERNAL_URL
1312
+ # Should show: API_INTERNAL_URL=http://api:3400/
1313
+ ```
1314
+
1315
+ 2. Test connectivity:
1316
+ ```bash
1317
+ docker compose exec web wget -O- http://api:3400
1318
+ # Should return API response, not timeout
1319
+ ```
1320
+
1321
+ 3. Check both services are on same network:
1322
+ ```bash
1323
+ docker compose ps
1324
+ # Both should show "{{name}}-network"
1325
+ ```
1326
+
1327
+ 4. If still failing, restart with network reset:
1328
+ ```bash
1329
+ docker compose down
1330
+ docker compose up
1331
+ ```
1332
+
1333
+ ### Issue: Production Build Not Found
1334
+
1335
+ **Symptoms:**
1336
+ ```
1337
+ Could not find a production build in the '.next' directory
1338
+ ```
1339
+
1340
+ **Cause:** The `.next` volume mount is overwriting the built files
1341
+
1342
+ **Solution:**
1343
+ Check `docker-compose.yml` and ensure this line is commented out:
1344
+ ```yaml
1345
+ # - web-next:/app/apps/web/.next # MUST be commented in production!
1346
+ ```
1347
+
1348
+ Then rebuild:
1349
+ ```bash
1350
+ docker compose down
1351
+ docker compose build
1352
+ docker compose up
1353
+ ```
1354
+
1355
+ ### Issue: Code Changes Not Reflected
1356
+
1357
+ **Symptoms:** You edit code but changes don't appear in the running container
1358
+
1359
+ **Cause:** Running production build or volumes not mounted
1360
+
1361
+ **Solution:**
1362
+ 1. Make sure you are using the dev override:
1363
+ ```bash
1364
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml ps
1365
+ ```
1366
+ If this command fails, you likely started only the base compose (production mode).
1367
+
1368
+ 2. Rebuild the dev images:
1369
+ ```bash
1370
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml down
1371
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml build --no-cache
1372
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
1373
+ ```
1374
+
1375
+ 3. Check volumes are mounted:
1376
+ ```bash
1377
+ docker compose config | grep -A 5 volumes
1378
+ ```
1379
+
1380
+ ### Issue: Build Fails with "Cannot find module"
1381
+
1382
+ **Cause:** Dependencies not installed or cached incorrectly
1383
+
1384
+ **Solution:**
1385
+ ```bash
1386
+ # Clear build cache and rebuild
1387
+ docker compose build --no-cache
1388
+
1389
+ # If still failing, remove volumes
1390
+ docker compose down -v
1391
+ docker compose build
1392
+ docker compose up
1393
+ ```
1394
+
1395
+ ### Issue: API Container Exits Immediately
1396
+
1397
+ **Symptoms:** `docker compose ps` shows API as "Exited (1)"
1398
+
1399
+ **Solution:**
1400
+ ```bash
1401
+ # Check logs for error
1402
+ docker compose logs api
1403
+
1404
+ # Common issues:
1405
+ # 1. Can't connect to Neo4j/Redis - verify connection strings
1406
+ # 2. Missing environment variables - check .env file
1407
+ # 3. Build error - rebuild with --no-cache
1408
+ ```
1409
+
1410
+ ### Issue: Port Already in Use
1411
+
1412
+ **Symptoms:**
1413
+ ```
1414
+ Error starting userland proxy: listen tcp 0.0.0.0:3400: bind: address already in use
1415
+ ```
1416
+
1417
+ **Solution:**
1418
+ ```bash
1419
+ # Find process using port (macOS/Linux)
1420
+ lsof -i :3400
1421
+
1422
+ # Find process using port (Windows)
1423
+ netstat -ano | findstr :3400
1424
+
1425
+ # Either kill the process or change port in .env:
1426
+ PORT=3402 # for web
1427
+ API_PORT=3402 # for api
1428
+ ```
1429
+
1430
+ ### Issue: Out of Disk Space
1431
+
1432
+ **Solution:**
1433
+ ```bash
1434
+ # Check Docker disk usage
1435
+ docker system df
1436
+
1437
+ # Remove unused images and containers
1438
+ docker system prune -a
1439
+
1440
+ # Remove volumes (WARNING: deletes data)
1441
+ docker system prune -a --volumes
1442
+ ```
1443
+
1444
+ ### Issue: NEXT_PUBLIC_* Variable Changes Not Applied
1445
+
1446
+ **Cause:** Next.js bakes `NEXT_PUBLIC_*` variables into the build at build time
1447
+
1448
+ **Solution:**
1449
+ After changing any `NEXT_PUBLIC_*` variable:
1450
+ ```bash
1451
+ # Must rebuild web container
1452
+ docker compose build --no-cache web
1453
+ docker compose up web
1454
+ ```
1455
+
1456
+ ## Advanced Topics
1457
+
1458
+ ### Running Individual Services
1459
+
1460
+ ```bash
1461
+ # Start only API (and its dependencies)
1462
+ docker compose up api
1463
+
1464
+ # Start only Web (and its dependencies)
1465
+ docker compose up web
1466
+
1467
+ # Start only Worker
1468
+ docker compose up worker
1469
+ ```
1470
+
1471
+ ### Viewing Logs
1472
+
1473
+ ```bash
1474
+ # Follow all logs
1475
+ docker compose logs -f
1476
+
1477
+ # Follow specific service
1478
+ docker compose logs -f web
1479
+
1480
+ # Show last 100 lines
1481
+ docker compose logs --tail=100 api
1482
+
1483
+ # Filter logs
1484
+ docker compose logs web | grep Error
1485
+ ```
1486
+
1487
+ ### Executing Commands in Containers
1488
+
1489
+ ```bash
1490
+ # Open shell in container
1491
+ docker compose exec web sh
1492
+ docker compose exec api sh
1493
+
1494
+ # Run single command
1495
+ docker compose exec api npm run migrate
1496
+ docker compose exec web ls -la /app/apps/web/.next
1497
+
1498
+ # Check environment
1499
+ docker compose exec web printenv
1500
+ ```
1501
+
1502
+ ### Scaling Workers
1503
+
1504
+ ```bash
1505
+ # Run 3 worker instances
1506
+ docker compose up --scale worker=3
1507
+ ```
1508
+
1509
+ ### Cleaning Up
1510
+
1511
+ ```bash
1512
+ # Stop services
1513
+ docker compose down
1514
+
1515
+ # Stop and remove volumes
1516
+ docker compose down -v
1517
+
1518
+ # Remove all {{name}} containers and images
1519
+ docker compose down --rmi all --volumes
1520
+
1521
+ # Clean up Docker system
1522
+ docker system prune -a
1523
+ ```
1524
+
1525
+ ### Resource Monitoring
1526
+
1527
+ ```bash
1528
+ # Live resource usage
1529
+ docker stats
1530
+
1531
+ # Container processes
1532
+ docker compose top
1533
+
1534
+ # Disk usage
1535
+ docker system df
1536
+ ```
1537
+
1538
+ ## Switching Between Dev and Production
1539
+
1540
+ The base compose file is production-oriented; add the dev override when you need hot reload.
1541
+
1542
+ ```bash
1543
+ # Production (default)
1544
+ docker compose down
1545
+ docker compose up --build -d
1546
+
1547
+ # Development (hot reload)
1548
+ docker compose down
1549
+ docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
1550
+ ```
1551
+
1552
+ **Note:** Always include `--build` when switching modes so Docker rebuilds the correct stage.
1553
+
1554
+ ## Best Practices
1555
+
1556
+ ### Development
1557
+
1558
+ 1. **Use the dev override** (`-f docker-compose.yml -f docker-compose.dev.yml`) for active development
1559
+ 2. **Keep source/shared volumes mounted** for hot-reload (default configuration)
1560
+ 3. **Don't commit `.env`** - use `.env.example` as template
1561
+ 4. **Check logs regularly** when something doesn't work
1562
+ 5. **Rebuild after dependency changes** (package.json modifications)
1563
+
1564
+ ### Production
1565
+
1566
+ 1. **Run the base compose file only** for production deployments
1567
+ 2. **Never commit secrets** - use environment variable management tools
1568
+ 3. **Avoid mounting `node_modules` or `.next`** to prevent dependency drift
1569
+ 4. **Use specific image tags** instead of `latest`
1570
+ 5. **Enable health checks** and monitoring
1571
+ 6. **Rebuild after ANY environment variable change** affecting build
1572
+
1573
+ ### Both Modes
1574
+
1575
+ 1. **Run external infrastructure** (Neo4j, Redis, MinIO) before starting services
1576
+ 2. **Verify network connectivity** if services can't communicate
1577
+ 3. **Monitor disk space** - Docker images can consume significant space
1578
+ 4. **Use `.dockerignore`** to exclude unnecessary files from build context
1579
+ 5. **Clean up regularly** with `docker system prune`
1580
+
1581
+ ## Additional Resources
1582
+
1583
+ - [Docker Compose Documentation](https://docs.docker.com/compose/)
1584
+ - [Next.js Docker Documentation](https://nextjs.org/docs/deployment#docker-image)
1585
+ - [NestJS Docker Documentation](https://docs.nestjs.com/recipes/docker)
1586
+ - [Multi-stage Docker Builds](https://docs.docker.com/build/building/multi-stage/)
1587
+
1588
+ ---
1589
+
1590
+ **Questions or Issues?**
1591
+ Check the main [README.md](./README.md) or open an issue on the repository.