# ByteLyst NoteLett - Agent Instructions > This file is read automatically by Claude Code. For full project instructions > shared across all AI tools, see [`CONTEXT.md`](CONTEXT.md). ## Critical Deployment Patterns (Learned from Production Deployment) ### 1. Docker Build Preparation **Before building Docker images, you MUST run the dependency packing script:** ```bash bash scripts/docker-prep.sh ``` This script: - Builds all @bytelyst/* packages from learning_ai_common_plat - Packs them as tarballs in `.docker-deps/` - Rewrites package.json files to reference the tarballs - Injects pnpm.overrides for version consistency **After building, ALWAYS restore the package.json files:** ```bash bash scripts/docker-prep.sh --restore ``` ### 2. Dockerfile Configuration **Dockerfiles MUST be updated to remove Gitea secrets and use .docker-deps:** **Backend Dockerfile changes:** - Remove `--mount=type=secret,id=gitea_npm_token` lines - Remove TOKEN environment setup - Add `COPY .docker-deps/ ../.docker-deps/` before install - Simplified install command: `RUN pnpm install --ignore-scripts --lockfile=false` **Web Dockerfile changes:** - Remove `--mount=type=secret,id=gitea_npm_token` lines - Remove GITEA_NPM_TOKEN environment setup - Ensure .docker-deps is copied before install ### 3. Public API URL Configuration **NEXT_PUBLIC_ environment variables MUST use public URLs, not internal Docker network names:** **Incorrect:** ```yaml NEXT_PUBLIC_NOTES_API_URL: http://localhost:4016/api NEXT_PUBLIC_NOTES_API_URL: http://backend:4011 ``` **Correct:** ```yaml NEXT_PUBLIC_NOTES_API_URL: https://api.bytelyst.com/notelett ``` This is because browsers cannot access internal Docker network names. The web app needs to connect to the public API endpoint. ### 4. Docker Compose Environment Variable Format **Use YAML mapping syntax, NOT array syntax:** **Incorrect:** ```yaml environment: - NODE_ENV=production - PORT=4016 ``` **Correct:** ```yaml environment: NODE_ENV: production PORT: 4016 ``` ### 5. Production vs Development Mode **Production mode (NODE_ENV=production) requires:** - DB_PROVIDER: cosmos (not memory) - FIELD_ENCRYPT_ENABLED: true (not false) - FIELD_ENCRYPT_KEY_PROVIDER: akv or env (not memory) **If these are not configured, use development mode:** ```yaml NODE_ENV: development ``` ### 6. Container Names for Caddy Routing **Container names MUST match Caddyfile configuration:** - Backend: `notelett-backend` - Web: `notelett-web` Add to docker-compose.yml: ```yaml services: backend: container_name: notelett-backend web: container_name: notelett-web ``` ### 7. Caddy Network Connectivity **Caddy MUST be connected to the app networks for reverse proxy:** ```bash docker network connect learning_ai_notes_default caddy docker network connect learning_ai_common_plat_default caddy ``` ### 8. DNS Configuration **For new subdomains, add DNS records via GoDaddy API:** ```bash # Example for notes.bytelyst.com curl -X PUT "https://api.godaddy.com/v1/domains/bytelyst.com/records/A/notes" \ -H "Authorization: sso-key $GODADDY_API_KEY:$GODADDY_API_SECRET" \ -H "Content-Type: application/json" \ -d '[{"data": "187.124.159.82", "name": "notes", "ttl": 600, "type": "A"}]' ``` Use the same IP as other bytelyst.com subdomains (187.124.159.82). ### 9. Caddy Configuration Pattern **Add subdomain routing to /opt/bytelyst/Caddyfile:** ```caddy notes.bytelyst.com { encode gzip reverse_proxy notelett-web:3045 } ``` Then reload Caddy: ```bash docker exec caddy caddy reload --config /etc/caddy/Caddyfile ``` ### 10. Deployment Script Usage **ALWAYS use the deployment script from learning_ai_devops_tools:** ```bash cd ../learning_ai_devops_tools bash deploy-notes.sh ``` Options: - Option 1: Normal deployment (with cache, with health checks) - Option 5: Force + No-cache (skip checks, force rebuild) - use when config changes - Option 6: Force + Skip health checks (skip both) - use when health checks are flaky ## Deployment Checklist Before deploying: 1. [ ] Run `bash scripts/docker-prep.sh` to package dependencies 2. [ ] Update Dockerfiles to remove Gitea secrets and use .docker-deps 3. [ ] Set NEXT_PUBLIC_ variables to use public API URLs 4. [ ] Use YAML mapping syntax for environment variables 5. [ ] Set correct NODE_ENV (development unless Cosmos/AKV configured) 6. [ ] Set container names to match Caddyfile 7. [ ] Update Caddyfile with subdomain routing 8. [ ] Add DNS records via GoDaddy API 9. [ ] Connect Caddy to app networks 10. [ ] Run deployment script with appropriate options After deploying: 1. [ ] Run `bash scripts/docker-prep.sh --restore` to restore package.json 2. [ ] Test public URL accessibility 3. [ ] Test API endpoint accessibility 4. [ ] Verify SSL certificates are working 5. [ ] Check container logs for errors 6. [ ] Commit and push changes ## Common Deployment Errors and Solutions ### Error: "failed to calculate checksum of ref: /.docker-deps: not found" **Solution:** Run `bash scripts/docker-prep.sh` before building ### Error: "HTTP 400 urn:ietf:params:acme:error:dns - DNS problem: NXDOMAIN" **Solution:** DNS records not propagated yet. Wait 5-30 minutes after adding DNS records, then restart Caddy. ### Error: "Production DB_PROVIDER must be cosmos" **Solution:** Either configure Cosmos DB credentials or set NODE_ENV to development ### Error: "services.web.environment.[3]: unexpected type map[string]interface {}" **Solution:** Convert environment variables from array syntax to YAML mapping syntax ### Error: React hydration errors or backend connection failures **Solution:** Check that NEXT_PUBLIC_ variables use public API URLs, not internal Docker network names ## Quick Deployment Commands ```bash # Prepare dependencies bash scripts/docker-prep.sh # Deploy cd ../learning_ai_devops_tools echo "5" | bash deploy-notes.sh # Force + No-cache # Restore after deployment bash scripts/docker-prep.sh --restore # Test curl -I https://notes.bytelyst.com curl -s https://api.bytelyst.com/notelett/health ``` ## Key Files for Deployment - `docker-compose.yml` - Container configuration - `backend/Dockerfile` - Backend container build - `web/Dockerfile` - Web container build - `scripts/docker-prep.sh` - Dependency packaging script - `/opt/bytelyst/Caddyfile` - Reverse proxy configuration - `../learning_ai_devops_tools/deploy-notes.sh` - Deployment script