Document hot-reload workflow for AI agents
Rewrite SAAC_DEPLOYMENT.md to lead with the two-domain model: - Production (yourapp.<server>.domain.com) — updates on saac deploy - Hot-reload (yourapp-hot.<server>.domain.com) — auto-rebuilds on git push Added: recommended dev workflow (push → check hot → deploy to prod), nodemon.json explanation, development cycle diagram, customization guide. Updated Dockerfile and docker-compose.yml headers to explain which container uses which file and reference nodemon.json.
This commit is contained in:
@@ -3,6 +3,82 @@
|
||||
> **READ THIS FIRST.** This file explains exactly how SAAC deploys your app.
|
||||
> Understanding this will save you hours of debugging.
|
||||
|
||||
## Your Two Domains
|
||||
|
||||
Every app gets **two live URLs** on the server. Both are created automatically when you deploy:
|
||||
|
||||
```
|
||||
yourapp.<server>.startanaicompany.com ← PRODUCTION (customers see this)
|
||||
yourapp-hot.<server>.startanaicompany.com ← HOT-RELOAD (you develop with this)
|
||||
```
|
||||
|
||||
For example, if your app domain is `my-saas.adam.startanaicompany.com`:
|
||||
- Production: `https://my-saas.adam.startanaicompany.com`
|
||||
- Hot-reload: `https://my-saas-hot.adam.startanaicompany.com`
|
||||
|
||||
### How to Use Them
|
||||
|
||||
**Hot-reload (`-hot` domain)** — Use this while developing. Every `git push` automatically:
|
||||
1. Pulls your latest code
|
||||
2. Rebuilds the React frontend (`npm run build`)
|
||||
3. Restarts the Express server
|
||||
4. Your changes are live in ~10-20 seconds
|
||||
|
||||
**Recommended development workflow:**
|
||||
```bash
|
||||
# 1. Make your code changes
|
||||
# 2. Push to git
|
||||
git add . && git commit -m "Add login page" && git push
|
||||
|
||||
# 3. Wait ~15 seconds, then check the hot domain
|
||||
curl https://yourapp-hot.adam.startanaicompany.com/health
|
||||
|
||||
# 4. Once it works on hot, deploy to production
|
||||
saac deploy
|
||||
|
||||
# 5. Verify production
|
||||
curl https://yourapp.adam.startanaicompany.com/health
|
||||
```
|
||||
|
||||
**Production domain** — Only updates when you run `saac deploy`. This rebuilds the Docker image from your Dockerfile and restarts everything. Use this for the final, tested version.
|
||||
|
||||
### Why Two Containers?
|
||||
|
||||
| Container | Domain | How it runs your code | When it updates |
|
||||
|-----------|--------|----------------------|-----------------|
|
||||
| **Production** | `yourapp.example.com` | Built from your `Dockerfile` (immutable Docker image) | Only on `saac deploy` |
|
||||
| **Hot-reload** | `yourapp-hot.example.com` | Volume-mounts your git repo, runs `npm run dev` via nodemon | Automatically on every `git push` |
|
||||
|
||||
**Key differences:**
|
||||
- **Production** uses your Dockerfile. The Docker image is built once and runs until next deploy.
|
||||
- **Hot-reload** does NOT use your Dockerfile. It mounts your source code directly, installs dependencies, builds the React client, and runs Express with nodemon.
|
||||
- **Hot-reload auto-rebuilds everything** — `nodemon.json` watches both `server.js` and `client/src/`. When files change (after `git push`), it runs `npm run build` (React) and restarts `node server.js`.
|
||||
|
||||
### How nodemon.json Works
|
||||
|
||||
The `nodemon.json` file in your repo tells the hot-reload container what to watch:
|
||||
|
||||
```json
|
||||
{
|
||||
"watch": ["server.js", "client/src"],
|
||||
"ext": "js,ts,tsx,jsx,css,json",
|
||||
"exec": "npm run build && node server.js"
|
||||
}
|
||||
```
|
||||
|
||||
- **watch**: Directories/files to monitor for changes
|
||||
- **ext**: File extensions that trigger a rebuild
|
||||
- **exec**: What to run when changes are detected — rebuilds React, restarts Express
|
||||
|
||||
**You can customize this.** For example, if you add a `lib/` directory with shared code:
|
||||
```json
|
||||
{
|
||||
"watch": ["server.js", "client/src", "lib"],
|
||||
"ext": "js,ts,tsx,jsx,css,json",
|
||||
"exec": "npm run build && node server.js"
|
||||
}
|
||||
```
|
||||
|
||||
## The Build Process
|
||||
|
||||
When you run `saac deploy`, the daemon executes these exact commands in your repo:
|
||||
@@ -20,23 +96,6 @@ Your repo MUST have:
|
||||
1. `docker-compose.yml` — defines services (app, postgres, redis)
|
||||
2. `Dockerfile` — referenced by the build directive in compose
|
||||
|
||||
## CRITICAL: Two Containers Per App
|
||||
|
||||
Every app gets TWO containers. Understanding this prevents the #1 debugging confusion:
|
||||
|
||||
| Container | Domain | How it runs your code | When it updates |
|
||||
|-----------|--------|----------------------|-----------------|
|
||||
| **Production** | `yourapp.startanaicompany.com` | Built from your `Dockerfile` (immutable image) | Only on `saac deploy` |
|
||||
| **Hot-reload** | `yourapp-hot.startanaicompany.com` | Volume-mounts your git repo, runs `npm run dev` | Instantly on `git push` |
|
||||
|
||||
**Key facts:**
|
||||
- **Production** runs the Docker image you built. Your Dockerfile, CMD, and build steps all apply.
|
||||
- **Hot-reload** does NOT use your Dockerfile. It mounts your source code directly and runs nodemon/npm run dev.
|
||||
- **Your main domain routes to PRODUCTION, not hot-reload.** If production works but hot-reload doesn't, your app is fine.
|
||||
- **TypeScript projects**: Production container compiles TS in the Dockerfile (`RUN npm run build`). Hot-reload needs a `dev` script in package.json that compiles and runs (e.g., `"dev": "tsc && node dist/server.js"` or `"dev": "tsx watch src/server.ts"`).
|
||||
|
||||
**Common confusion:** "My Docker build works but the app serves old code!" — You're probably looking at the hot-reload container. Check the PRODUCTION domain (without `-hot`).
|
||||
|
||||
## The 5 Rules
|
||||
|
||||
### Rule 1: Use `expose`, NEVER `ports`
|
||||
@@ -93,8 +152,8 @@ DO NOT:
|
||||
|
||||
DO:
|
||||
- Get the template deploying first (`saac deploy`, verify with `saac logs`)
|
||||
- Add one feature, deploy, verify
|
||||
- Add the next feature, deploy, verify
|
||||
- Add one feature, push, check the hot domain
|
||||
- When it works, add the next feature
|
||||
- **Coordinate deploys** — only ONE agent should push/deploy at a time
|
||||
|
||||
### Rule 5: Dockerfile must produce a running container
|
||||
@@ -135,6 +194,22 @@ saac exec "cat package.json" # Check what's in the container
|
||||
saac db sql "SELECT * FROM users LIMIT 5" # Query database
|
||||
```
|
||||
|
||||
## Quick Reference: Development Cycle
|
||||
|
||||
```
|
||||
git push ──→ hot-reload updates (~15s) ──→ check yourapp-hot domain
|
||||
│ │
|
||||
│ ┌─────── works? ──┘
|
||||
│ │
|
||||
│ YES ────┤──── NO
|
||||
│ │ │ │
|
||||
│ saac deploy │ fix code, git push again
|
||||
│ │ │
|
||||
│ production │
|
||||
│ updated │
|
||||
└────────────────────────────┘
|
||||
```
|
||||
|
||||
## Common Mistakes and Fixes
|
||||
|
||||
| Mistake | Fix |
|
||||
@@ -145,8 +220,9 @@ saac db sql "SELECT * FROM users LIMIT 5" # Query database
|
||||
| `tsc: not found` in Dockerfile | Install ALL deps first: `RUN npm install` (not `--production`) |
|
||||
| `.dockerignore` has `dist/` | Remove it — dist is built inside container |
|
||||
| Multiple agents deploying simultaneously | Coordinate — one agent deploys at a time |
|
||||
| "App serves old code" | Check production domain (not hot-reload). Run `saac deploy` to rebuild. |
|
||||
| Hot-reload container crashes | This is separate from production. Fix `package.json` `dev` script. |
|
||||
| "App serves old code" on production | Run `saac deploy` to rebuild the Docker image |
|
||||
| "App serves old code" on hot domain | Wait ~15s after push. Check `saac logs` for rebuild errors |
|
||||
| Hot-reload container crashes | Check `saac logs` — usually a missing dependency or build error |
|
||||
|
||||
## Do NOT Add Traefik Labels
|
||||
|
||||
|
||||
Reference in New Issue
Block a user