Work ohsnap
desktop

OhSnap!

A Windows 11 photo booth that snaps on anything — map any button by pressing it once, brand every pixel, install in one click.

OhSnap! is an event photo booth for Windows 11: full-screen, cursor hidden, running the operator's branding rather than ours. Any input can be the shutter — a keyboard, a gamepad, a MIDI pad, a foot pedal, a barcode-style HID button or an Arduino on a serial port — and binding one takes a single press in learn mode rather than a configuration file. Backgrounds swap live between a camera feed, a still, a looping video or a flat colour; logo, frame, watermark and text are positioned in percentages so what is on the wall is what lands in the photo at full camera resolution. Every admin surface is a key chord, so a guest never sees a menu. It ships as a one-click unsigned NSIS installer built in CI, with a companion site — one Go binary, standard library only, assets embedded — that serves the installer behind a password, documents every Windows warning the operator will meet on the way, and publishes the hash to check the file against.

Versionv0.4.0 Last updateSep 16, 2026 PrimaryJavaScript
  • JavaScript
  • Electron 33
  • Go
  • serialport
  • electron-builder
  • NSIS
  • GitHub Actions
  • nginx
  • systemd
OhSnap! — A Windows 11 photo booth that snaps on anything — map any button by pressing it once, brand every pixel, install in one click.

OhSnap! is a photo booth for events, built for a Windows 11 machine that has to survive a night of strangers pressing things. It boots full-screen into an idle loop with the operator's own logo and prompt, waits for whatever has been mapped as the shutter, counts down with a tick and a flash, composites the shot at full camera resolution and offers keep, retake or print before returning to idle for the next guest.

Press anything

The input layer is the part most booths get wrong. OhSnap! takes keyboards, gamepads, MIDI pads, serial devices and HID burst typers — the button boxes that "type" a word and press Enter — and binds any of them the same way: open the inputs panel, press Bind next press, then press the thing. Every action can carry any number of bindings, a binding can be told to require a half-second hold so a knock can't fire the camera, and a keyboard binding can go global so the shutter works even when the window isn't focused. A running list of every press the app hears — bound or not — makes "the button does nothing" a thirty-second diagnosis at a venue rather than a phone call.

Their brand, not ours

Idle screen, subject box, frame, watermark and text are all set as percentages of the screen, which is what makes the preview honest: the saved photo uses the same numbers as the wall. Backgrounds accept a live camera, a still, a looping video or a flat colour, swapped mid-event as soon as nobody is mid-snap, with blur and dim to push a live feed back behind the guest. A whole look can be exported as a preset and loaded on the next machine.

Nothing on screen the guest can break

There is no menu on the stage. The admin hub, cameras, backgrounds, inputs, branding, output, gallery and diagnostics are each a key chord, quitting asks first, and Alt+F4 does nothing in kiosk mode. The operator guide is one printable page of chords and recovery steps, because at a venue the fix has to be findable by someone who isn't the person who built it.

Offline at the venue, honest about the installer

The app works with no network — photos land in a folder the operator chose and can find, with no account, no cloud and no product key. The installer is deliberately unsigned, so rather than pretend otherwise the site documents the entire "unknown publisher" path: the browser's download warning in Edge, Chrome and Firefox, the SmartScreen box, what Defender may do, and the SHA-256 to check the file against. A code-signing certificate is a real cost; explaining four screenshots is not.

The release path

A single command bumps the version, tags it, builds the Windows installer in CI, publishes it and redeploys the site — which is a Go binary with its templates and assets embedded, behind nginx and systemd, serving the download behind a password with the version, date, size and hash rendered from the release itself. The changelog on the site is the changelog in the repository.

Straight from the source

The project's own README.

Rendered in place — every link, image, and code block carried over from the repo. The page below is what a contributor would see opening the project for the first time.

OhSnap!

A Windows 11 photo-booth kiosk for Peak Technologies, and the website that serves its installer: https://ohsnap.gamingworld.uk.

  • app/ — the Electron kiosk (main / preload / renderer, vanilla ES modules).
  • site/ — the website: one Go binary, stdlib only, templates and assets embedded.
  • scripts/ — the release pipeline (just ship).
  • deploy/ — the canonical systemd unit and nginx vhost for this box.
  • docs/PLAN.md (the design), CHECKLIST.md (the tick-list), handoff.md (start here).
just              # list every task
just dev          # website on :8083, templates reload
just check        # gofmt, vet, test, node --check
just deploy       # build + install + restart the live site
just push "msg"   # commit, push, deploy, verify — one command
just ship         # release the app: bump, tag, CI build, publish, deploy

Mail for the project: [email protected].

Gallery

The full set.

Build something like this

Want a tool like this for your shop?

We've shipped this kind of thing before. Twenty-minute intro call, no slides.