No description
  • Go 32.9%
  • HTML 24.1%
  • TypeScript 21.5%
  • JavaScript 11.8%
  • CSS 8.2%
  • Other 1.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Sebastian Leheis d1c7bc4453
Add a real calendar date per day; make "Als Nächstes" date-aware and global
The previous fix scoped "Als Nächstes" strictly to the selected day tab,
but that meant switching to a day whose bands had already passed (by
wall-clock time) just showed an empty box, even though the person's
actual next band might be on a following day -- there was no way to know
that without a real date, since "Tag 1".."Tag 5" were just labels.

Each day in festival.ini now requires a `date = YYYY-MM-DD` key (validated
at startup like the other fields). The backend exposes it via /api/config,
and computeUpcoming() now builds a real Date per band (day's date + band's
time, with times before 06:00 correctly rolling onto the next real
calendar date) and returns the next N signed-up bands across the whole
festival by actual chronological order -- completely independent of which
day tab happens to be selected.

Verified with realistic past/today/tomorrow scenarios: past bands are
excluded, today's remaining bands and tomorrow's bands are both picked up
in the right order, and the midnight-rollover math resolves to the
correct following calendar date.

No dedicated security review for this one: it's a config schema addition
plus client-side date arithmetic, no new user input, no new WS message
type, no new trust boundary.
2026-08-11 00:47:58 +02:00
.claude Initial Commit 2026-08-10 22:53:18 +02:00
backend Add a real calendar date per day; make "Als Nächstes" date-aware and global 2026-08-11 00:47:58 +02:00
config Add a real calendar date per day; make "Als Nächstes" date-aware and global 2026-08-11 00:47:58 +02:00
frontend Add a real calendar date per day; make "Als Nächstes" date-aware and global 2026-08-11 00:47:58 +02:00
migration Add Firebase-to-Postgres signup migration script 2026-08-10 23:33:37 +02:00
.dockerignore Initial Commit 2026-08-10 22:53:18 +02:00
.env.example Fix crash on empty signups state; add config validation and DEBUG dump logging 2026-08-10 23:13:28 +02:00
.gitignore Track only a config template, not the real festival.ini 2026-08-10 23:58:11 +02:00
docker-compose.yml Fix crash on empty signups state; add config validation and DEBUG dump logging 2026-08-10 23:13:28 +02:00
Dockerfile Initial Commit 2026-08-10 22:53:18 +02:00
README.md Add a real calendar date per day; make "Als Nächstes" date-aware and global 2026-08-11 00:47:58 +02:00
sboa26-signup-firebase.html Initial Commit 2026-08-10 22:53:18 +02:00

Festival Track - Live Signup Board

Festival Track is a live festival signup board that replaces the legacy Firebase-based HTML file. It allows festival participants to sign up for performances in real time, with live synchronization across all connected browsers—no page reload necessary.

Prerequisites

  • Docker (version 20.10+)
  • Docker Compose (version 2.0+)
  • A text editor to configure config/festival.ini

Quick Start

  1. Prepare environment variables:

    cp .env.example .env
    

    Edit .env and set a strong password for POSTGRES_PASSWORD. Never commit this file to version control.

  2. Configure the festival lineup:

    cp config/festival.ini.example config/festival.ini
    

    config/festival.ini is gitignored (just like .env) so your real lineup and participant names never end up in version control -- only the generic .example template is tracked. Edit config/festival.ini to set:

    • Event metadata ([event] section): title, tagline, description, footer
    • Participant names ([participants] section): comma-separated list of names
    • Days and stages: [days] section lists the day order; one [<DayName>] section per day with stages=... line; one [<DayName>.<StageName>] section per stage with Band Name = HH:MM entries
  3. Start the services:

    docker compose up -d --build
    

    This builds the Docker image and starts both the PostgreSQL database and the web app.

  4. Access the app: Open your browser to http://localhost:8080 (or the port you set in .env via APP_PORT).

Configuration

Environment Variables (.env)

  • POSTGRES_USER: Database user (default: festival)
  • POSTGRES_PASSWORD: Required. Choose a strong, unique password.
  • POSTGRES_DB: Database name (default: festival)
  • APP_PORT: Host port for the web app (default: 8080)
  • DEBUG: Set to true to dump the fully parsed config (all days, stages, bands, and participants, each with the generated id) to docker compose logs app at startup. Default: off. Useful for verifying festival.ini was parsed as expected.

Config validation

At startup the app validates festival.ini and refuses to start (with a list of every problem found) if it detects: no participants, duplicate participant names, no days, a day with no stages, a stage with no bands, a band with an empty name/time, a band time that isn't HH:MM, a day with a missing/malformed date, or two bands whose generated ids collide. A sparse lineup (e.g. a day with only one stage) is valid and will not be rejected.

INI Configuration (config/festival.ini)

Example structure:

[event]
title = Festival Name
eyebrow = Location / Year
subtitle = Description for participants
footer = Footer text

[participants]
names = Alice, Bob, Charlie, Diana

[days]
order = Day 1, Day 2, Day 3

[Day 1]
date = 2026-08-13
stages = Main Stage, Side Stage

[Day 1.Main Stage]
Band A = 14:00
Band B = 15:30
Band C = 17:00

[Day 1.Side Stage]
Band X = 14:30
Band Y = 16:00

Every day section needs a date = YYYY-MM-DD -- the real calendar date that day starts on. This is what lets the "Als Nächstes" section on the page work out what's genuinely coming up next (across the whole event, not just the currently selected day tab), instead of guessing from the system clock and whichever day happens to be selected. A band timed before 06:00 (e.g. 01:00) is treated as the tail end of that day's program, past midnight into the following real date -- you don't need to adjust anything for that, just set each day's date to the date its program actually starts.

Important: Configuration changes require restarting the app service:

docker compose restart app

Architecture

  • Frontend: TypeScript single-page application (SPA) built with esbuild. Assets are statically embedded in the Go binary.
  • Backend: Go 1.25 REST + WebSocket server that handles:
    • Config queries (/api/config)
    • Health checks (/healthz)
    • Live WebSocket broadcasts for signup changes (/ws)
    • Static file serving (frontend assets)
  • Database: PostgreSQL 16 running in a separate container with persistent data volume.
  • Networking: Compose-internal network; database is not exposed to the host. Only the web app port (APP_PORT) is published.

Deployment Notes

TLS/HTTPS

This deployment runs plain HTTP. For production or public-facing use, deploy behind a reverse proxy (Caddy, nginx, Traefik) to provide HTTPS termination. Example with Caddy:

caddy reverse-proxy --from :443 --to localhost:8080

Stopping and Cleanup

Stop services without removing data:

docker compose down

Remove everything including the database volume:

docker compose down -v

Logs

View app logs:

docker compose logs -f app

View database logs:

docker compose logs -f db

Development

To rebuild the image after code changes:

docker compose up -d --build

To run without daemon mode (see logs in real time):

docker compose up --build

Press Ctrl+C to stop.