Your moment on the big screen. A live photo wall for any event: guests send photos from their phones, it plays on Fire TV.
A conference booth, a trade fair, a wedding or a party: guests scan the QR code on the screen, take a photo, a host approves it, and a second later it drops onto the wall as a polaroid. It was built for Fire TV on Amazon Vega OS, and the same wall runs in any browser, so a laptop or a projector works too.
Runs on Vega OS (Fire TV) · any browser
Try it: live demo · site and guides
On the live demo a person approves each photo by hand, so yours may take a while to appear. To approve your own, run it on your machine with pnpm demo (below).
1. Scan the QR code on the screen → 2. Snap a photo and add a caption → 3. Watch it land on the wall once a host approves it
Make it yours · Vega OS field notes · How it's built
Rather not run servers? BoothWall Cloud, the hosted version, is coming soon: get notified. This repo is the complete open edition.
One deployed stack runs one wall for a single host. Configure its identity, branding and presentation in files. The native TV app supports Vega OS only. The browser provides the display at /, guest capture at /snap, and a passcode-protected Control desk at /control (Review, Live and Guests tabs on a phone).
Twelve polaroids drift on the wall, a page at a time, while it steps through every approved photo. New arrivals get a badge and a moment full screen. The side panel has the QR code and a live count per category. It's driven by the D-pad, Back is kiosk-safe, and every animation runs on the native driver.
The room can drive it too. The remote's Play/Pause and Next/Previous keys reach the wall through Vega Media Controls, the route Alexa's "pause" and "next" take too. Hold OK, or press Photo call in Control, for a photo call: a minute with a big QR code, a mission from your categories and a countdown, then a closing card with the photos it brought. Outside demo mode Menu opens a card naming every remote button, and so does Remote help in Control; any key closes it, or it goes after ten seconds. Control's Photo call and Remote help reach the browser wall too: there Escape ends a call, and a key or a click closes the card.
Press OK for the spotlight, a full-screen slideshow that keeps going on its own.
Four looks come with it, each one line in the config (settings.theme): universal, wedding, party and conference. In demo mode the remote's Menu button flips through them, and Next theme in Control flips the TV and browser walls through them until the app restarts or the page reloads.
The wall is one shared package. The TV renders it through React Native for Vega and the web app renders the same code through React Native for Web, live from the same API. Open the wall in a browser and put it on a projector, or press F for full screen.
The root address stays a display on every screen size. Guests use the separate /snap page; changing the browser width never changes its role.
Guests upload at /snap, the address behind the QR code. They pick a photo, add a caption, choose a category when required, and tick the consent box. The page then follows their photo: it tells them the moment it's live, says "Still waiting · the host reviews each photo" if nobody has approved it after 15 seconds, and says "Not this time. The host didn't put this one on the wall." if the host keeps it off, with a button to send another. While it's waiting or live, they can remove it themselves. The page speaks English and German.
Manual approval is the default. Control is the host's desk: today's numbers (on the wall, waiting, sent today) and the waiting queue to approve or reject, a live preview of the wall, switches for the slideshow and guest uploads, Photo call, Remote help and Next theme for the TV and the browser wall, and the guest QR and link. On a phone it splits into Review, Live and Guests at /control, /control/live and /control/guests. Branding, categories and presentation are configured in files, not in Control.
A Hono API on Cloudflare Workers, photos in R2, rows in D1, and one Durable Object that pushes each approval to every screen. It hibernates while nothing is happening, so a connected screen sitting idle costs nothing.
Tested on macOS on Apple Silicon with Node 24, pnpm 10 and Vega SDK 0.24.12112.
You need Node 24 and pnpm 10 (corepack enable sets up pnpm); no Vega SDK and no Cloudflare account:
git clone https://github.com/boothwall/boothwall-oss && cd boothwall-oss
pnpm install
pnpm demo --lanIt starts the API and web app on your machine's network address, adds approved demo photos to a fresh wall and prints display, guest and Control addresses plus the local passcode. Open / on a laptop or projector, scan its QR code with your phone, send a photo and approve it in /control. Your phone needs to be on the same network. Plain pnpm demo keeps everything on localhost, where /snap in a second browser tab stands in for the phone. Ctrl+C stops it.
pnpm web:dev runs the web app alone against the API in your config, at http://localhost:5173. Arrow keys, Enter, Space and Escape stand in for the remote. Add ?demo to run the wall on the bundled photos with no API at all, ?kiosk to hide the cursor and hints, or ?fullscreen to go full screen on the first key press.
You need the Vega SDK with the Virtual Device, Node 24 and pnpm 10. Start the Virtual Device, then run the whole thing:
export PATH="$HOME/vega/bin:$PATH"
pnpm tv:vvd:start:1080 # the Virtual Device at 1920×1080
pnpm trypnpm try is pnpm demo --lan plus the TV: it points urls in the config at your machine while it runs (the TV reads its API at build time; stopping puts the config back), builds the app and opens it on the Virtual Device. The QR code on the TV leads phones to your local wall. To do it by hand, set the urls that pnpm demo --lan prints and run pnpm tv:build:debug && pnpm tv:run:vvd (tv:run:vvd installs the Apple Silicon build; on an Intel Mac use pnpm try).
Use the Virtual Device's on-screen remote, or run pnpm remote for a bigger one in your browser. To run without a network, set demo: true in the config and rebuild; in demo mode the remote's Menu button steps through the four themes.
For developers: about 15 minutes to your own wall on Cloudflare's free tier. Photos go to R2, and Cloudflare asks for a payment method before it turns R2 on, even on the free tier.
-
Configure. Everything event-specific lives in
packages/shared/src/config/boothwall.config.ts: the event name, hashtag, categories, brand colours, the badge beside the logo and where it deploys. Setdeploy.apiDomainanddeploy.webDomainto domains on your Cloudflare account, or to""for free workers.dev addresses. docs/customising.md explains every field. -
Brand it. Swap the logo, the TV backdrop and the icons for yours, keeping the file names (list). To see a fully branded wall first, run
pnpm boothwall example conference-booth. -
Deploy. Run
pnpm exec cf auth login, thenpnpm boothwall setup. Unlessapps/api/.dev.varsalready has a Control passcode, it asks for one of 12 or more characters (Enter makes one) and keeps it there. Then it creates the D1 database and R2 bucket in your account, deploys the API and the web app, and writes the addresses back into the config. It doesn't print a passcode it made; read it from that file. After that,pnpm boothwall deployships changes.If you ran
pnpm demofirst,apps/api/.dev.varsalready holds the demo's 8-digit passcode, and setup stops before it creates anything rather than replace it. Change theADMIN_TOKEN=line to 12 or more characters (letters, digits and_ ! @ % + = : . , / -), or delete the line to be asked, then run setup again.pnpm demokeeps using whatever passcode is there. -
Put it on the TV. Set
tv.wallIdin the config (andtv.displayCredentialonly if your host checks one), then build a release and install it on a Fire TV in developer mode, or on the Virtual Device. The build is yours: it shows that one wall, a different wall means a rebuild, and the config inside it can be extracted, so keep it on your own TVs and never publish the.vpkg(details).pnpm tv:build:release vega run-app apps/tv-vega/build/armv7-release/tv_armv7.vpkg com.boothwall.app.main -d <device>
<device>is the stick's serial fromvega device list. The first time, the stick needs developer mode, which takes an Amazon developer account (free to create): Turning on developer mode on a Vega OS Fire TV Stick walks through it, and Testing a Vega app on a real Fire TV Stick covers connecting over Wi-Fi, installing, pressing keys and taking screenshots from a terminal. After a fresh install, the remote's Play/Pause and Next/Previous keys work from the app's second launch. To update the TV, rebuild and run the same command; the config is bundled into the app, so the TV keeps the old values until you do.
- A phone can't open the
--lanaddress. It has to be on the same network as your machine, and some Wi-Fi networks (guest networks, many offices and venues) keep devices apart. If macOS asks whether Node may accept incoming connections, allow it; a VPN can get in the way too. Without a phone, plainpnpm demoand/snapin a second browser tab work. - The Virtual Device can't reach your machine. Use
pnpm tryorpnpm demo --lan, which listen on every interface; a server that listens only onlocalhostis out of the Virtual Device's reach. More in the Vega OS notes. - "Package is invalid" on install. Check the manifest: an ASCII
titleand the icon with its file extension (details). Install the.vpkgbuilt for that device:armv7for a Fire TV Stick,aarch64for the Virtual Device on Apple Silicon. - An Intel Mac.
pnpm tv:run:vvdinstalls the Apple Silicon build. Usepnpm try, which picks the right one, or runvega run-apponapps/tv-vega/build/x86_64-debug/tv_x86_64.vpkg. - The TV app never shows a wall. A fresh clone's config points at an example API,
https://wall-api.example.com, and the TV reads it at build time. Runpnpm try, runpnpm boothwall setup, or setdemo: true, then rebuild.
- Running an event: the TV remote, the Control desk, what guests see after sending, and privacy and safety.
- Older review settings: upgrading a saved instance to manual standalone approval.
- Customising: every config field and the images to replace.
- How it's built: how a photo gets from a phone to the wall, and why each piece is the way it is.
- Vega OS field notes: the platform gotchas I hit, from build commands to memory on a Fire TV Stick.
- Development: commands, running the API locally and changing the database.
- Changelog: what changed in each release.
- Contributing: checks before a pull request and how the code is organised. Issues and pull requests are welcome, especially from people building for Vega OS.
BoothWall started as a booth demo I built on my own and first showed at next.app devCon 2026 in Berlin. Everything event-specific now lives in one config file, so the same code works for any event. The changelog has the rest.
The code is MIT. The default BoothWall artwork in brand/ and the apps' asset folders is MIT too, with two exceptions:
- The caption fonts in
apps/tv-vega/assets/fonts/keep their own licences, the SIL Open Font License 1.1 or Apache 2.0, in the licence file beside each font. The web app loads the same fonts from their@fontsourcepackages. - The GitHub mark in
packages/wall-ui/src/assets/icons/belongs to GitHub, Inc. and is used only to link to the repo.
The demo photos, the booth photos in the UI kit's preview and the night-sky backdrop were made with ChatGPT image generation. They show no real people or events.
The TV app builds on the Vega SDK and the @amazon-devices/* packages, which come from npm under Amazon's Program Materials License Agreement, not MIT. They aren't in this repo, but a built .vpkg contains them.
BoothWall is an independent project by @ddedic. It isn't an official Amazon product and isn't endorsed by Amazon. Amazon, Fire TV, Vega and Alexa are trademarks of Amazon.com, Inc. or its affiliates. GitHub and the GitHub logo are trademarks of GitHub, Inc.





