Selected Work

TLV After Dark

An event photobooth with no booth. Guests scan a QR, use their own phone as the camera, and get a branded photo strip back in three taps.

TLV After Dark preview
Taps for a guest
3
App download
None
Image storage
Cloudflare R2
Runs with no cloud setup
Yes

Problem

A photobooth at an event is a rented enclosure, a camera, a printer and a queue. It is expensive, it occupies floor space, and the guest walks away with a strip they then have to photograph to post anywhere.

Approach

Remove the booth. A guest scans a QR at the booth station, the site opens in their own phone's browser, and their phone, mounted on a ring light, is the camera.

Scan QR, start, pick 1 or 4 photos, countdown, save, done. Three taps for a guest, and the station resets itself for the next person. No app download and no sign-up. A copy lands automatically in the public event album.

Architecture decisions

Image bytes live in Cloudflare R2, not Supabase Storage. This is the decision the project turns on. Supabase's free tier caps egress at 5 GB per month, and the entire point of the album is that guests share it widely. A popular album would exhaust that cap and go dark partway through the event, which is precisely when it matters. R2 offers 10 GB free with no egress fees, so bandwidth cannot throttle the album mid-event. Google Photos was ruled out separately.

Supabase still does what it is good at: Postgres, row-level security, and email/password admin login. The split is deliberate rather than a preference for one vendor.

sharp handles thumbnails and re-encoding server-side, which also strips EXIF, because guests' photos should not carry location metadata into a public album.

The app runs with no cloud setup at all. With no Supabase or R2 credentials present it falls back to a built-in event and placeholder templates, so the entire guest flow (camera, countdown, compositing, save) is testable immediately. Only the album is inert. Configuration is never a prerequisite for development.

Built with

  • Next.js 16
  • · Supabase
  • · Cloudflare R2
  • · sharp