When the Unlayer editor calls PUT /campaigns/templates/:name to save a
design, the hub writes:
• templates/<name>.html (compiled email-safe HTML)
• templates/<name>.json (Unlayer design tree for editor restore)
• templates/<name>.bak-<ts>.html (backup of previous version)
All three need write access to /app/templates inside the container.
The mount was previously declared as :ro, which made these writes
fail with EROFS (read-only filesystem) once the editor was wired up.
Two changes:
1. Local docker-compose.yml: add ./templates:/app/templates (without
:ro) and ./uploads:/app/uploads (which was already RW on prod but
missing from the committed file — local was out of sync).
2. Prod docker-compose.yml: hot-patched via sed on prod to drop the
:ro flag, then `docker compose down + up -d` to apply the mount
change. PUT verified working (returns 200 with size + design_size).
The /app/lib, /app/server.js, /app/public, /app/package.json mounts stay
:ro since the hub never writes to those — keeping the read-only flag
there is defense-in-depth against compromised code overwriting itself.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>