Real-time web application for managing gaming station reservations at LAN party events.
If you are running NixOS, make sure flakes are enabled.
On other operating systems/distributions, install Nix using the Determinate Systems Nix installer:
curl -fsSL https://install.determinate.systems/nix | sh -s -- installConsider installing direnv to automatically install the project's nix shell when you cd into the folder. If you have direnv installed, simply run direnv allow and follow the instructions below.
If you don't use direnv, activate the nix shell using nix shell --impure.
To start lanparty-seating:
- Start PostgreSQL (keep running in a dedicated terminal):
devenv up - Install dependencies:
mix deps.get - Create and migrate database:
mix ecto.create && mix ecto.migrate - Seed database:
mix ecto.reset - Install Node.js dependencies:
cd assets && yarn install --dev && cd .. - Generate HTTPS certificate:
mix gen_dev_cert - Deploy assets:
mix assets.deploy - Start Phoenix:
mix phx.server
Now you can visit localhost:4000 from your browser.
For WebBluetooth scanner provisioning, use HTTPS at localhost:4001.
After running mix ecto.reset, the following test data is created from priv/repo/seeds.exs:
Admin User:
- Email:
admin@otakuthon.com - Password:
change-me-on-first-login - Name:
Admin
Admin Badge (for badge-based admin access):
- Badge Number:
ADMIN-001
Test Badge (for testing reservations):
- Badge Number:
1
Sample Tournaments:
- 3 tournaments with stations 1-10 locked for the first one
The seed configuration (grid size, timing offset) can be adjusted at the top of priv/repo/seeds.exs.
Production seeds (priv/repo/seeds_prod.exs) create only the minimal required data:
- Default settings
- 70 stations (10x7 grid)
- Admin user (
admin@otakuthon.com/change-me-on-first-login)
No test badges or sample tournaments are created.
Copy .env.sample to .env for local development:
cp .env.sample .envThe .envrc file automatically loads .env when using direnv. Edit .env to configure optional integrations like OpenTelemetry tracing.
Note: Database configuration for development is handled automatically by devenv up - no DATABASE_URL needed locally.
mix phx.server # Start dev server
mix phx.routes # List all routes
mix ecto.reset # Drop, create, migrate, seed DB
iex -S mix phx.server # Start with IEx REPLmix ecto.create # Create database
mix ecto.migrate # Run migrations
mix ecto.rollback # Rollback last migration
mix ecto.gen.migration name # Generate new migrationmix format # Format code
mix test # Run testsThere are multiple ways to debug elixir code as shown in the Debugging section of the elixir manual.
In general, you can use the VSCode editor with the recommended extensions for the project to debug in the editor using ElixirLS.
You can also launch the program with the elixir repl using iex -S mix phx.server and insert "breakpoints" into the code using IEx.pry() in order to make the app break into the repl at that point, allowing you to introspect its state.
Live Dashboard: Visit http://localhost:4000/dashboard (dev only) to view processes, metrics, and request logs.
Database:
DATABASE_URL- PostgreSQL connection string
Web:
PHX_HOST- Public hostnamePORT- HTTP port (default: 4000)SECRET_KEY_BASE- Phoenix secret (required)
Timezone:
TZ=America/Toronto- Application timezoneSTORAGE_DIR=/tmp/tzdata- Timezone data cache
OTP:
RELEASE_COOKIE- Erlang distribution cookie (for clustering)
You can configure the app to automatically upload its grafana dashboards to grafana and annotate its lifecycle events in grafana by setting the following environment variables:
GRAFANA_ENABLE- Any value such as1enables grafana supportGRAFANA_HOST- URL to the grafana instanceGRAFANA_AUTH_TOKEN- Grafana auth tokenGRAFANA_DATASOURCE_ID- Grafana datasource id for the prometheus instance
Configure OpenTelemetry tracing via .env (see .env.sample):
OTEL_EXPORTER_OTLP_ENDPOINT- OTLP endpoint (e.g.,https://api.honeycomb.io)OTEL_EXPORTER_OTLP_HEADERS- Auth headers (e.g.,x-honeycomb-team=YOUR_TOKEN)OTEL_SERVICE_NAME- Service name for traces
nix build .#container # Build container image
nix run .#container.copyToDockerDaemon # Load into Docker
docker run -p 4000:4000 lanparty-seatingDATABASE_URL=postgresql://user:pass@host:5432/lanpartyseating_prod
SECRET_KEY_BASE=$(mix phx.gen.secret)
PHX_HOST=example.com
PORT=4000
TZ=America/Torontobin/lanpartyseating eval "Lanpartyseating.Release.migrate()"
bin/lanpartyseating eval "Lanpartyseating.Release.seed()"mix assets.deploy # Build and digest assets
mix release # Build OTP releaseFor exit sign-out stations, the system supports external ESP32-based badge scanners that allow attendees to cancel their reservations by scanning their badge at exit points.
Hardware Firmware: otakulan/lanparty-seating-badge-reader
- Configure WiFi credentials in Settings > Scanners (stored encrypted, shared by all scanners)
- Create a scanner entry (generates a unique API token)
- Provision the ESP32 via WebBluetooth (sends WiFi + API credentials to device)
Scanners call POST /api/v1/reservations/cancel with bearer token authentication:
curl -X POST https://your-server/api/v1/reservations/cancel \
-H "Authorization: Bearer lpss_..." \
-H "Content-Type: application/json" \
-d '{"badge_uid": "ABC123"}'WebBluetooth provisioning requires a secure context. In development:
- Generate HTTPS certificate:
mix gen_dev_cert - Use HTTPS on port 4001: https://localhost:4001
- Or access via
localhoston HTTP (exempt from HTTPS requirement)
The certificate is generated using OpenSSL (not mix phx.gen.cert) for
compatibility with Chrome and OTP 28.
See the hardware repository for firmware setup, hardware requirements, and LED status indicators.