# Photo Gallery — Design Document ## 0. Solution **Go app (Option B)** — a single static binary reverse-proxied by Caddy. - Caddy handles TLS and serves the app on a secret URL path (e.g., `https://photos.example.com/trip-crete-2026-a8f3b2c1/`). - The Go binary serves an HTML page with multi-file upload (drag-and-drop), a file listing, and a "download all as zip" button. - Photos land in a configurable directory (one per trip). When the trip is done, stop the binary, move the folder to cold storage. - No database, no runtime deps, no Docker. ~200-400 lines of Go, ~10 MB binary. **Why this over pure Caddy (Option A):** At this scale (10 friends, 200 photos, ~4 GB max), both work. But the Go app gives a noticeably better mobile upload experience (multi-file, progress feedback) and zip download for free — worth the cost of one extra process. --- ## 1. Context & Scope After a holiday with friends, everyone has photos scattered across their phones. The goal is a self-hosted, lightweight web application where: - Friends open a link in their browser, upload their photos. - Friends can browse and download photos others have uploaded. - Once everyone has contributed, all photos live on the server — a single consolidated archive. - The host (you) keeps everything on their own infrastructure. No third-party cloud involved. **Current landscape:** Caddy is already used as the primary web server/reverse proxy. The solution should integrate naturally with it. The server is personal infrastructure — simplicity and low resource usage matter more than scaling to thousands of users. --- ## 2. Goals & Non-Goals ### Goals - **Browser-only UX** — no app install, no client software, no account creation. - **Upload & download** — friends can push photos and pull the full set. - **Lightweight** — minimal dependencies, low memory/CPU footprint, easy to deploy and tear down. - **Self-hosted** — all data stays on your server, full ownership. - **Simple ops** — ideally a single binary or a Caddyfile tweak, no database. - **Caddy-friendly** — works behind or with Caddy with minimal config. ### Non-Goals - User accounts or authentication beyond a shared secret/link. - Image editing, resizing, or transcoding. - Long-lived public gallery (this is ephemeral, per-trip). - Mobile app. - Handling thousands of concurrent users. - Video support (nice-to-have at best, not a driver). --- ## 3. Design The system is intentionally shallow. One server, one directory of files, one web interface. ```mermaid graph LR subgraph Friends A[Browser] B[Browser] C[Browser] end subgraph Server D[Caddy] E[Application / File Backend] F[/photos directory/] end A -- "upload/download via HTTPS" --> D B -- "upload/download via HTTPS" --> D C -- "upload/download via HTTPS" --> D D -- "reverse proxy or direct serve" --> E E -- "read/write" --> F ``` ### Features #### Friends (end users) | Feature | Detail | |---|---| | **Batch upload** | Select multiple photos at once (file picker or drag-and-drop) and upload them in a single action. Progress feedback per file. | | **Browse gallery** | View all uploaded photos directly in the browser — no download required. Images are served as compressed/resized previews to keep page load fast. | | **Download as zip** | Download the entire directory as a single `.zip` file with one click. | | **Password access** | Enter a directory-specific password to access the gallery. No account creation. | #### Operator (you) | Feature | Detail | |---|---| | **Create directory + password** | Create a new photo directory (one per trip/event) and assign it a password. This is the only admin action needed before sharing the link with friends. | | **Tear down** | When collection is done, stop the service or remove the route. Archive the photos directory to cold storage. | ### Key design points - **One directory per event** — each trip/event gets its own directory and its own password. No shared state between directories. - **Caddy terminates TLS** — every approach sits behind Caddy for HTTPS + domain. - **Access control** — password per directory, set by the operator at creation time. Friends enter the password once to access upload/browse/download. - **Ephemeral lifecycle** — spin up before sharing the link, tear down after collection is done. The photos directory persists. - **Compressed previews** — the gallery view serves resized/compressed versions of photos for fast browsing. Original full-resolution files are preserved on disk and served in the zip download. --- ## 4. Alternatives ### A. Caddy `file_server` + `upload` module (pure Caddy) Use Caddy's built-in `file_server` for browsing/downloading, combined with a community Caddy upload handler plugin ([caddyserver/caddy-upload](https://github.com/caddyserver/caddy-upload) or similar). | Aspect | Detail | |---|---| | **How it works** | Caddy serves the directory with `browse`. Uploads go through a Caddy handler that accepts `PUT`/`POST` and writes to disk. A minimal HTML page with a `