Barclays-banner-builder/docs/project/infrastructure.md
Vadym Samoilenko 24713ce5e6 Add Oliver rebrand, character counts, delete variants, 6-format spec validation
- Rebrand LoginPage logo to Oliver design system
- Move Admin nav link to bottom-left user area
- Remove "Ask AI to improve" button from step 2 (VariantsGrid)
- Add CharCount component with copy limits across prompt, edit, and export views
- Add delete variant with confirmation dialog on step 2 cards
- Add theme palette migration (0007_theme_palette.py)
- Add copyLimits.ts and themes.ts libs
- Remove unused BannerEditor.tsx page and old logo PNG
- Add AGENTS.md project entry point
- Add docs/ directory

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 15:35:25 +01:00

5.5 KiB

Infrastructure

Server

Property Value
Host optical-dev.oliver.solutions
OS Ubuntu (shared host)
Deployment path /opt/barclays-banner-builder/
Static SPA path /var/www/html/barclays-banner-builder/
Live URL https://optical-dev.oliver.solutions/barclays-banner-builder/
API URL https://optical-dev.oliver.solutions/barclays-banner-builder/api/
API docs (dev only) https://optical-dev.oliver.solutions/barclays-banner-builder/docs

Docker Services

Development (docker-compose.yml)

Service Image / Build Host port Container port Role
postgres pgvector/pgvector:pg16 Not exposed 5432 Database
redis redis:7-alpine Not exposed 6379 Queue broker
api ./backend (dev target) 127.0.0.1:8010 8000 FastAPI + uvicorn
worker ./backend (dev target) None RQ worker
web ./frontend (dev target) 5174 5174 Vite dev server

Production (docker-compose.prod.yml)

Service Image / Build Host port Notes
postgres pgvector/pgvector:pg16 Not exposed restart: always, internal network
redis redis:7-alpine Not exposed restart: always, internal network
api ./backend (prod target) 127.0.0.1:8010 2 uvicorn workers, restart: always
worker ./backend (prod target) None rq worker --with-scheduler, restart: always

No web container in prod — Apache serves the React SPA from the filesystem.


Docker Volumes

Volume Mount point (api/worker) Purpose
postgres_data /var/lib/postgresql/data PostgreSQL data directory
redis_data /data Redis persistence
pdf_artifacts /artifacts Generated PDF contact sheets
./backend (bind) /app Backend source code (dev: hot reload)
./assets (bind, ro) /assets Illustration PNGs + templates
./rag-corpus (bind, ro) /rag-corpus RAG .docx source files

Docker Network

In production, all services share the internal bridge network. The API is the only container with a host port binding (127.0.0.1:8010). PostgreSQL and Redis are not reachable from outside Docker.


Apache Configuration

File: deploy/apache-barclays.conf — included into the main vhost at: /etc/apache2/sites-enabled/optical-dev.oliver.solutions.conf

Location Handler Target
/barclays-banner-builder/api/ ProxyPass http://127.0.0.1:8010/api/
/barclays-banner-builder/docs ProxyPass http://127.0.0.1:8010/docs
/barclays-banner-builder/openapi.json ProxyPass http://127.0.0.1:8010/openapi.json
/barclays-banner-builder Alias /var/www/html/barclays-banner-builder
/barclays-banner-builder/* FallbackResource index.html (React Router)

The FollowSymLinks option is required — deploy.sh creates a symlink at {WEB_DIR}/illustrations → {REPO_DIR}/assets/illustrations so Apache serves PNGs directly without going through the API proxy.


Backend Dockerfile

Multi-stage build in backend/Dockerfile:

Stage Base Purpose
base python:3.12-slim Install OS deps (WeasyPrint, Pillow) + pip install package
dev base Copy source; pip installs dev extras (pytest, ruff, mypy)
prod base Copy source; production-only install

OS deps installed: libpango, libpangocairo, libgdk-pixbuf, libcairo2, libffi-dev, libgirepository1.0-dev, shared-mime-info, fonts-liberation (required by WeasyPrint for PDF rendering).


Frontend Dockerfile

frontend/Dockerfile — dev target runs Vite dev server. Production build is done on the host by deploy.sh and static files are copied to /var/www/html/barclays-banner-builder/.


Deployment Flow (deploy.sh)

Step What happens
1. Preflight Check docker, node, npm, git
2. Pull code git pull --ff-only origin main
3. Validate .env Fail if OPENAI_API_KEY, POSTGRES_PASSWORD, SECRET_KEY are empty
4. Build images Rebuild only if backend/Dockerfile or pyproject.toml changed (hash check)
5. Start DB + Redis docker compose up -d postgres redis; wait for healthcheck
6. Start API docker compose up -d api; 3-second startup wait
7. Migrations alembic upgrade head inside api container
8. First-run seed Seed admin user if users table is empty
9. RAG ingest Embed RAG corpus if rag_chunks is empty (or --reindex)
10. Icon indexing Index illustrations if icons table is empty (or --reindex)
11. Frontend build npm ci (cached on package.json hash) + npm run build
12. Frontend deploy rsync to /var/www/html/barclays-banner-builder/
13. Restart services docker compose up -d --no-deps --force-recreate api worker
14. Apache config Insert Include fragment into vhost if not already present; apache2ctl configtest + systemctl reload apache2
15. Health check Curl /api/health — up to 15 retries with 2s sleep

Port Allocation on Host

Port Binding Service
8010 127.0.0.1 FastAPI API (proxied by Apache)
8000 (occupied by another project) Not used by this project
8090 (not used in prod) Dev-only Nginx placeholder
5174 0.0.0.0 (dev only) Vite dev server