A unified monorepo for local development of the Generic Publication Platform (GPP) services.
This monorepo consolidates all GPP microservices for easier local development and testing:
| Service | Description | Tech Stack | Port |
|---|---|---|---|
| gpp-app (ODPC) | Publication Composer - UI for creating publications | .NET 8 + Vue 3 | 62230 |
| publicatiebank (ODRC) | Publication Registry - stores publications | Django + Celery | 8002 |
| woo-hoo | LLM Metadata Extraction - AI-powered document analysis | FastAPI + Python | 8003 |
| openzaak | Document Management System | Django | 8001 |
| nginx | Unified reverse proxy | nginx | 8080 |
- Docker & Docker Compose
- just command runner (
brew install just) - Node.js 20+ (for frontend development)
- .NET 8 SDK (for backend development, optional)
- uv (for Python/woo-hoo development)
# 1. Create environment file
cp .env.example .env
# 2. Add your OpenRouter API key to .env (required for woo-hoo)
# Get one at: https://openrouter.ai
# 3. Build and start everything
just quickstart
# Or step by step:
just build
just up# Start all services
just up
# Start only dependencies (DB, Redis, OpenZaak, Publicatiebank)
just up-deps
# Check health of all services
just health
# View logs
just logs
# Stop everything
just downββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β METADATA GENERATION FLOW β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββ βββββββββββββββ βββββββββββββββββ ββββββββββββββββ
β Browser βββββΆβ gpp-app βββββΆβ publicatiebankβββββΆβ OpenZaak β
β (Vue.js) β β (.NET 8) β β (Django) β β (DRC API) β
βββββββββββββββ βββββββββββββββ βββββββββββββββββ ββββββββββββββββ
β β β β
β β β β
β βΌ β β
β βββββββββββββββ β β
β β woo-hoo β β β
β β (FastAPI) β β β
β β LLM/OCR β β β
β βββββββββββββββ β β
β β β
β βΌ β
β βββββββββββββββββ β
β β celery worker βββββββββββββββ
β β (strip_pdf) β
β βββββββββββββββββ
STEP BY STEP:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. DOCUMENT UPLOAD (User β gpp-app β publicatiebank β OpenZaak)
Browser POST /api/v2/documenten βββΆ gpp-app βββΆ publicatiebank βββΆ OpenZaak
2. STRIP_PDF TASK (celery β OpenZaak)
celery downloads from OpenZaak βββΆ strips metadata βββΆ uploads NEW to OpenZaak
3. METADATA GENERATION (gpp-app β publicatiebank β OpenZaak β woo-hoo)
gpp-app GET /api/v2/documenten/{uuid}/download βββΆ publicatiebank
publicatiebank proxies to OpenZaak βββΆ returns PDF
gpp-app POST /api/v1/metadata/generate-from-file βββΆ woo-hoo
ββββββββββββββββββββ
β Browser/User β
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β nginx (8080) β
β Reverse Proxy β
ββββββββββ¬ββββββββββ
β
ββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββ
β β β
βΌ βΌ βΌ
ββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
β gpp-app (ODPC) β β publicatiebank β β woo-hoo β
β .NET + Vue βββββββββββΊβ (ODRC) Django β β FastAPI β
β Port 62230 β β Port 8002 β β Port 8003 β
ββββββββββ¬ββββββββββ ββββββββββ¬ββββββββββ ββββββββββββββββββββ
β β β
β β β
β βΌ β
β ββββββββββββββββββββ β
β β OpenZaak β β
β β Port 8001 β β
β ββββββββββ¬ββββββββββ β
β β β
βββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββ
β
ββββββββββββββ΄βββββββββββββ
βΌ βΌ
ββββββββββββββββββββ ββββββββββββββββββββ
β PostgreSQL β β Redis β
β Port 5432 β β Port 6379 β
ββββββββββββββββββββ ββββββββββββββββββββ
| Service | URL | Credentials |
|---|---|---|
| Main Application | http://localhost:8080 | Auto-login (dev mode) |
| GPP-App Direct | http://localhost:62230 | Auto-login (dev mode) |
| Publicatiebank Admin | http://localhost:8002/admin | admin / admin |
| OpenZaak Admin | http://localhost:8001/admin | admin / admin |
| woo-hoo API Docs | http://localhost:8003/docs | - |
| woo-hoo Health | http://localhost:8003/health | - |
just upAll services run in Docker containers. Best for integration testing and simulating production.
# Start dependencies in Docker
just up-deps
# Run Vue dev server with hot reload (in a new terminal)
just dev-frontendAccess the Vue app at http://localhost:5173 - it proxies API calls to the Docker backend.
# Start dependencies
just up-deps
# Run woo-hoo locally with hot reload
just dev-woo-hoo# Start only infrastructure
just up-infra
# Run each service locally (in separate terminals):
just dev-backend # .NET backend
just dev-frontend # Vue frontend
just dev-woo-hoo # woo-hooIn production, GPP uses OIDC (OpenID Connect) for authentication, which provides:
- User identity and roles from the identity provider
- User groups (OrganisationUnits) for authorization
For local development, OIDC is bypassed:
- The
OIDC_AUTHORITYenvironment variable is intentionally NOT set - GPP-app automatically logs in as a local developer with admin rights
- Test user groups are seeded via fixtures
If you need to test OIDC integration, you can configure it in .env:
OIDC_AUTHORITY=https://your-idp.example.com
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secretwoo-hoo uses LLMs to extract metadata from Dutch government documents. It requires an OpenRouter API key.
- Get an API key from OpenRouter
- Add it to your
.env:OPENROUTER_API_KEY=sk-or-v1-...
By default, woo-hoo uses EU-based Mistral models for data sovereignty:
mistralai/mistral-large-2512(default)mistralai/mistral-medium-3.1mistralai/mistral-small-3.2-24b-instruct-2506
Change the model in .env:
WOO_HOO_MODEL=mistralai/mistral-large-2512# Check health
curl http://localhost:8003/health
# View API docs
open http://localhost:8003/docs
# List available models
curl http://localhost:8003/api/v1/metadata/models
# Generate metadata from a file
curl -X POST http://localhost:8003/api/v1/metadata/generate-from-file \
-F "file=@document.pdf"Run just or just --list to see all available commands:
# Main commands
just up # Start all services
just down # Stop all services
just restart # Restart all services
just logs # View logs
# Selective startup
just up-infra # Start only postgres & redis
just up-deps # Start dependencies (+ openzaak, publicatiebank)
just up-woo-hoo # Start woo-hoo only
# Development
just dev-frontend # Vue dev server (hot reload)
just dev-backend # .NET backend (local)
just dev-woo-hoo # woo-hoo (hot reload)
# Testing
just test # Run all tests
just test-gpp-app # Run gpp-app tests
just test-woo-hoo # Run woo-hoo tests
# Code quality
just lint # Lint all code
just format # Format all code
# Database
just db-shell # Open psql
just db-odpc # Connect to ODPC database
just db-publicatiebank # Connect to publicatiebank database
# Utilities
just health # Check service health
just ps # Show running containers
just clean # Clean up Docker resourcesgppmono/
βββ services/
β βββ gpp-app/ # Publication Composer (.NET + Vue)
β β βββ ODPC.Server/ # .NET backend
β β βββ ODPC.Test/ # Backend tests
β β βββ odpc.client/ # Vue frontend
β βββ publicatiebank/ # Publication Registry (Django)
β β βββ src/woo_publications/
β βββ woo-hoo/ # LLM Metadata Service (FastAPI)
β βββ src/woo_hoo/
βββ docker/
β βββ nginx/ # Reverse proxy config
β βββ postgres/init/ # Database initialization
β βββ fixtures/ # Seed data for local dev
βββ docker-compose.yml # Main compose file
βββ docker-compose.override.yml # Local dev overrides
βββ justfile # Command runner recipes
βββ .env.example # Environment template
βββ CLAUDE.md # AI assistant instructions
βββ README.md # This file
# Check what's running
just ps
# View logs for specific service
just logs gpp-app
just logs publicatiebank
# Rebuild images
just build
# Nuclear option: clean slate
just down-v
just up# Reset databases (destroys all data!)
just down-v
just up
# Check database health
just db-shell
\l # List databases
\c ODPC # Connect to ODPC
\dt # List tables- Check if
OPENROUTER_API_KEYis set in.env - Check woo-hoo logs:
just logs woo-hoo - Test health:
curl http://localhost:8003/health
If ports are already in use, check for running containers:
docker ps -a
# Kill conflicting containers or change ports in docker-compose.override.yml- Create a feature branch
- Make your changes
- Run tests:
just test - Run linting:
just lint - Submit a pull request
See individual service directories for license information.