Guild Kiosk Architecture Decision

Problem

The kiosk app (BBS terminal UI for NFC check-in, weather, events, leaderboards) lives inside the Guild monolith as a Next.js route group at (kiosk)/. As we add more ambient features (Spotify now playing, community feeds, etc.), there’s a question of whether it should be extracted into a separate service.

Approach

Decision: keep the kiosk in the monolith.

The Raspberry Pi runs a headless browser pointing at a URL. It doesn’t know or care what serves the page. This eliminates deployment divergence as a reason to split — the kiosk deploys whenever the main app deploys, same URL, same infra.

Why not split

  • The coupling is thin but real. The kiosk’s core job is check-in, which calls processCheckIn via server actions with direct DB access. Extracting would mean switching to HTTP calls to /api/check-in — possible, but adds latency and failure modes for no benefit.
  • Route groups already isolate it. (kiosk)/ has its own layout, styles, and component tree. No client components leak into the frontend bundle. This is the architectural boundary Next.js gives us — it’s working.
  • New features are lightweight. Spotify is REST calls, weather and events are already integrated. None of these add heavy dependencies that would bloat the main app’s build.
  • We’re still iterating fast. The BBS design just landed (~21 commits). Premature extraction would slow iteration by adding an API contract between two apps.

When to revisit

  • The kiosk pulls in heavy client-side deps (canvas libs, websocket frameworks, animation engines) that noticeably increase main app bundle size or build time
  • The kiosk needs a fundamentally different rendering strategy (e.g., real-time streaming that conflicts with the main app’s caching)
  • The shared code surface shrinks to just API calls — meaning the kiosk is a pure display client with no benefit from being in the monolith

Migration path (when the time comes)

Extraction cost is low because the coupling is already minimal:

  1. Stand up a separate Next.js app for the kiosk
  2. Replace server actions with HTTP calls to existing /api/check-in
  3. Call external APIs (Spotify, weather, events) directly
  4. Copy over the few shared UI components (GlitchText, Progress)
  5. Point the Pi’s browser at the new URL

Open questions

  • Does adding Spotify surface any bundle size concerns in practice?