A set of small, decoupled, single-purpose demoparty management tools.
Originally built for the Evoke demoparty to handle the operational "side quests" that competition-focused systems like Granola intentionally leave out. All tools are open-source, run as Docker containers, and are built with Go and React.
- kasseapparat: Lightweight POS and guestlist manager for the entrance desk.
- tidsapparat: Timetable manager to adjust running orders and serve structured schedule data.
- funkapparat: Minimal news hub for quick text announcements.
- billedapparat: Big-screen display system for the main hall (rotates slides, pulls live schedules from tidsapparat and news from funkapparat).
- protokolapparat: The shared glue. It defines the protocol and data structures used to exchange news and events between tidsapparat, funkapparat, and billedapparat via Redis.
The Apparat suite relies on decoupling. There is no central monolithic database. Instead, the tools communicate asynchronously via Redis. tidsapparat and funkapparat publish their updates, and billedapparat subscribes to them.
To keep the services lean, there is no built-in user management. Authentication and routing should be handled externally via a reverse proxy (like Traefik) and an OIDC provider.
graph TD
User([Party Organizer]) --> Traefik
subgraph Infrastructure
Traefik[Reverse Proxy<br>Traefik + OIDC]
Redis[(Redis)]
end
subgraph The Apparat Suite
Traefik -->|Admin UI| K[kasseapparat]
Traefik -->|Admin UI| T[tidsapparat]
Traefik -->|Admin UI| F[funkapparat]
Traefik -->|Display UI| B[billedapparat]
T -.->|Publishes events via protokolapparat| Redis
F -.->|Publishes news via protokolapparat| Redis
Redis -.->|Subscribes| B
end
The easiest way to run the full suite locally is using docker compose. This structural example includes a basic Traefik proxy for routing and a Redis instance for internal communication.
Note: In a production environment, you should attach an OIDC middleware to Traefik to secure the admin interfaces.
# docker-compose.yml
services:
traefik:
image: traefik:v3.0
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
redis:
image: redis:7-alpine
expose:
- "6379"
kasseapparat:
image: ghcr.io/potibm/kasseapparat:latest
labels:
- "traefik.http.routers.kasse.rule=Host(`kasse.apparat.localhost`)"
tidsapparat:
image: ghcr.io/potibm/tidsapparat:latest
environment:
- REDIS_URL=redis:6379
labels:
- "traefik.http.routers.tids.rule=Host(`tids.apparat.localhost`)"
funkapparat:
image: ghcr.io/potibm/funkapparat:latest
environment:
- REDIS_URL=redis:6379
labels:
- "traefik.http.routers.funk.rule=Host(`funk.apparat.localhost`)"
billedapparat:
image: ghcr.io/potibm/billedapparat:latest
environment:
- REDIS_URL=redis:6379
labels:
- "traefik.http.routers.billed.rule=Host(`billed.apparat.localhost`)"Run docker compose up -d and access the tools via http://*.apparat.localhost.
The docker-compose.yml above outlines the general architecture and routing. However, to make the tools fully functional, you need to provide their specific configuration files (e.g., to set the Redis URL, CORS headers, or database paths).
Each tool is configured via its own config.yaml or environment variables. Please refer to the documentation in the individual repositories for detailed setup instructions and full configuration examples.