create-forgeon 0.0.3 → 0.1.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 (83) hide show
  1. package/README.md +10 -5
  2. package/bin/create-forgeon.mjs +9 -604
  3. package/package.json +6 -2
  4. package/src/cli/add-help.mjs +12 -0
  5. package/src/cli/add-options.mjs +54 -0
  6. package/src/cli/add-options.test.mjs +24 -0
  7. package/src/cli/help.mjs +20 -0
  8. package/src/cli/options.mjs +121 -0
  9. package/src/cli/options.test.mjs +41 -0
  10. package/src/cli/prompt-select.mjs +89 -0
  11. package/src/cli/prompt-select.test.mjs +34 -0
  12. package/src/constants.mjs +13 -0
  13. package/src/core/docs.mjs +128 -0
  14. package/src/core/docs.test.mjs +91 -0
  15. package/src/core/install.mjs +14 -0
  16. package/src/core/scaffold.mjs +57 -0
  17. package/src/core/validate.mjs +12 -0
  18. package/src/core/validate.test.mjs +73 -0
  19. package/src/databases/index.mjs +26 -0
  20. package/src/frameworks/index.mjs +32 -0
  21. package/src/infrastructure/proxy.mjs +12 -0
  22. package/src/modules/docs.mjs +70 -0
  23. package/src/modules/executor.mjs +40 -0
  24. package/src/modules/executor.test.mjs +62 -0
  25. package/src/modules/registry.mjs +37 -0
  26. package/src/presets/i18n.mjs +203 -0
  27. package/src/presets/index.mjs +2 -0
  28. package/src/presets/proxy.mjs +32 -0
  29. package/src/run-add-module.mjs +47 -0
  30. package/src/run-create-forgeon.mjs +72 -0
  31. package/src/utils/fs.mjs +26 -0
  32. package/src/utils/values.mjs +20 -0
  33. package/templates/base/docs/AI/MODULE_SPEC.md +56 -0
  34. package/templates/base/docs/AI/TASKS.md +17 -7
  35. package/templates/base/docs/README.md +2 -1
  36. package/templates/base/infra/caddy/Caddyfile +11 -7
  37. package/templates/base/infra/docker/compose.none.yml +37 -0
  38. package/templates/docs-fragments/AI_ARCHITECTURE/00_title.md +1 -0
  39. package/templates/docs-fragments/AI_ARCHITECTURE/10_layout_base.md +6 -0
  40. package/templates/docs-fragments/AI_ARCHITECTURE/11_layout_infra.md +1 -0
  41. package/templates/docs-fragments/AI_ARCHITECTURE/12_layout_i18n_resources.md +1 -0
  42. package/templates/docs-fragments/AI_ARCHITECTURE/20_env_base.md +4 -0
  43. package/templates/docs-fragments/AI_ARCHITECTURE/21_env_i18n.md +3 -0
  44. package/templates/docs-fragments/AI_ARCHITECTURE/30_default_db.md +7 -0
  45. package/templates/docs-fragments/AI_ARCHITECTURE/31_docker_runtime.md +5 -0
  46. package/templates/docs-fragments/AI_ARCHITECTURE/32_scope_freeze.md +5 -0
  47. package/templates/docs-fragments/AI_ARCHITECTURE/40_docs_generation.md +9 -0
  48. package/templates/docs-fragments/AI_ARCHITECTURE/50_extension_points.md +8 -0
  49. package/templates/docs-fragments/AI_PROJECT/00_title.md +1 -0
  50. package/templates/docs-fragments/AI_PROJECT/10_what_is.md +3 -0
  51. package/templates/docs-fragments/AI_PROJECT/20_structure_base.md +5 -0
  52. package/templates/docs-fragments/AI_PROJECT/21_structure_i18n.md +2 -0
  53. package/templates/docs-fragments/AI_PROJECT/22_structure_docker.md +1 -0
  54. package/templates/docs-fragments/AI_PROJECT/23_structure_docs.md +1 -0
  55. package/templates/docs-fragments/AI_PROJECT/30_run_dev.md +8 -0
  56. package/templates/docs-fragments/AI_PROJECT/31_run_docker.md +5 -0
  57. package/templates/docs-fragments/AI_PROJECT/32_proxy_notes.md +5 -0
  58. package/templates/docs-fragments/AI_PROJECT/32_proxy_notes_none.md +5 -0
  59. package/templates/docs-fragments/AI_PROJECT/33_i18n_notes.md +4 -0
  60. package/templates/docs-fragments/AI_PROJECT/40_change_boundaries_base.md +3 -0
  61. package/templates/docs-fragments/AI_PROJECT/41_change_boundaries_docker.md +1 -0
  62. package/templates/docs-fragments/README/00_title.md +3 -0
  63. package/templates/docs-fragments/README/10_stack.md +8 -0
  64. package/templates/docs-fragments/README/20_quick_start_dev_intro.md +6 -0
  65. package/templates/docs-fragments/README/21_quick_start_dev_db_docker.md +4 -0
  66. package/templates/docs-fragments/README/21_quick_start_dev_db_local.md +1 -0
  67. package/templates/docs-fragments/README/22_quick_start_dev_outro.md +7 -0
  68. package/templates/docs-fragments/README/30_quick_start_docker.md +7 -0
  69. package/templates/docs-fragments/README/30_quick_start_docker_none.md +9 -0
  70. package/templates/docs-fragments/README/31_proxy_preset_caddy.md +9 -0
  71. package/templates/docs-fragments/README/31_proxy_preset_nginx.md +8 -0
  72. package/templates/docs-fragments/README/31_proxy_preset_none.md +6 -0
  73. package/templates/docs-fragments/README/32_prisma_container_start.md +5 -0
  74. package/templates/docs-fragments/README/40_i18n.md +10 -0
  75. package/templates/docs-fragments/README/90_next_steps.md +7 -0
  76. package/templates/module-fragments/jwt-auth/00_title.md +1 -0
  77. package/templates/module-fragments/jwt-auth/10_overview.md +6 -0
  78. package/templates/module-fragments/jwt-auth/20_scope.md +7 -0
  79. package/templates/module-fragments/jwt-auth/90_status_planned.md +3 -0
  80. package/templates/module-fragments/queue/00_title.md +1 -0
  81. package/templates/module-fragments/queue/10_overview.md +6 -0
  82. package/templates/module-fragments/queue/20_scope.md +7 -0
  83. package/templates/module-fragments/queue/90_status_planned.md +3 -0
