Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Wanderwall

An NFC-powered travel gallery that lives on your fridge. Tap a souvenir fridge magnet on a hidden reader and a framed touchscreen flies a globe to that trip - tracing the actual route, road-trip legs and flight arcs alike - then opens a photo gallery: an auto-rolling carousel, an Apple Photos-style grid, and a "things we ate" section.

Originally inspired by thecodedose's EverAfter (concept only; all code and art here is original). Unlike EverAfter, content is fully runtime-driven: adding a trip is a Drive folder drop, not a rebuild.

Architecture

magnet (NTAG sticker) -> PN532 reader -> nfc-service -> POST /api/scan
                                                          |
Google Drive folder -> rclone pull -> ingest pipeline     |
                       (thumbs, GPS route, globe frames)  v
                                        FastAPI server -- WebSocket --> kiosk UI
                                        (serves media + API + kiosk build)
  • server/ — FastAPI: trips API, media serving, WebSocket scan events, photo management, background sync job
  • kiosk/ — React + Vite: the kiosk experience plus the admin at /admin (Sync / Library / Magnets)
  • ingest/ — content pipeline: photos in; manifest, thumbnails, GPS-derived route, and the globe animation out
  • nfc-service/ — PN532 polling daemon for the Raspberry Pi
  • deploy/ — Raspberry Pi setup script, systemd units, and publish_web.sh (static site deploy)
  • library/ — runtime data root (gitignored): trips/<slug>/, tags.json

The globe

The signature moment. Every trip gets a pre-rendered spin + zoom sprite sheet (buttery on a Pi - no live 3D), and the kiosk overlays pins, place labels, and an animated route using the same orthographic projection math:

  • Photo EXIF GPS is clustered into stops (>25 km apart), ordered by timestamp.
  • Legs under ~400 km draw as solid ground paths (road trip); longer legs as dashed, bowed flight arcs.
  • The zoom level adapts to the trip's spread: a road trip zooms deep into one region, an international hop stays wide.
  • No GPS? The folder name is geocoded to a single destination. Wrong guess? Fix it in the admin - the globe re-renders in the background.

Quick start (demo, no hardware)

# 1. Python env
python3 -m venv .venv && .venv/bin/pip install -r server/requirements.txt

# 2. Generate demo content (3 sample trips with routes)
.venv/bin/python -m ingest.demo_content

# 3. Kiosk build
cd kiosk && npm install && npm run build && cd ..

# 4. Run
.venv/bin/uvicorn server.app.main:app --port 8000

Open http://localhost:8000 — press keys 1..9 to simulate magnet scans, u for an unknown magnet (pairing flow). Admin lives at http://localhost:8000/admin.

For development with hot reload: cd kiosk && npm run dev (proxies API to :8000).

Adding a real trip

Drop photos into the Drive folder Wanderwall/<Place Name>/ (food shots into a food/ subfolder), then press Sync in the admin - or locally, drop into library/inbox/<Place Name>/ and run:

.venv/bin/python -m ingest.ingest

Re-syncing the same folder merges new photos into the existing trip. To pair a magnet, just scan the blank NFC sticker on the kiosk and pick the trip.

Magnet stickers & deep links

Every trip is reachable at /trip/<slug> (e.g. /trip/japan-2025; add ?view=globe to play the globe flight first). This is the URL to write onto each magnet's NTAG215 sticker — one encoding serves both worlds:

  • Phone: tapping the magnet pops the trip gallery in the browser — no app, no kiosk hardware needed. Use a free app like NFC Tools to write the full public URL (record type "URL", e.g. https://wanderwall.pages.dev/trip/japan-2025 — see "Publishing the website" below), then optionally lock the tag.
  • Pi kiosk: the PN532 service reads the same URL off the tag, parses the slug, and opens the trip on the wall display. URL-encoded tags need no pairing; blank tags still work via the admin Magnets pairing flow (UID mapping), which also serves as a fallback if a tag's URL slug goes stale.

Slugs are permanent once written to a physical sticker — trip titles can change freely, but renaming a slug breaks the magnets pointing at it.

Publishing the website (free, no server)

The public site is a static export — no machine of yours runs in production. Your PC does the work (sync, ingest, admin edits), then one command snapshots everything and pushes it to Cloudflare's CDN:

your PC: Drive sync -> ingest -> admin fixes -> export  ──deploy──>  Cloudflare Pages (free)
                                                                          ^
                                             phone taps magnet ── opens /trip/<slug>

One-time setup (free Cloudflare account required):

npx wrangler login
npx wrangler pages project create wanderwall

Publish (and republish after every new trip or edit):

deploy/publish_web.sh

That runs python -m ingest.export_static — which builds the kiosk in static mode (VITE_STATIC_SITE=1: JSON snapshots instead of live API, no websocket, no admin) and assembles dist-public/ with api/trips.json, api/trips/<slug>.json, the photo library, and an SPA fallback for /trip/<slug> deep links — then deploys the folder with wrangler. Your site lands at https://wanderwall.pages.dev (custom domains are free in the Pages dashboard); that's the URL to write on magnet stickers.

Notes:

  • The published site is a snapshot: it updates only when you re-run deploy/publish_web.sh. Admin, Drive sync, and live scan events stay on your PC / the Pi — they never ship publicly.
  • A static site is public to anyone who has the link. To restrict it, put Cloudflare Access (free tier) in front of the Pages project.
  • python -m ingest.export_static --skip-build --out <dir> reuses the last kiosk build or changes the output folder.

Raspberry Pi (hardware phase)

See deploy/README.md for the full Pi 5 + Touch Display 2 + PN532 wiring and install guide. Google Drive sync uses rclone with your own account (read-only scope; the folder stays private).

About

An NFC-powered travel gallery that lives on your fridge.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages