# pathways A photo viewer that walks your library as a maze. You start on one random picture; every photo secretly holds up to four paths — its biggest memberships across labels, keywords, camera, and lens — one per direction. Press a direction (arrow keys, or the buttons that appear when you hover) and the next photo of that path locks into the grid beside you, in the direction you moved. The visited pictures accumulate into a mosaic you can pan around and step back through. The live instance lives at and reads the PhotoPrism database directly (read-only) on the same machine. PhotoPrism's admin UI stays behind basic auth at ; pathways is public. ## How the paths work - Every photo's paths are its member groups: label(s), keyword(s), camera, lens. They're ranked by member count; the top four (one per direction) become its exits. - Paths with a single member are skipped; a photo with fewer than four usable paths is topped up with a "library" path (all photos), so every direction always leads somewhere. - Each path is an ordered cycle (by taken date, then id): walking "grey" goes grey → grey → … and wraps around. Assignment is deterministic, so revisiting a photo always offers the same four exits. - Movement is spatial: pressing a direction lands you on whatever photo already occupies that cell — you walk through photos you've placed before rather than over them. New photos are only added when you step into a genuinely empty cell. If the path's next photo is already placed elsewhere, focus jumps to it, so the mosaic never holds two copies of a photo. ## Run it ```bash npm install DB_HOST=127.0.0.1 DB_USER=photoprism DB_PASSWORD=… DB_NAME=photoprism \ PORT=3100 THUMBS_ROOT=/srv/photoprism/storage/cache/thumbnails \ node server.mjs ``` On NixOS the box runs it as a systemd unit (`systemd.services.pathways`), started after `mysql.service`, as user `dax`. ## API - `GET /api/paths` — every photo (id, thumb, title, date) plus the facets (groups with ≥3 members) - `GET /api/random` — one random photo - `GET /api/exits/:id` — a photo plus its four exits; each exit has the path it follows (`type`, `name`, `count`) and the `next` photo in that path's cycle - `GET /api/health` — liveness probe Thumbnails are served as static files by Caddy from `/srv/photoprism/storage/cache/thumbnails/{a}/{b}/{c}/{hash}_{size}.jpg` (`720x720_fit` for tiles). ## Layout ``` server.mjs API + static file serving public/index.html splash + the walkable stage public/app.css tiles, hover exits, lock-in animation public/app.js grid state, exits, pan/click/keyboard, cycling walk ``` The thumbnail path sharding matches PhotoPrism: directory = first three characters of the file hash. Note `file_hash` comes back from MariaDB as a binary Buffer, so it is decoded to a string before building URLs.