Demo mode¶
Proton Faces ships with a demo mode that lets you explore every feature of the app without a Proton account, a session file, or any configuration. The bridge container is skipped entirely; in its place, an in-process DemoBridge serves a curated fixture of free CC0/Unsplash photos.
Quick start¶
Open http://localhost:8080 and sign in with:
- username:
demo - password:
proton-faces
That's it. The two containers (indexer-demo and app-demo) come up with DEMO_MODE=1, skip the Proton bridge, and load the bundled fixture.
Override the password:
What you get¶
The fixture is a small but representative library:
| Count | Source | |
|---|---|---|
| Faces | 32 | randomuser.me portraits (MIT) |
| Scenes / objects | 50 | picsum.photos (Unsplash License) |
| Total photos | 82 | |
| Distinct people clusters | ~8 | HDBSCAN over face embeddings |
| Cities with markers on the map | 10 | Lille, Paris, Barcelona, Rome, Berlin, Amsterdam, NYC, Tokyo, Lisbon, Edinburgh |
| Albums | 4 | Summer 2024, Trips, Portraits, Objects & Scenes |
| Duplicate pairs | 2 | for the Duplicates view |
Every demo photo has a real sha1 hash, real capture time, and the right media type — the same code paths that run on real Proton photos run on these.
What changes in demo mode¶
| Path | Real mode | Demo mode |
|---|---|---|
proton-bridge container |
Runs and talks to Proton | Skipped (compose profile) |
bridge_client.get_bridge() |
HTTP client to bridge | Returns DemoBridge |
| Timeline / nodes / albums | Fetched from Proton's API | Served from app/src/demo_assets/fixture.json |
| Thumbnails | Downloaded from Proton | Generated locally from photos/<uid>.jpg |
| GPS / place names | From each photo's own EXIF | Injected from the fixture |
| Multi-user auth | Manual --create-admin |
Default demo admin auto-created on first boot |
Binary media endpoints (/thumb, /full, /cover, /crop) |
Secure by default (bearer token or signed URL) | World-readable — the profile sets DEMO_ALLOW_PUBLIC_THUMBS=1 so static <img> tags work without JS |
| Everything else (CLIP, faces, clustering, search, admin) | Same | Same |
The ML pipeline — InsightFace, CLIP, HDBSCAN — runs exactly as it does in real mode. The only thing that's different is where the photo bytes come from.
How it's wired¶
app/src/demo.pydefines aDemoBridgeclass that mirrors the surface of the realBridgeClient.app/src/bridge_client.py::get_bridge()returnsDemoBridgewhenDEMO_MODE=1is set.- The
democompose profile setsDEMO_MODE=1on two services (indexer-demoandapp-demo) and excludesproton-bridge.
You can read the source: app/src/demo.py.
Refreshing the fixture¶
The fixture is committed to the repo under app/src/demo_assets/. To re-fetch it:
This pulls new face portraits from randomuser.me and new scenes from picsum.photos. Re-run any time — already-downloaded photos are reused, and the fixture is fully deterministic (RNG seeds are pinned).
To wipe the data volume and start over:
Using demo mode with your own code¶
Demo mode is also a convenient way to run automated UI tests against a real proton-faces instance. The capture script in scripts/capture_screenshots.py uses it as a target:
BASE_URL=http://localhost:8080 DEMO_USERNAME=demo DEMO_PASSWORD=proton-faces \
python scripts/capture_screenshots.py
For API scripting, see the REST API reference.
Limitations¶
- The fixture photos are JPEGs only — no HEIC, no videos. The HEIC + video fallback path in the fullres loop is not exercised by demo mode.
- All photos are ~512px max-side thumbnails on disk (the "full-resolution" view returns the same bytes).
- Album membership is curated, not real Proton albums.
- No EXIF data besides GPS is populated.
These don't affect the UI behavior — every view in the docs site works against demo mode.
Credits¶
Every photo in the fixture is free for use. See app/src/demo_assets/CREDITS.md for the full per-photo attribution.