@@ -0,0 +1,72 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { printHelp } from './cli/help.mjs';
5
+ import { parseCliArgs, promptForMissingOptions } from './cli/options.mjs';
6
+ import { DEFAULT_DB, DEFAULT_FRONTEND, DEFAULT_PROXY, FIXED_DOCKER_ENABLED } from './constants.mjs';
7
+ import { runInstall } from './core/install.mjs';
8
+ import { scaffoldProject } from './core/scaffold.mjs';
9
+ import { validatePresetSupport } from './core/validate.mjs';
10
+ import { parseBoolean } from './utils/values.mjs';
11
+
12
+ export async function runCreateForgeon(argv = process.argv.slice(2)) {
13
+ const { options: parsedOptions, positional } = parseCliArgs(argv);
14
+ const options = { ...parsedOptions };
15
+
16
+ if (options.help) {
17
+ printHelp();
18
+ return;
19
+ }
20
+
21
+ if (!options.name && positional.length > 0) {
22
+ [options.name] = positional;
23
+ }
24
+
25
+ const promptedOptions = await promptForMissingOptions(options);
26
+
27
+ if (!promptedOptions.name || promptedOptions.name.trim().length === 0) {
28
+ throw new Error('Project name is required.');
29
+ }
30
+
31
+ const frontend = (promptedOptions.frontend ?? DEFAULT_FRONTEND).toString().toLowerCase();
32
+ const db = (promptedOptions.db ?? DEFAULT_DB).toString().toLowerCase();
33
+ const i18nEnabled = parseBoolean(promptedOptions.i18n, true);
34
+ const dockerEnabled = FIXED_DOCKER_ENABLED;
35
+ const proxy = (promptedOptions.proxy ?? DEFAULT_PROXY).toString().toLowerCase();
36
+ const installEnabled = parseBoolean(promptedOptions.install, false);
37
+
38
+ validatePresetSupport({ frontend, db, dockerEnabled, proxy });
39
+
40
+ const projectName = promptedOptions.name.trim();
41
+ const targetRoot = path.resolve(process.cwd(), projectName);
42
+ if (fs.existsSync(targetRoot)) {
43
+ throw new Error(`Target directory already exists: ${targetRoot}`);
44
+ }
45
+
46
+ const srcDir = path.dirname(fileURLToPath(import.meta.url));
47
+ const packageRoot = path.resolve(srcDir, '..');
48
+ const templateRoot = path.join(packageRoot, 'templates', 'base');
49
+
50
+ scaffoldProject({
51
+ templateRoot,
52
+ packageRoot,
53
+ targetRoot,
54
+ projectName,
55
+ frontend,
56
+ db,
57
+ i18nEnabled,
58
+ proxy,
59
+ });
60
+
61
+ if (installEnabled) {
62
+ runInstall(targetRoot);
63
+ }
64
+
65
+ console.log('Forgeon scaffold generated.');
66
+ console.log(`- path: ${targetRoot}`);
67
+ console.log(`- frontend: ${frontend}`);
68
+ console.log(`- db: ${db}`);
69
+ console.log(`- i18n: ${i18nEnabled}`);
70
+ console.log(`- docker: ${dockerEnabled}`);
71
+ console.log(`- proxy: ${proxy}`);
72
+ }
@@ -0,0 +1,26 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ export function copyRecursive(source, destination) {
5
+ const stat = fs.statSync(source);
6
+
7
+ if (stat.isDirectory()) {
8
+ fs.mkdirSync(destination, { recursive: true });
9
+ for (const entry of fs.readdirSync(source)) {
10
+ copyRecursive(path.join(source, entry), path.join(destination, entry));
11
+ }
12
+ return;
13
+ }
14
+
15
+ fs.copyFileSync(source, destination);
16
+ }
17
+
18
+ export function writeJson(filePath, data) {
19
+ fs.writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\n`, 'utf8');
20
+ }
21
+
22
+ export function removeIfExists(targetPath) {
23
+ if (fs.existsSync(targetPath)) {
24
+ fs.rmSync(targetPath, { recursive: true, force: true });
25
+ }
26
+ }
@@ -0,0 +1,20 @@
1
+ export function parseBoolean(value, fallback) {
2
+ if (value === undefined) return fallback;
3
+ if (typeof value === 'boolean') return value;
4
+
5
+ const normalized = String(value).trim().toLowerCase();
6
+ if (['true', '1', 'yes', 'y'].includes(normalized)) return true;
7
+ if (['false', '0', 'no', 'n'].includes(normalized)) return false;
8
+
9
+ throw new Error(`Invalid boolean value: ${value}`);
10
+ }
11
+
12
+ export function toKebabCase(value) {
13
+ return (
14
+ value
15
+ .trim()
16
+ .toLowerCase()
17
+ .replace(/[^a-z0-9]+/g, '-')
18
+ .replace(/^-+|-+$/g, '') || 'forgeon-app'
19
+ );
20
+ }
@@ -0,0 +1,56 @@
1
+ # MODULE SPEC
2
+
3
+ ## Goal
4
+
5
+ Define one repeatable fullstack pattern for Forgeon add-modules.
6
+
7
+ Each feature module should be split into:
8
+
9
+ 1. `@forgeon/<feature>-contracts`
10
+ 2. `@forgeon/<feature>-api`
11
+ 3. `@forgeon/<feature>-web`
12
+
13
+ ## 1) Contracts Package
14
+
15
+ Single source of truth shared by backend and frontend.
16
+
17
+ Must contain:
18
+
19
+ - DTO/request/response types
20
+ - route constants (`API.<feature>.*`)
21
+ - error codes (`<FEATURE>_*`)
22
+ - shared constants (header/cookie names)
23
+
24
+ Should contain:
25
+
26
+ - zod schemas + inferred TS types
27
+
28
+ ## 2) API Package
29
+
30
+ NestJS module integrating contracts into backend runtime.
31
+
32
+ Must contain:
33
+
34
+ - module/service/controller
35
+ - guards/strategies (if auth/security related)
36
+ - config keys
37
+ - minimal e2e test path
38
+ - integration with `@forgeon/core` errors/logging
39
+
40
+ ## 3) Web Package
41
+
42
+ React integration layer for the same feature.
43
+
44
+ Must contain:
45
+
46
+ - provider/hooks/store
47
+ - route guard (if feature requires auth/access)
48
+ - API client helpers using contracts route constants/types
49
+ - token/header/cookie wiring where relevant
50
+
51
+ ## Acceptance Criteria
52
+
53
+ - No duplicate route strings across api/web.
54
+ - No duplicate error-code enums across api/web.
55
+ - Contracts package can be imported from both sides without circular dependencies.
56
+ - Module has docs under `docs/AI/MODULES/<module-id>.md`.
@@ -38,11 +38,21 @@ Run build checks and show changed files.
38
38
  ## Generate Preset
39
39
 
40
40
  ```text
41
- Create a new preset flow for create-forgeon:
42
- - add new flag(s)
43
- - update interactive questions
44
- - update generated files
45
- - keep defaults: Prisma + Postgres, React + Vite + TS
46
- - update docs/AI/ARCHITECTURE.md
47
- ```
41
+ Create or update create-forgeon preset flow:
42
+ - keep canonical stack fixed: NestJS + React + Prisma/Postgres + Docker
43
+ - allow only runtime proxy choice: caddy/nginx/none
44
+ - update generated docs fragments
45
+ - update docs/AI/ARCHITECTURE.md and docs/AI/MODULE_SPEC.md when scope changes
46
+ ```
47
+
48
+ ## Add Fullstack Module
49
+
50
+ ```text
51
+ Implement `create-forgeon add <module-id>` for a fullstack feature.
52
+ Requirements:
53
+ - split module into contracts/api/web packages
54
+ - contracts is source of truth for routes, DTOs, errors
55
+ - add docs note under docs/AI/MODULES/<module-id>.md
56
+ - keep backward compatibility
57
+ ```
48
58
 
@@ -2,4 +2,5 @@
2
2
 
3
3
  - `AI/PROJECT.md` - project overview and run modes
4
4
  - `AI/ARCHITECTURE.md` - monorepo design and extension model
5
- - `AI/TASKS.md` - ready-to-use Codex prompts
5
+ - `AI/MODULE_SPEC.md` - fullstack module contract (`contracts/api/web`)
6
+ - `AI/TASKS.md` - ready-to-use Codex prompts
@@ -1,11 +1,15 @@
1
1
  :80 {
2
2
  encode gzip zstd
3
3
 
4
- handle /api/* {
5
- reverse_proxy api:3000
6
- }
4
+ route {
5
+ handle /api/* {
6
+ reverse_proxy api:3000
7
+ }
7
8
 
8
- root * /srv
9
- try_files {path} /index.html
10
- file_server
11
- }
9
+ handle {
10
+ root * /srv
11
+ try_files {path} /index.html
12
+ file_server
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,37 @@
1
+ services:
2
+ db:
3
+ image: postgres:16-alpine
4
+ restart: unless-stopped
5
+ environment:
6
+ POSTGRES_USER: ${POSTGRES_USER}
7
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
8
+ POSTGRES_DB: ${POSTGRES_DB}
9
+ ports:
10
+ - "5432:5432"
11
+ volumes:
12
+ - db_data:/var/lib/postgresql/data
13
+ healthcheck:
14
+ test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
15
+ interval: 10s
16
+ timeout: 5s
17
+ retries: 10
18
+
19
+ api:
20
+ build:
21
+ context: ../..
22
+ dockerfile: apps/api/Dockerfile
23
+ restart: unless-stopped
24
+ environment:
25
+ PORT: ${PORT}
26
+ DATABASE_URL: ${DATABASE_URL}
27
+ I18N_ENABLED: ${I18N_ENABLED}
28
+ I18N_DEFAULT_LANG: ${I18N_DEFAULT_LANG}
29
+ I18N_FALLBACK_LANG: ${I18N_FALLBACK_LANG}
30
+ depends_on:
31
+ db:
32
+ condition: service_healthy
33
+ ports:
34
+ - "3000:3000"
35
+
36
+ volumes:
37
+ db_data:
@@ -0,0 +1 @@
1
+ # ARCHITECTURE
@@ -0,0 +1,6 @@
1
+ ## Monorepo Layout
2
+
3
+ - `apps/*` - deployable apps
4
+ - `packages/*` - reusable modules and presets
5
+
6
+ Canonical stack is fixed for now: NestJS API + React web + Prisma/Postgres + Docker.
@@ -0,0 +1 @@
1
+ - `infra/*` - runtime infrastructure (compose, proxy, env examples)
@@ -0,0 +1 @@
1
+ - `resources/*` - static assets (includes translation dictionaries when i18n is enabled)
@@ -0,0 +1,4 @@
1
+ ## Environment Flags
2
+
3
+ - `PORT` - API port (default 3000)
4
+ - `DATABASE_URL` - DB connection string for Prisma
@@ -0,0 +1,3 @@
1
+ - `I18N_ENABLED` - toggles i18n package wiring
2
+ - `I18N_DEFAULT_LANG` - default language
3
+ - `I18N_FALLBACK_LANG` - fallback language
@@ -0,0 +1,7 @@
1
+ ## Default DB Stack
2
+
3
+ Current default stack is `{{DB_LABEL}}`.
4
+
5
+ - Prisma schema and migrations live in `apps/api/prisma`
6
+ - DB access is encapsulated via `PrismaModule` (`apps/api/src/prisma`)
7
+ - Additional DB presets are intentionally out of scope for the current milestone.
@@ -0,0 +1,5 @@
1
+ ## Docker Runtime Flow
2
+
3
+ - Compose file: `infra/docker/compose.yml`
4
+ - API starts through migration deploy, then NestJS server boot.
5
+ - Active reverse proxy preset: `{{PROXY_LABEL}}` (`{{PROXY_CONFIG_PATH}}`)
@@ -0,0 +1,5 @@
1
+ ## Scope Freeze (Current)
2
+
3
+ - Frontend preset selection is disabled (React is fixed).
4
+ - DB preset selection is disabled (Prisma/Postgres is fixed).
5
+ - Docker is always generated; runtime proxy is selectable (`caddy|nginx|none`).
@@ -0,0 +1,9 @@
1
+ ## Docs Generation Pipeline
2
+
3
+ Project docs are assembled from markdown fragments in:
4
+
5
+ - `packages/create-forgeon/templates/docs-fragments/README`
6
+ - `packages/create-forgeon/templates/docs-fragments/AI_PROJECT`
7
+ - `packages/create-forgeon/templates/docs-fragments/AI_ARCHITECTURE`
8
+
9
+ During scaffold generation, the CLI selects fragments based on chosen flags and writes final docs into project root and `docs/AI`.
@@ -0,0 +1,8 @@
1
+ ## Extension Points
2
+
3
+ Future presets should extend both code and docs in parallel:
4
+
5
+ 1. Add or update fullstack module templates (`contracts/api/web`).
6
+ 2. Register modules in `create-forgeon add` registry.
7
+ 3. Add module docs fragments and update module spec docs.
8
+ 4. Keep canonical core stack stable unless a major version changes it.
@@ -0,0 +1 @@
1
+ # PROJECT
@@ -0,0 +1,3 @@
1
+ ## What This Repository Is
2
+
3
+ A canonical fullstack monorepo scaffold intended to be reused as a project starter.
@@ -0,0 +1,5 @@
1
+ ## Structure
2
+
3
+ - `apps/api` - NestJS backend
4
+ - `apps/web` - React frontend (`{{FRONTEND_LABEL}}`, fixed)
5
+ - `packages/core` - shared backend core placeholder
@@ -0,0 +1,2 @@
1
+ - `packages/i18n` - reusable nestjs-i18n integration package
2
+ - `resources/i18n` - translation dictionaries
@@ -0,0 +1 @@
1
+ - `infra` - Docker Compose (always) + proxy preset (`{{PROXY_LABEL}}`)
@@ -0,0 +1 @@
1
+ - `docs` - documentation, AI prompts, and module spec contracts
@@ -0,0 +1,8 @@
1
+ ## Run Modes
2
+
3
+ ### Dev mode
4
+
5
+ ```bash
6
+ pnpm install
7
+ pnpm dev
8
+ ```
@@ -0,0 +1,5 @@
1
+ ### Docker mode
2
+
3
+ ```bash
4
+ docker compose --env-file infra/docker/.env.example -f infra/docker/compose.yml up --build
5
+ ```
@@ -0,0 +1,5 @@
1
+ ### Proxy Notes
2
+
3
+ - Active proxy preset: `{{PROXY_LABEL}}`
4
+ - Main proxy config: `{{PROXY_CONFIG_PATH}}`
5
+ - Keep service names `api` and `db` stable unless you update compose and proxy config together.
@@ -0,0 +1,5 @@
1
+ ### Proxy Notes
2
+ - Active proxy preset: `none`
3
+ - No proxy config file is used.
4
+ - API is exposed directly from compose on `localhost:3000`.
5
+ - For OAuth/SSL test scenarios, switch to `proxy=caddy`.
@@ -0,0 +1,4 @@
1
+ ### i18n Notes
2
+
3
+ - Toggle via `I18N_ENABLED`.
4
+ - Default/fallback are controlled by `I18N_DEFAULT_LANG` and `I18N_FALLBACK_LANG`.
@@ -0,0 +1,3 @@
1
+ ## Change Boundaries
2
+
3
+ - Safe to change first: env files, host ports, and app code under `apps/*`.
@@ -0,0 +1 @@
1
+ - Change carefully: proxy config and docker service names because routing depends on them.
@@ -0,0 +1,3 @@
1
+ # Forgeon Fullstack Scaffold
2
+
3
+ Canonical monorepo scaffold for NestJS + frontend with shared packages and generated docs.
@@ -0,0 +1,8 @@
1
+ ## Generated Preset
2
+
3
+ - Stack: `NestJS + React + Prisma/Postgres + Docker`
4
+ - Frontend: `{{FRONTEND_LABEL}}` (fixed)
5
+ - Database: `{{DB_LABEL}}` (fixed)
6
+ - i18n: `{{I18N_STATUS}}`
7
+ - Docker/infra: `enabled` (fixed)
8
+ - Reverse proxy: `{{PROXY_LABEL}}` (`caddy|nginx|none`)
@@ -0,0 +1,6 @@
1
+ ## Quick Start (Dev)
2
+
3
+ 1. Install dependencies:
4
+ ```bash
5
+ pnpm install
6
+ ```
@@ -0,0 +1,4 @@
1
+ 2. Start local Postgres (Docker):
2
+ ```bash
3
+ docker compose --env-file infra/docker/.env.example -f infra/docker/compose.yml up db -d
4
+ ```
@@ -0,0 +1 @@
1
+ 2. Ensure PostgreSQL is running locally and configure `DATABASE_URL` in `apps/api/.env`.
@@ -0,0 +1,7 @@
1
+ 3. Run API + web in dev mode:
2
+ ```bash
3
+ pnpm dev
4
+ ```
5
+ 4. Open:
6
+ - Web: `http://localhost:5173`
7
+ - API health: `http://localhost:3000/api/health`
@@ -0,0 +1,7 @@
1
+ ## Quick Start (Docker)
2
+
3
+ ```bash
4
+ docker compose --env-file infra/docker/.env.example -f infra/docker/compose.yml up --build
5
+ ```
6
+
7
+ Open `http://localhost:8080`.
@@ -0,0 +1,9 @@
1
+ ## Quick Start (Docker)
2
+
3
+ ```bash
4
+ docker compose --env-file infra/docker/.env.example -f infra/docker/compose.yml up --build
5
+ ```
6
+
7
+ Open API at `http://localhost:3000/api/health`.
8
+
9
+ Frontend is not served by Docker in `proxy=none` mode. Use `pnpm dev` for web.
@@ -0,0 +1,9 @@
1
+ ### Proxy Preset: Caddy
2
+
3
+ - `/api/*` is proxied to `api:3000`.
4
+ - Static frontend build is served by Caddy.
5
+ - Main proxy config: `infra/caddy/Caddyfile`.
6
+ - Compose service wiring: `infra/docker/compose.yml` (`caddy` service).
7
+ - Safe to edit: host ports and env values in `infra/docker/.env.example`.
8
+ - Avoid renaming service hosts (`api`, `db`) unless you also update proxy/compose config.
9
+ - Recommended preset for local SSL/OAuth-style testing.
@@ -0,0 +1,8 @@
1
+ ### Proxy Preset: Nginx
2
+
3
+ - `/api/*` is proxied to `api:3000`.
4
+ - Static frontend build is served by Nginx.
5
+ - Main proxy config: `infra/nginx/nginx.conf`.
6
+ - Compose service wiring: `infra/docker/compose.yml` (`nginx` service).
7
+ - Safe to edit: host ports and env values in `infra/docker/.env.example`.
8
+ - Avoid renaming service hosts (`api`, `db`) unless you also update proxy/compose config.
@@ -0,0 +1,6 @@
1
+ ### Proxy Preset: none
2
+
3
+ - No reverse proxy container is started.
4
+ - API is exposed directly on `http://localhost:3000`.
5
+ - Useful for minimal local backend testing.
6
+ - For OAuth/SSL-style local tests, prefer `proxy=caddy`.
@@ -0,0 +1,5 @@
1
+ ### Prisma In Container Start
2
+
3
+ API container starts with:
4
+ 1. `pnpm --filter @forgeon/api prisma:migrate:deploy`
5
+ 2. `node apps/api/dist/main.js`
@@ -0,0 +1,10 @@
1
+ ## i18n Configuration
2
+
3
+ Environment keys:
4
+ - `I18N_ENABLED=true|false`
5
+ - `I18N_DEFAULT_LANG=en`
6
+ - `I18N_FALLBACK_LANG=en`
7
+
8
+ Resources location: `resources/i18n`.
9
+
10
+ When `I18N_ENABLED=false`, API starts without loading `@forgeon/i18n`.
@@ -0,0 +1,7 @@
1
+ ## Next Steps
2
+
3
+ - Backend entrypoint: `apps/api/src/main.ts`
4
+ - Frontend entrypoint: `apps/web/src/main.tsx`
5
+ - Project docs index: `docs/README.md`
6
+ - AI workflow docs: `docs/AI/*`
7
+ - Module contract spec: `docs/AI/MODULE_SPEC.md`
@@ -0,0 +1 @@
1
+ # MODULE: {{MODULE_LABEL}}
@@ -0,0 +1,6 @@
1
+ ## Overview
2
+
3
+ - Id: `{{MODULE_ID}}`
4
+ - Category: `{{MODULE_CATEGORY}}`
5
+ - Status: {{MODULE_STATUS}}
6
+ - Description: {{MODULE_DESCRIPTION}}
@@ -0,0 +1,7 @@
1
+ ## Scope (Planned)
2
+
3
+ Planned implementation target:
4
+
5
+ 1. Add reusable auth package wiring under `packages/*`.
6
+ 2. Add NestJS guard + strategy integration in `apps/api`.
7
+ 3. Add env docs and usage examples.
@@ -0,0 +1,3 @@
1
+ ## Current State
2
+
3
+ This module is registered but not implemented yet.
@@ -0,0 +1 @@
1
+ # MODULE: {{MODULE_LABEL}}
@@ -0,0 +1,6 @@
1
+ ## Overview
2
+
3
+ - Id: `{{MODULE_ID}}`
4
+ - Category: `{{MODULE_CATEGORY}}`
5
+ - Status: {{MODULE_STATUS}}
6
+ - Description: {{MODULE_DESCRIPTION}}
@@ -0,0 +1,7 @@
1
+ ## Scope (Planned)
2
+
3
+ Planned implementation target:
4
+
5
+ 1. Add queue package preset (worker + producer abstractions).
6
+ 2. Wire module imports and config in `apps/api`.
7
+ 3. Document runtime and deployment notes.
@@ -0,0 +1,3 @@
1
+ ## Current State
2
+
3
+ This module is registered but not implemented yet.