forgecad 0.6.3 → 0.8.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.
- package/README.md +3 -12
- package/dist/assets/{AdminPage-CeqCUUgu.js → AdminPage-D4bocK4E.js} +250 -151
- package/dist/assets/{BlogPage-P_AJP0v9.js → BlogPage-CJEXL_zJ.js} +94 -70
- package/dist/assets/{DocsPage-CKRV2iq2.js → DocsPage-D3A_g8V3.js} +329 -163
- package/dist/assets/{EditorApp-CnC2k4cW.css → EditorApp-BWYUSpUN.css} +590 -136
- package/dist/assets/EditorApp-Cihhqcsq.js +11692 -0
- package/dist/assets/{EmbedViewer-DBlzmQ5i.js → EmbedViewer-kWjKaC_t.js} +2 -4
- package/dist/assets/LandingPageProofDriven-Bg2IUc3l.css +856 -0
- package/dist/assets/LandingPageProofDriven-DXkKlyhI.js +601 -0
- package/dist/assets/PricingPage-BsU5vzEx.js +232 -0
- package/dist/assets/{SettingsPage-BqCh9JcC.js → SettingsPage-PqvpAKIs.js} +129 -5
- package/dist/assets/{evalWorker-Ql-aKwLA.js → evalWorker-C-hzNUMy.js} +8949 -3161
- package/dist/assets/{Viewport-CoB46f5R.js → index-Pz321YAt.js} +38382 -7501
- package/dist/assets/{index-2hfs_ub0.css → index-ay13WNfa.css} +726 -53
- package/dist/assets/{javascript-DCxGoE5Y.js → javascript-DAl8Gmyo.js} +1 -1
- package/dist/assets/{manifold-CqNMHHKO.js → manifold-BcbjWLIo.js} +4 -3
- package/dist/assets/{manifold-Cce9wRFz.js → manifold-DBckbFgx.js} +1 -1
- package/dist/assets/{manifold-D6BeHIOo.js → manifold-O2AAGXyj.js} +1 -1
- package/dist/assets/{reportWorker-sFEFonXf.js → reportWorker-Dxr-5A7w.js} +8760 -3559
- package/dist/assets/{vendor-react-Dt7-aaJH.js → vendor-react-CG3i_wp0.js} +65 -8
- package/dist/docs/index.html +2 -2
- package/dist/docs-raw/CLI.md +341 -718
- package/dist/docs-raw/generated/assembly.md +699 -112
- package/dist/docs-raw/generated/concepts.md +1834 -1346
- package/dist/docs-raw/generated/core.md +1012 -1059
- package/dist/docs-raw/generated/curves.md +759 -116
- package/dist/docs-raw/generated/lib.md +43 -748
- package/dist/docs-raw/generated/output.md +139 -245
- package/dist/docs-raw/generated/sdf.md +208 -0
- package/dist/docs-raw/generated/sheet-metal.md +473 -21
- package/dist/docs-raw/generated/sketch.md +1518 -362
- package/dist/docs-raw/generated/viewport.md +368 -299
- package/dist/docs-raw/generated/wood.md +104 -0
- package/dist/index.html +2 -2
- package/dist/landing/proof-ams-adapter.png +0 -0
- package/dist/landing/proof-bolt-and-nut.png +0 -0
- package/dist/landing/proof-fillet-enclosure.png +0 -0
- package/dist/landing/proof-glasses.png +0 -0
- package/dist/landing/proof-gyroid.png +0 -0
- package/dist/sitemap.xml +6 -6
- package/dist-cli/forgecad.js +12321 -5700
- package/dist-cli/forgecad.js.map +1 -0
- package/dist-cli/solver-46FFSK2U.js +363 -0
- package/dist-cli/solver-46FFSK2U.js.map +1 -0
- package/dist-skill/CONTEXT.md +4890 -6302
- package/dist-skill/SKILL-dev.md +22 -66
- package/dist-skill/SKILL.md +20 -59
- package/dist-skill/docs/API/core/concepts.md +37 -92
- package/dist-skill/docs/CLI.md +341 -718
- package/dist-skill/docs/generated/assembly.md +699 -112
- package/dist-skill/docs/generated/core.md +1012 -1059
- package/dist-skill/docs/generated/curves.md +759 -116
- package/dist-skill/docs/generated/lib.md +43 -748
- package/dist-skill/docs/generated/output.md +139 -245
- package/dist-skill/docs/generated/sdf.md +208 -0
- package/dist-skill/docs/generated/sheet-metal.md +473 -21
- package/dist-skill/docs/generated/sketch.md +1518 -362
- package/dist-skill/docs/generated/viewport.md +368 -299
- package/dist-skill/docs/generated/wood.md +104 -0
- package/dist-skill/docs/guides/coordinate-system.md +11 -17
- package/dist-skill/docs/guides/geometry-conventions.md +13 -70
- package/dist-skill/docs/guides/joint-design.md +78 -0
- package/dist-skill/docs/guides/modeling-recipes.md +22 -195
- package/dist-skill/docs/guides/positioning.md +88 -147
- package/dist-skill/docs-dev/API/core/concepts.md +78 -0
- package/dist-skill/docs-dev/CLI.md +488 -0
- package/dist-skill/{docs → docs-dev}/blueprint-first.md +5 -0
- package/dist-skill/{docs → docs-dev}/coding-best-practices.md +6 -8
- package/dist-skill/{docs → docs-dev}/coding.md +2 -4
- package/dist-skill/docs-dev/component-model.md +164 -0
- package/dist-skill/docs-dev/generated/assembly.md +779 -0
- package/dist-skill/docs-dev/generated/core.md +1676 -0
- package/dist-skill/docs-dev/generated/curves.md +855 -0
- package/dist-skill/docs-dev/generated/lib.md +55 -0
- package/dist-skill/docs-dev/generated/output.md +234 -0
- package/dist-skill/docs-dev/generated/sdf.md +208 -0
- package/dist-skill/docs-dev/generated/sheet-metal.md +506 -0
- package/dist-skill/docs-dev/generated/sketch.md +1753 -0
- package/dist-skill/docs-dev/generated/viewport.md +513 -0
- package/dist-skill/docs-dev/generated/wood.md +104 -0
- package/dist-skill/docs-dev/guides/coordinate-system.md +46 -0
- package/dist-skill/docs-dev/guides/geometry-conventions.md +52 -0
- package/dist-skill/docs-dev/guides/joint-design.md +78 -0
- package/dist-skill/docs-dev/guides/modeling-recipes.md +77 -0
- package/dist-skill/docs-dev/guides/positioning.md +151 -0
- package/dist-skill/{docs → docs-dev}/guides/skill-maintenance.md +21 -10
- package/dist-skill/{docs → docs-dev}/internals/compiler.md +5 -6
- package/dist-skill/{docs → docs-dev}/internals/constraint-solver-quality.md +0 -1
- package/dist-skill/{docs → docs-dev}/internals/constraint-solver.md +0 -1
- package/dist-skill/{docs → docs-dev}/internals/sketch-2d-pipeline.md +2 -3
- package/examples/api/attachTo-basics.forge.js +8 -8
- package/examples/api/bill-of-materials.forge.js +9 -9
- package/examples/api/bolt-pattern.forge.js +5 -5
- package/examples/api/boolean-operations.forge.js +5 -5
- package/examples/api/bounding-box-visualizer.forge.js +3 -3
- package/examples/api/clone-duplicate.forge.js +2 -2
- package/examples/api/colors-union-vs-array.forge.js +6 -6
- package/examples/api/connector-assembly.forge.js +8 -6
- package/examples/api/connector-basics.forge.js +7 -7
- package/examples/api/constrained-sketch-mechanical.forge.js +4 -4
- package/examples/api/elbow-test.forge.js +3 -3
- package/examples/api/extrude-options.forge.js +8 -14
- package/examples/api/feature-created-faces.forge.js +6 -10
- package/examples/api/fillet-showcase.forge.js +2 -2
- package/examples/api/folded-service-panel-cover.forge.js +2 -2
- package/examples/api/gears-tier1.forge.js +5 -5
- package/examples/api/group-test.forge.js +3 -3
- package/examples/api/group-vs-union.forge.js +1 -1
- package/examples/api/highlight-debug.forge.js +4 -0
- package/examples/api/js-module-pillars.js +1 -1
- package/examples/api/js-module-scene.js +2 -2
- package/examples/api/mesh-import-slats.forge.js +4 -4
- package/examples/api/patterns.forge.js +3 -3
- package/examples/api/pointAlong-orientation.forge.js +3 -3
- package/examples/api/profile-2020-b-slot6.forge.js +4 -5
- package/examples/api/route-perimeter-flange.forge.js +1 -1
- package/examples/api/sdf-rover-demo.forge.js +10 -10
- package/examples/api/sketch-on-face-demo.forge.js +2 -2
- package/examples/api/sketch-regions.forge.js +4 -4
- package/examples/api/sketch-rounding-strategies.forge.js +1 -1
- package/examples/api/smooth-curve-connections.forge.js +1 -1
- package/examples/api/transition-curves.forge.js +4 -4
- package/examples/api/variable-sweep-pure-sdf-test.forge.js +162 -0
- package/examples/api/variable-sweep-test.forge.js +2 -2
- package/examples/api/wood-joinery.forge.js +60 -0
- package/examples/compiler-corpus/enclosure-shell-cuts.forge.js +3 -3
- package/examples/compiler-corpus/fastener-plate-variants.forge.js +2 -2
- package/examples/constraints/01-fully-constrained-rect.forge.js +2 -2
- package/examples/constraints/02-underconstrained-triangle.forge.js +1 -1
- package/examples/constraints/03-redundant-constraints.forge.js +2 -2
- package/examples/constraints/05-parallel-with-linedistance.forge.js +2 -2
- package/examples/constraints/06-complex-spectrogram.forge.js +1 -1
- package/examples/constraints/07-perpendicular-chain.forge.js +4 -4
- package/examples/constraints/08-symmetric-bracket.forge.js +4 -4
- package/examples/constraints/09-stress-spiral.forge.js +1 -1
- package/examples/constraints/10-stress-honeycomb.forge.js +1 -1
- package/examples/constraints/11-surface-grid.forge.js +2 -2
- package/examples/constraints/12-surface-nested.forge.js +4 -4
- package/examples/constraints/13-surface-complex.forge.js +1 -1
- package/examples/exact-arc-housing.forge.js +12 -0
- package/examples/experiments/drone-arm.forge.js +53 -0
- package/examples/furniture/adjustable-table.forge.js +15 -15
- package/examples/furniture/bathroom.forge.js +26 -26
- package/examples/furniture/chair.forge.js +13 -13
- package/examples/furniture/picture-frame.forge.js +6 -6
- package/examples/furniture/shoe-rack-doors.forge.js +8 -8
- package/examples/furniture/shoe-rack.forge.js +7 -7
- package/examples/furniture/table-lamp.forge.js +8 -8
- package/examples/gcode/lissajous-vase.forge.js +4 -4
- package/examples/gcode/math-surface.forge.js +3 -3
- package/examples/gcode/parametric-vase.forge.js +4 -4
- package/examples/gcode/spiral-tower.forge.js +4 -4
- package/examples/generative/crystal-growth.forge.js +9 -9
- package/examples/generative/frost-spires.forge.js +9 -9
- package/examples/generative/golden-spiral-tower.forge.js +11 -11
- package/examples/generative/molten-forge.forge.js +6 -6
- package/examples/generative/neon-coral.forge.js +7 -7
- package/examples/mechanical/3d-printer.forge.js +37 -37
- package/examples/mechanical/5-finger-robot-hand.forge.js +19 -19
- package/examples/mechanical/airplane-propeller.forge.js +9 -9
- package/examples/mechanical/bolt-and-nut.forge.js +10 -10
- package/examples/mechanical/door-with-hinges.forge.js +7 -7
- package/examples/mechanical/fillet-enclosure.forge.js +15 -11
- package/examples/mechanical/headphone-hanger-v2.forge.js +11 -11
- package/examples/mechanical/robot_hand.forge.js +24 -24
- package/examples/mechanical/robot_hand_2.forge.js +26 -26
- package/examples/nurbs-surface.forge.js +8 -0
- package/examples/nurbs-tube.forge.js +7 -0
- package/examples/products/bottle.forge.js +8 -8
- package/examples/products/chess-set.forge.js +25 -25
- package/examples/products/classical-piano.forge.js +20 -20
- package/examples/products/clock.forge.js +33 -33
- package/examples/products/cup.forge.js +5 -5
- package/examples/products/iphone.forge.js +20 -20
- package/examples/products/laptop.forge.js +24 -24
- package/examples/products/laser-cut-box.forge.js +6 -6
- package/examples/products/laser-cut-tray.forge.js +6 -6
- package/examples/products/liquid-soap-dispenser.forge.js +23 -23
- package/examples/products/origami-fish.forge.js +14 -12
- package/examples/products/spiderman-cake.forge.js +6 -6
- package/examples/shelf/container.forge.js +5 -5
- package/examples/shelf/shelf-unit.forge.js +6 -6
- package/examples/toolbox/bolted-joint.forge.js +7 -7
- package/package.json +9 -4
- package/dist/assets/EditorApp-B-vQvgam.js +0 -9888
- package/dist/assets/LandingPage-C5n9hDXI.js +0 -322
- package/dist/assets/PublishedModelPage-Dt7PCVBj.js +0 -146
- package/dist/assets/__vite-browser-external-CURh0WXD.js +0 -8
- package/dist/assets/deserializeRunResult-BLAFoiE0.js +0 -19365
- package/dist/assets/index-1CYp3zUp.js +0 -1455
- package/dist-skill/docs/API/API.md +0 -1666
- package/dist-skill/docs/API/README.md +0 -37
- package/dist-skill/docs/API/assembly/assembly.md +0 -617
- package/dist-skill/docs/API/core/edge-queries.md +0 -130
- package/dist-skill/docs/API/core/parameters.md +0 -122
- package/dist-skill/docs/API/core/reserved-terms.md +0 -137
- package/dist-skill/docs/API/core/sdf.md +0 -326
- package/dist-skill/docs/API/core/skill-cli.md +0 -194
- package/dist-skill/docs/API/core/skill-guide.md +0 -205
- package/dist-skill/docs/API/core/specs.md +0 -186
- package/dist-skill/docs/API/core/topology.md +0 -372
- package/dist-skill/docs/API/entities.md +0 -268
- package/dist-skill/docs/API/output/bom.md +0 -58
- package/dist-skill/docs/API/output/brep-export.md +0 -87
- package/dist-skill/docs/API/output/dimensions.md +0 -67
- package/dist-skill/docs/API/output/export.md +0 -110
- package/dist-skill/docs/API/output/gcode.md +0 -195
- package/dist-skill/docs/API/runtime/viewport.md +0 -420
- package/dist-skill/docs/API/sheet-metal/sheet-metal.md +0 -185
- package/dist-skill/docs/API/sketch/anchor.md +0 -37
- package/dist-skill/docs/API/sketch/booleans.md +0 -91
- package/dist-skill/docs/API/sketch/core.md +0 -73
- package/dist-skill/docs/API/sketch/extrude.md +0 -62
- package/dist-skill/docs/API/sketch/on-face.md +0 -104
- package/dist-skill/docs/API/sketch/operations.md +0 -78
- package/dist-skill/docs/API/sketch/path.md +0 -75
- package/dist-skill/docs/API/sketch/primitives.md +0 -146
- package/dist-skill/docs/API/sketch/regions.md +0 -80
- package/dist-skill/docs/API/sketch/text.md +0 -108
- package/dist-skill/docs/API/sketch/transforms.md +0 -65
- package/dist-skill/docs/API/toolbox/fasteners.md +0 -129
- package/dist-skill/docs/INDEX.md +0 -94
- package/dist-skill/docs/RELEASING.md +0 -55
- package/dist-skill/docs/cli-monetization.md +0 -111
- package/dist-skill/docs/deployment.md +0 -281
- package/dist-skill/docs/generated/concepts.md +0 -2112
- package/dist-skill/docs/internals/shape-from-slices.md +0 -152
- package/dist-skill/docs/platform/admin.md +0 -45
- package/dist-skill/docs/platform/architecture.md +0 -79
- package/dist-skill/docs/platform/auth.md +0 -110
- package/dist-skill/docs/platform/email.md +0 -67
- package/dist-skill/docs/platform/projects.md +0 -111
- package/dist-skill/docs/platform/sharing.md +0 -90
- package/dist-skill/docs/runbook.md +0 -345
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
skill-group: dev-conventions
|
|
3
|
-
skill-order: 3
|
|
4
|
-
skill-tiers: [dev]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# ForgeCAD Deployment & Environment
|
|
8
|
-
|
|
9
|
-
See also the **[Runbook](runbook.md)** for day-to-day operations, testing, troubleshooting, and API reference.
|
|
10
|
-
|
|
11
|
-
ForgeCAD runs as a Docker Compose stack. There are two compose files:
|
|
12
|
-
|
|
13
|
-
- **`docker-compose.yml`** — Full self-hosted stack (Caddy + ForgeCAD + PostgreSQL + Redis). Use this for manual VPS deployment.
|
|
14
|
-
- **`docker-compose.coolify.yml`** — Simplified stack for Coolify (ForgeCAD + PostgreSQL only). Coolify handles TLS and reverse proxy.
|
|
15
|
-
|
|
16
|
-
Production runs on **Hetzner** via **Coolify**, which auto-deploys on push to `mainline`.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## Architecture
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
Internet
|
|
24
|
-
│
|
|
25
|
-
├─ Coolify Proxy (Traefik) ← TLS termination, routing
|
|
26
|
-
│ │
|
|
27
|
-
│ └─ forgecad container ← Fastify app (Node.js)
|
|
28
|
-
│ │
|
|
29
|
-
│ ├─ Serves SPA (dist/) ← Vite-built React frontend
|
|
30
|
-
│ ├─ API routes (/api/*) ← Auth, projects, files
|
|
31
|
-
│ └─ connects to ──────► postgresql container
|
|
32
|
-
│
|
|
33
|
-
└─ Volume: project-data ← User project files on disk
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
In the self-hosted compose file, Caddy replaces Coolify's proxy, and Redis/Valkey is added for rate limiting.
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## Environment Variables
|
|
41
|
-
|
|
42
|
-
### Server Core
|
|
43
|
-
|
|
44
|
-
These configure the Fastify application server itself.
|
|
45
|
-
|
|
46
|
-
| Variable | Required | Default | Purpose |
|
|
47
|
-
|----------|----------|---------|---------|
|
|
48
|
-
| `NODE_ENV` | no | `development` | Set to `production` for deployed instances |
|
|
49
|
-
| `FORGE_PORT` | no | `5173` | HTTP port the server listens on |
|
|
50
|
-
| `FORGE_HOST` | no | `127.0.0.1` | Bind address. Use `0.0.0.0` in Docker |
|
|
51
|
-
| `FORGE_DIST_DIR` | no | — | Path to Vite build output (the SPA). In Docker: `/app/dist` |
|
|
52
|
-
|
|
53
|
-
### Database
|
|
54
|
-
|
|
55
|
-
ForgeCAD uses PostgreSQL 16 for users, projects, sessions, and audit logs. The database schema is managed by Drizzle ORM with auto-migrations on server startup.
|
|
56
|
-
|
|
57
|
-
| Variable | Required | Default | Purpose |
|
|
58
|
-
|----------|----------|---------|---------|
|
|
59
|
-
| `FORGE_DB_URL` | **yes** | — | PostgreSQL connection string |
|
|
60
|
-
|
|
61
|
-
**How the connection is wired in Coolify:**
|
|
62
|
-
|
|
63
|
-
Coolify auto-generates credentials for linked database services and injects them as `SERVICE_USER_POSTGRES` and `SERVICE_PASSWORD_POSTGRES`. The compose file constructs the full URL from these:
|
|
64
|
-
|
|
65
|
-
```yaml
|
|
66
|
-
FORGE_DB_URL=postgresql://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@postgresql:5432/${POSTGRES_DB:-forgecad}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
The hostname `postgresql` is the Docker Compose service name — Docker's internal DNS resolves it to the postgres container. You never need to set `FORGE_DB_URL` directly in Coolify; it assembles itself from Coolify's auto-generated service credentials.
|
|
70
|
-
|
|
71
|
-
**In the self-hosted compose file**, the pattern is simpler:
|
|
72
|
-
|
|
73
|
-
```yaml
|
|
74
|
-
FORGE_DB_URL=postgresql://forgecad:${POSTGRES_PASSWORD}@postgres:5432/forgecad
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Here you set `POSTGRES_PASSWORD` in a `.env` file and the same value is shared with the postgres container.
|
|
78
|
-
|
|
79
|
-
### Authentication
|
|
80
|
-
|
|
81
|
-
Authentication uses JWT access tokens (short-lived, 15 min) and refresh tokens (7 days, stored in DB with rotation and replay detection).
|
|
82
|
-
|
|
83
|
-
| Variable | Required | Default | Purpose |
|
|
84
|
-
|----------|----------|---------|---------|
|
|
85
|
-
| `FORGE_JWT_SECRET` | **yes** | — | HMAC key for signing JWT tokens. Generate with `openssl rand -base64 32` |
|
|
86
|
-
| `FORGE_JWT_ACCESS_EXPIRES` | no | `15m` | Access token lifetime |
|
|
87
|
-
| `FORGE_JWT_REFRESH_EXPIRES` | no | `7d` | Refresh token lifetime |
|
|
88
|
-
|
|
89
|
-
**The JWT secret is critical.** Without it, login and registration complete the database operations but crash when issuing tokens — the user gets a 500 error. The server starts without it (the value is lazily read), but all auth endpoints fail.
|
|
90
|
-
|
|
91
|
-
### CORS & Public URL
|
|
92
|
-
|
|
93
|
-
These tell the server which origins to trust and how to construct user-facing URLs (e.g., in emails).
|
|
94
|
-
|
|
95
|
-
| Variable | Required | Default | Purpose |
|
|
96
|
-
|----------|----------|---------|---------|
|
|
97
|
-
| `FORGE_ALLOWED_ORIGINS` | no | `http://localhost:5173` | Comma-separated list of allowed CORS origins |
|
|
98
|
-
| `FORGE_APP_URL` | no | `http://localhost:5173` | Public base URL for the app. Used in email links |
|
|
99
|
-
|
|
100
|
-
For production, set `FORGE_ALLOWED_ORIGINS=https://forgecad.io` and `FORGE_APP_URL=https://forgecad.io`.
|
|
101
|
-
|
|
102
|
-
### OAuth Providers
|
|
103
|
-
|
|
104
|
-
Optional. If not set, the corresponding "Sign in with X" button won't appear on the login page.
|
|
105
|
-
|
|
106
|
-
| Variable | Required | Default | Purpose |
|
|
107
|
-
|----------|----------|---------|---------|
|
|
108
|
-
| `GITHUB_CLIENT_ID` | no | — | GitHub OAuth app client ID |
|
|
109
|
-
| `GITHUB_CLIENT_SECRET` | no | — | GitHub OAuth app client secret |
|
|
110
|
-
| `GOOGLE_CLIENT_ID` | no | — | Google OAuth client ID |
|
|
111
|
-
| `GOOGLE_CLIENT_SECRET` | no | — | Google OAuth client secret |
|
|
112
|
-
|
|
113
|
-
To set up GitHub OAuth: create an OAuth App at github.com/settings/developers with callback URL `https://forgecad.io/auth/callback/github`.
|
|
114
|
-
|
|
115
|
-
### Email Delivery
|
|
116
|
-
|
|
117
|
-
Email is used for account verification and password reset. Without `RESEND_API_KEY`, emails are logged to the container's stdout instead of being sent — useful for development, but users won't receive them.
|
|
118
|
-
|
|
119
|
-
| Variable | Required | Default | Purpose |
|
|
120
|
-
|----------|----------|---------|---------|
|
|
121
|
-
| `RESEND_API_KEY` | no | — | API key from [resend.com](https://resend.com). Enables real email delivery |
|
|
122
|
-
| `FORGE_EMAIL_FROM` | no | `ForgeCAD <noreply@forgecad.io>` | Sender address for outgoing emails |
|
|
123
|
-
|
|
124
|
-
To enable email: sign up at Resend, verify `forgecad.io` as a sending domain (add their DNS records), get an API key, and set it in Coolify.
|
|
125
|
-
|
|
126
|
-
### File Storage
|
|
127
|
-
|
|
128
|
-
User project files (`.forge.js`, meshes) are stored on disk, not in the database.
|
|
129
|
-
|
|
130
|
-
| Variable | Required | Default | Purpose |
|
|
131
|
-
|----------|----------|---------|---------|
|
|
132
|
-
| `FORGE_STORAGE_ROOT` | no | `/data/projects` | Root directory for project file storage |
|
|
133
|
-
|
|
134
|
-
In Docker, this is backed by the `project-data` volume, which persists across container rebuilds.
|
|
135
|
-
|
|
136
|
-
---
|
|
137
|
-
|
|
138
|
-
## Coolify-Specific Variables
|
|
139
|
-
|
|
140
|
-
These are managed by Coolify itself — you don't set them manually, but the compose file references them:
|
|
141
|
-
|
|
142
|
-
| Variable | Source | Purpose |
|
|
143
|
-
|----------|--------|---------|
|
|
144
|
-
| `SERVICE_USER_POSTGRES` | Coolify auto-generated | PostgreSQL username |
|
|
145
|
-
| `SERVICE_PASSWORD_POSTGRES` | Coolify auto-generated | PostgreSQL password |
|
|
146
|
-
| `POSTGRES_DB` | Coolify (defaults to `forgecad`) | Database name |
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
|
-
## What You Actually Need to Set in Coolify
|
|
151
|
-
|
|
152
|
-
Only these variables need manual configuration in Coolify's environment settings:
|
|
153
|
-
|
|
154
|
-
1. **`FORGE_JWT_SECRET`** — `openssl rand -base64 32`. Without this, auth is broken.
|
|
155
|
-
2. **`FORGE_ALLOWED_ORIGINS`** — `https://forgecad.io`
|
|
156
|
-
3. **`RESEND_API_KEY`** — from resend.com (optional, but needed for email)
|
|
157
|
-
4. **`GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`** — if you want GitHub login
|
|
158
|
-
5. **`GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET`** — if you want Google login
|
|
159
|
-
|
|
160
|
-
Everything else has working defaults or is auto-generated by Coolify.
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## Database Migrations
|
|
165
|
-
|
|
166
|
-
Migrations run automatically on server startup (`server/db/migrate.ts`). The migration system:
|
|
167
|
-
|
|
168
|
-
1. Creates a `_migrations` table to track which migrations have been applied
|
|
169
|
-
2. Runs any unapplied migrations in order
|
|
170
|
-
3. Logs each migration to stdout
|
|
171
|
-
|
|
172
|
-
No manual database setup is needed. The PostgreSQL container starts with an empty database, and the ForgeCAD server creates all tables on first boot.
|
|
173
|
-
|
|
174
|
-
---
|
|
175
|
-
|
|
176
|
-
## Debugging Production
|
|
177
|
-
|
|
178
|
-
SSH access: `ssh hetzner` (see `~/.ssh/config`).
|
|
179
|
-
|
|
180
|
-
```bash
|
|
181
|
-
# Find containers
|
|
182
|
-
docker ps --format "{{.Names}}" | grep forge
|
|
183
|
-
|
|
184
|
-
# App logs
|
|
185
|
-
docker logs --tail 200 <forgecad-container>
|
|
186
|
-
|
|
187
|
-
# DB access (get credentials from app env first)
|
|
188
|
-
docker exec <forgecad-container> env | grep POSTGRES
|
|
189
|
-
docker exec <postgres-container> psql -U <USER> -d forgecad
|
|
190
|
-
|
|
191
|
-
# System health
|
|
192
|
-
df -h && free -h
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
See the `/hetzner-logs` skill for the full workflow.
|
|
196
|
-
|
|
197
|
-
### Email not delivered (user didn't receive verification/reset email)
|
|
198
|
-
|
|
199
|
-
**Symptom:** User registers or requests password reset, no email arrives. Logs show:
|
|
200
|
-
```
|
|
201
|
-
[email] To: user@example.com | Subject: Verify your ForgeCAD email
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
**Cause:** `RESEND_API_KEY` is empty or missing. The `[email]` log line is the dev fallback — it means the email was *logged* to stdout, not sent.
|
|
205
|
-
|
|
206
|
-
**Check:**
|
|
207
|
-
```bash
|
|
208
|
-
docker exec <forgecad-container> env | grep RESEND_API_KEY
|
|
209
|
-
# → RESEND_API_KEY= ← empty = emails not sent
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
**Fix:** Set `RESEND_API_KEY` in Coolify environment variables → redeploy.
|
|
213
|
-
|
|
214
|
-
### Connecting a DB client (e.g. Beekeeper Studio) to prod
|
|
215
|
-
|
|
216
|
-
The PostgreSQL container has no host port mapping — `localhost:5432` is not reachable from outside the server. Instead use an SSH tunnel to the container's Docker network IP.
|
|
217
|
-
|
|
218
|
-
1. Find the container IP (run once, it's stable across restarts within the same Coolify stack):
|
|
219
|
-
```bash
|
|
220
|
-
ssh hetzner "docker inspect \$(docker ps -qf name=postgresql) | grep '\"IPAddress\"'"
|
|
221
|
-
# → 10.0.2.3 (or similar)
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
2. In Beekeeper Studio, configure the SSH tunnel:
|
|
225
|
-
- SSH Host: `65.108.210.215`, User: `kostard`, use your private key
|
|
226
|
-
- DB Host: `10.0.2.3`, Port: `5432`
|
|
227
|
-
- Credentials: from Coolify's auto-generated `SERVICE_USER_POSTGRES` / `SERVICE_PASSWORD_POSTGRES`
|
|
228
|
-
- Database: `forgecad`
|
|
229
|
-
|
|
230
|
-
> `AllowTcpForwarding yes` must be set in `/etc/ssh/sshd_config` on the server for the tunnel to work.
|
|
231
|
-
|
|
232
|
-
---
|
|
233
|
-
|
|
234
|
-
## Local Development
|
|
235
|
-
|
|
236
|
-
### Quick start (editor only, no auth)
|
|
237
|
-
|
|
238
|
-
For working on the CAD editor, geometry, sketches, or viewer:
|
|
239
|
-
|
|
240
|
-
```bash
|
|
241
|
-
npm run dev
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
Opens the editor with local example files. No login, no database. Fastest workflow for anything that doesn't touch auth or multi-user features. Vite proxies `/api` to port 5174 but the backend is optional — the editor works without it.
|
|
245
|
-
|
|
246
|
-
### Production build locally (test real server behavior)
|
|
247
|
-
|
|
248
|
-
For testing WASM serving, bundle sizes, caching headers — the full production Fastify server on your machine:
|
|
249
|
-
|
|
250
|
-
```bash
|
|
251
|
-
npm run dev:db # start PostgreSQL (once)
|
|
252
|
-
npm run dev:prod # tsc + vite build + run Fastify server
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
Open `http://localhost:5173` — same server code as production, serving the Vite production build. ~25s turnaround.
|
|
256
|
-
|
|
257
|
-
### Full stack (auth, database, landing page, docs, blog)
|
|
258
|
-
|
|
259
|
-
For working on the hosted application:
|
|
260
|
-
|
|
261
|
-
```bash
|
|
262
|
-
# Terminal 1: start PostgreSQL (once)
|
|
263
|
-
npm run dev:db
|
|
264
|
-
|
|
265
|
-
# Terminal 2: start Fastify API server (port 5174)
|
|
266
|
-
npm run dev:server
|
|
267
|
-
|
|
268
|
-
# Terminal 3: start Vite dev server (port 5173, proxies /api to 5174)
|
|
269
|
-
npm run dev:studio
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
Open `http://localhost:5173` — landing page, login, docs, blog, admin, the full thing.
|
|
273
|
-
|
|
274
|
-
To stop the database: `npm run dev:db:stop`
|
|
275
|
-
|
|
276
|
-
**Dev credentials** (hardcoded in `dev:server`, never used in production):
|
|
277
|
-
- Database: `forgecad:forgecad@localhost:5432/forgecad`
|
|
278
|
-
- JWT secret: `dev-secret-do-not-use-in-production`
|
|
279
|
-
- Allowed origin: `http://localhost:5173`
|
|
280
|
-
|
|
281
|
-
Migrations run automatically on server startup.
|