~/work/pinball-asylum

pinball asylum

A membership and door-entry system for a volunteer-run nonprofit pinball venue: members buy a pass, pull up a signed QR code, and get scanned in at the door.

Visit pinballasylum.netlify.app

client

The Pinball Asylum

role

Solo build, from scratch

launched

Public beta, 2026

status

Live

next.jstypescripttailwindprismaneon postgresnextauthsquareresendnetlifyplaywright
pinballasylum.netlify.app
The Pinball Asylum homepage hero over a pinball playfield, with Plan Your Visit and Member Sign In buttons.

// the problem

The Pinball Asylum is a 501(c)(3) run by volunteers, not a staffed business. They needed a way to sell passes, verify members at the door, and let non-technical board members run all of it without touching a server or a database. Paper passes and manual check-in do not hold up at a busy venue, and there was no online way to pay or to prove that a pass was real.

pinballasylum.netlify.app/visit
The Pinball Asylum Visit page explaining what to expect on a first visit to the venue.
the in-person venue that needs digital passes and door check-in

// what I built

I built the whole thing solo: a public marketing site, member accounts, the pass and QR system, a door-scanning tool for staff, and a role-gated admin portal. Members register, get a pass, and see a QR code that changes every day. Staff open a scanner page and validate a member at the door in one step. Board members connect Square, issue passes, edit site copy, and manage the machine list from the browser. Payments run through Square for both online and in-person sales, and the machine catalog stays current by syncing from Pinside and OPDB on a schedule.

pinballasylum.netlify.app/account
A member account page showing an active day pass and a daily QR code to scan at the door.
an active day pass and a QR code that refreshes daily

// technical highlights

  • Passes render as HMAC-SHA256 signed QR codes bound to a single calendar day and a single-use nonce. The scan endpoint verifies the signature, checks the stored nonce, and marks it used, so a screenshot of yesterday's code (or a second scan of today's) is rejected.
  • Square integration covers online hosted checkout plus a webhook (payment.created and payment.updated) with signature verification and an idempotency key, so a retried webhook delivery cannot issue a pass twice.
  • The webhook finds or creates a member account by buyer email and grants the matching pass by line item, so a walk-in who pays gets an account and a pass automatically.
  • Square credentials are entered from the admin and stored AES-256-GCM encrypted at rest, so board members connect payments with no server access.
  • New accounts are passwordless and receive a single-use, expiring set-password link (the same token flow also powers Forgot Password), so no plaintext temporary passwords are ever emailed.
  • The machine catalog syncs from Pinside through a scheduled GitHub Actions scraper (Playwright), is stored as snapshots, and is reconciled (adds and retires) with a review step, then linked to OPDB for clean art and metadata. The auto-sync interval is configurable from the admin.
  • Access is role-based (member, staff, board, admin, webmaster), enforced in middleware, with an audit log for sensitive actions and rate limiting on login, registration, and the scan endpoint.
  • A Playwright end-to-end suite covers the core journeys: public pages, auth, pass issuance, admin gating, and the full QR scan round-trip.
pinballasylum.netlify.app/admin
The staff QR Verify page with a camera scan panel and the admin portal navigation.
door scan in one step, inside the role-gated admin
pinballasylum.netlify.app/admin
The Games admin showing machines synced from Pinside and linked to OPDB, with the auto-sync cadence control.
machines synced from Pinside, linked to OPDB, with a configurable cadence

// the impact

server-verified
Door QR codes are signed, date-bound, and single-use per day, checked and consumed at scan.
no server access
Board members connect Square and issue passes from the browser, with secrets encrypted at rest.
end-to-end tested
A Playwright suite covers auth, pass issuance, admin gating, and the QR scan flow.

In public beta. Cash and in-person passes and door scanning work today. Online card payments turn on when the board connects their own Square account, which they can do from the admin without any developer help.

pinballasylum.netlify.app/admin
The admin Payments page with a step-by-step guide for a board member to connect Square.
a board member connects payments themselves, secrets encrypted

Have a similar problem?

Let's talk about what to build.

Start a project →