The digital archive of arts centre VIERNULVIER - search decades of culture in Ghent.
Live website · API Docs · Wiki · CMS · User Manual
- About the project
- Architecture
- Tech stack
- Getting started
- Environments
- Running tests
- Linting & formatting
- Data synchronisation
- Deployment
- Wiki
VIERNULVIER is an arts centre in Ghent with a rich history of performances. That archive data was until now not publicly available via the main website - this application solves that.
VIERNULVIER Archive provides a searchable archive website where visitors can discover decades of cultural history: performances, series, locations, media and more - synchronised directly from the VIERNULVIER/Peppered API.
viernulvier-2/
├── backend/ # Django REST API - domain apps, serializers, views, tests
├── frontend/ # React + TypeScript app built with Vite
├── infrastructure/ # Docker Compose, nginx, certbot configuration
└── wiki/ # Architecture notes and developer guides
┌─────────────────────────────────────────────────────────────┐
│ Browser │
└───────────────────────────┬─────────────────────────────────┘
│ HTTPS
┌───────────────────────────▼─────────────────────────────────┐
│ nginx │
│ (reverse proxy + static frontend files) │
└──────────┬────────────────────────────────┬─────────────────┘
│ /api/* /admin/* │ /*
┌──────────▼──────────────┐ ┌───────────▼───────────────┐
│ Django REST Backend │ │ React Frontend (Vite) │
│ (Gunicorn + Python) │ │ (static build) │
└──────────┬──────────────┘ └───────────────────────────┘
│
┌──────────▼──────────────┐ ┌───────────────────────────┐
│ PostgreSQL │ │ VIERNULVIER/Peppered API │
│ (database) │ │ (external data source) │
└─────────────────────────┘ └───────────────────────────┘
Full architecture documentation is available on the Architecture wiki page.
| Layer | Technology |
|---|---|
| Backend | Python 3.10+, Django, Django REST Framework, pytest |
| Frontend | TypeScript, React 19, Vite, Material UI, i18next |
| Database | PostgreSQL |
| Reverse proxy | nginx |
| TLS | Let's Encrypt / certbot |
| Lint / format | ruff (Python), ESLint + Prettier (TypeScript) |
| CI/CD | GitHub Actions + self-hosted runner |
| Containers | Docker & Docker Compose |
| Tool | Version |
|---|---|
| Python | 3.10+ |
| Node.js / npm | v24+ |
| Docker & Docker Compose | recent version |
| Git | recent version |
Tip: Docker is optional for native development, but required for staging and production.
# 1. Copy the environment file
cp infrastructure/.env.example infrastructure/.env
# 2. Start the database (PostgreSQL via Docker)
docker compose -f infrastructure/docker-compose.dev.yml up -d
# 3. Create a virtual environment and activate it
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 4. Install dependencies
pip install -r backend/requirements/development.txt
# 5. Run migrations
cd backend
python manage.py makemigrations
python manage.py migrate
# 6. (Optional) Create a superuser for /admin/
python manage.py createsuperuser
# 7. Start the dev server -> http://localhost:8000
python manage.py runserverStop the database when you're done:
docker compose -f infrastructure/docker-compose.dev.yml downcd frontend
# Install dependencies
npm ci
# Start the dev server -> http://localhost:5173
npm run dev
# Build for production
npm run buildStart backend, frontend and database simultaneously:
docker compose -f infrastructure/docker-compose.staging.yml up --buildThe full stack is then accessible at:
| Service | URL |
|---|---|
| Frontend | http://localhost/ |
| API | http://localhost/api/ |
| Admin | http://localhost/admin/ |
| API Docs | http://localhost/api/docs/ |
| Environment | Compose file | What runs | Purpose |
|---|---|---|---|
| Dev | docker-compose.dev.yml |
PostgreSQL only | Fast iteration - Django + Vite run natively |
| Staging | docker-compose.staging.yml |
PostgreSQL, backend, frontend, nginx | Full local stack at http://localhost |
| Production | docker-compose.prod.yml |
PostgreSQL, backend, frontend, nginx, certbot | Self-hosted deployment on a public server |
cd backend
# Full test suite
pytest
# Single app
pytest tests/events
# With coverage
coverage run -m pytest
coverage report -mFull CI check (required before a PR):
ruff check . # lint
ruff format --check . # formatting
python manage.py check # Django system check
python manage.py makemigrations --check --dry-run # no pending migrations
pytest # test suitecd frontend
npm ci
npm testSee the Testing wiki page for a full overview of the test structure and guidelines.
cd backend
ruff check . # lint
ruff format --check . # check formatting
ruff format . # automatically fix formattingcd frontend
npm run lint # lint
npm run lint:fix # automatically fix
npm run format:check # check formatting
npm run format:fix # automatically fix formattingCI behaviour: On a push to
main, lint errors are automatically fixed and committed back. On a pull request, CI fails if there are errors - resolve them locally before pushing.
The sync_viernulvier management command fetches data from the VIERNULVIER/Peppered API:
# Synchronise everything
python manage.py sync_viernulvier
# Only one model type
python manage.py sync_viernulvier --only events
# Incremental - only records updated after a given date
python manage.py sync_viernulvier --updated-after 2024-06-01T00:00:00ZImport historical pre-API data from bundled CSV files:
python manage.py import_legacy_csv
python manage.py import_legacy_csv --dry-run # preview without writingAvailable sync steps (in dependency order):
uitdatabank_types -> genres -> tags -> locations -> spaces -> halls -> media_galleries -> media_items -> prices -> price_ranks -> productions -> events -> event_prices
Full documentation: Scraper wiki page.
Production runs on a self-hosted GitHub Actions runner with Docker. A push to main triggers the deploy workflow automatically.
# 1. Install Docker (https://docs.docker.com/engine/install/)
# 2. Register a GitHub Actions self-hosted runner (Settings -> Actions -> Runners)
# 3. Add all variables from infrastructure/.env.example as GitHub repository secrets
# 4. Push to main (or trigger the workflow manually) for the first deployment
# 5. Request the TLS certificate
bash infrastructure/certbot/setup-certbot.sh your-domain.example admin@example.comdocker compose -f infrastructure/docker-compose.prod.yml ps
curl https://your-domain.example/health # expected: okFull instructions: Setup and Deployment wiki.
| Page | Description |
|---|---|
| Architecture | System and deployment architecture |
| API Overview | Authentication, permissions, throttling, endpoints |
| Backend Folder Structure | Django app structure and naming conventions |
| Backend Requirements Structure | Dependency management per environment |
| Frontend | React app overview, routing, theming, scripts |
| Frontend Components | Component library and reusable patterns |
| Frontend folder structure | Frontend directory structure |
| Scraper | Sync command, filters, scraper architecture |
| Setup and Deployment | Installation and deployment guide |
| Testing, Linting and Formatting | Test strategy, linting and CI behaviour |
| EER diagram | Entity-relationship diagram of the domain model |
Made by students of Ghent University as part of the Software Engineering Lab 2 course · SELab-2
Distributed under the terms of the LICENSE file in the root of this project.