Scanner setup

Turn any phone or laptop with a camera into a gate scanner. No app install — it runs in the browser.

1. Create a scanner account

In Settings → Scanners, add a scanner for each gate (e.g. “North 4”, “VIP”). Each gets a short access code so volunteers can sign in on a shared device without your dashboard credentials.

2. Open the scanner

Go to Dashboard → Scan, choose the event and gate, and grant camera permission. The scanner uses html5-qrcode to read tickets continuously.

Camera access requires HTTPS. Your Netlify URL is HTTPS by default, so this works out of the box in production.

3. Scan

Each scan returns one of five verdicts:

  • VALID — first valid scan; the ticket is checked in.
  • ALREADY_USED — the ticket was already checked in.
  • WRONG_EVENT — a ticket for a different event/org.
  • EXPIRED — the signed token is past its expiry.
  • INVALID — bad signature or cancelled ticket.

Why duplicates are impossible

Check-in is a single atomic database update that flips the ticket from VALID to USED only if it is still VALID. If two devices scan the same code at once, exactly one wins; the other gets ALREADY_USED.

ts
// atomic compare-and-set
const updated = await prisma.ticket.updateMany({
  where: { id: ticketId, status: "VALID" },
  data:  { status: "USED", checkedInAt: new Date() },
});
// updated.count === 1  -> this device checked them in
// updated.count === 0  -> someone already did