Azione!Lab
A warm, editorial single-page website for a contemporary theatre workshop. Wagtail provides an editor-friendly headless CMS, Astro renders the public site, PostgreSQL stores content, and Docker Compose supplies a reproducible local environment.
Architecture
backend/: Django and Wagtail admin, content models, media uploads, and the aggregate read-only API atGET /api/site/home/.frontend/: Astro components, responsive design system, typed API adapter, and Italian fallback content for development when the CMS is unavailable.nginx/: reverse-proxy virtual host forazionelab.org, routing public requests to Astro or Wagtail.db: persistent PostgreSQL database.- Docker volumes:
postgres_datafor the database andmedia_datafor uploads.
See the architecture document, ADR-0001, and ADR-0002 for the rationale.
Prerequisites
- Docker Engine with Docker Compose v2.
- Ports
8080,4321, and8000available on localhost. - A local hosts-file entry mapping
azionelab.orgto127.0.0.1.
No host Python or Node.js installation is required.
Start locally
cp .env.example .env
docker compose up --build -d
docker compose ps
docker compose exec backend python manage.py seed_demo
For local domain resolution, add this line to /etc/hosts using your normal system
administration workflow:
127.0.0.1 azionelab.org
Open:
- public site: http://azionelab.org:8080
- Wagtail admin: http://azionelab.org:8080/admin/
- aggregate API: http://azionelab.org:8080/api/site/home/
Direct loopback ports 4321 and 8000 remain available for local diagnostics only.
The frontend remains usable with curated fallback content if the API is unavailable. On first startup the backend applies migrations and collects static files before starting Gunicorn. Wait until all four services report healthy.
Create an editor account
docker compose exec backend python manage.py createsuperuser
Sign in to Wagtail at http://azionelab.org:8080/admin/. The public site has no user accounts or authentication.
Demo content
The seed command is idempotent and creates or updates the initial home page, site settings, participation cards, teacher, lessons, shows, gallery entries, and local placeholder images:
docker compose exec backend python manage.py seed_demo
Re-run it only when you intentionally want to restore the demo records. Content edited after seeding may be overwritten for records managed by the command.
Editing content
- Open Wagtail admin and select Pages to edit the home hero, introduction, laboratory section, and the three participation cards.
- Select Settings > Site settings for the workshop name and contact details.
- Use Snippets for the teacher, lessons, shows, and gallery.
- Publish page changes. Snippet and settings changes are returned immediately by the aggregate endpoint.
The frontend reads PUBLIC_CMS_API_URL; inside Compose it defaults to
http://backend:8000. Media URLs use WAGTAILADMIN_BASE_URL so browsers receive the
public reverse-proxy address. Change both values for another environment.
The standard published-page endpoint is also available at /api/v2/pages/.
The PostgreSQL service is named db. Existing .env files should replace @postgres:
with @db: in DATABASE_URL; a compatibility network alias keeps older local values
working during the transition.
Useful commands
# Follow application logs
docker compose logs -f db backend frontend proxy
# Run database migrations
docker compose exec backend python manage.py migrate
# Run all required checks in containers
docker compose run --rm backend python manage.py test
docker compose run --rm frontend npm run check
docker compose run --rm frontend npm run build
docker compose run --rm proxy nginx -t
docker compose -f docker-compose.yml -f docker-compose.test.yml --profile test run --rm backend python manage.py seed_demo
docker compose -f docker-compose.yml -f docker-compose.test.yml --profile test run --build --rm functional-tests
docker compose config --quiet
# Stop the stack without deleting content
docker compose down
# Stop and permanently delete local database and uploaded media
docker compose down --volumes
The final command is destructive. It is useful only when intentionally resetting the local environment; run the seed command again after the next startup.
Directory structure
.
├── backend/ # Wagtail/Django CMS and API
├── frontend/ # Astro public website
├── nginx/ # Reverse-proxy virtual host
├── tests/functional/ # Playwright browser tests
├── docker-compose.test.yml # Functional-test Compose override
├── docs/ # Architecture, operations, security, and ADRs
├── docker-compose.yml
├── .env.example
└── README.md
Functional tests
The Compose test override builds a pinned Playwright image, exposes azionelab.org on
the internal Docker network, and runs the browser suite against NGINX. It replaces the
database mount with the isolated test_postgres_data volume, so the normal CMS data is
not changed. Refresh the idempotent test seed first:
docker compose -f docker-compose.yml -f docker-compose.test.yml --profile test run --rm backend python manage.py seed_demo
docker compose -f docker-compose.yml -f docker-compose.test.yml --profile test run --build --rm functional-tests
The suite covers page content and section order, contact actions, mobile navigation, responsive overflow, semantic landmarks, image alternatives, the aggregate API and media, Wagtail admin routing, and rejection of unknown virtual hosts.
Database and media backups
Database rows and uploaded files must be backed up together:
mkdir -p backups/media
docker compose stop frontend backend
docker compose exec -T db sh -c 'pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB"' > backups/database.sql
docker compose cp backend:/app/media/. backups/media/
docker compose start backend frontend
This brief maintenance window keeps database rows and uploaded files in sync. See
operations for the destructive restore procedure and its
cautions. Do not commit database dumps, .env, or uploaded media.
Production TODOs
This repository deliberately targets a simple, working local deployment. Before a public production launch, add TLS certificates, production-grade static/media serving, off-host backups, monitoring, and a deployment-specific secret manager.