Files
shpm/TODO.md
T
2026-08-17 11:01:47 -04:00

90 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Self-Hosted Photo Manager — TODO
## Architecture
A self-built alternative to Immich: React/Vite frontend + Express/SQLite backend,
files stay on disk, DB indexes them, thumbnails are the only derived asset.
```
┌───────────────────┐ watches ┌──────────────────────┐
│ Photo folder(s) │ ─────────────────────▶ │ Ingestion Worker │
│ (disk / NAS) │ │ (chokidar file watch) │
└───────────────────┘ └───────────┬────────────┘
│ extract EXIF,
│ generate thumbnail,
│ compute pHash
▼
┌──────────────────────┐
│ SQLite metadata DB │
│ (photos, tags, │
│ albums, hashes) │
└───────────┬────────────┘
│
▼
┌──────────────────────┐
│ Express API server │
└───────────┬────────────┘
│ REST
▼
┌──────────────────────┐
│ React/Vite frontend │
│ (timeline, albums, │
│ search, map) │
└──────────────────────┘
```
## Build Order
- [ ] **1. Ingestion worker + SQLite schema** — watch folder, extract EXIF, generate thumbnails, populate DB
- [ ] **2. Basic API + timeline UI** — paginated grid, chronological browsing (usable on its own)
- [ ] **3. Detail view + manual tagging/albums**
- [ ] **4. Dedupe detection + review UI** — pHash comparison, side-by-side review, keep/delete
- [ ] **5. Search + filters** — date range, camera model, tag
- [ ] **6. Map view** — Leaflet/MapLibre pins from GPS EXIF
- [ ] **7. Face grouping** — only if wanted after v1–v5 (biggest scope jump, treat as v2+)
## Stack
| Layer | Tech |
|---|---|
| File watching | `chokidar` (persistent) or cron scan |
| EXIF extraction | `exifr` or `exiftool` wrapper |
| Thumbnails | `sharp` (1–2 sizes: grid thumb + preview) |
| Dedupe hashing | pHash via `sharp` + hashing lib, or `blockhash-core` |
| Database | SQLite via `better-sqlite3` |
| API | Express |
| Frontend | React + Vite |
| Map | Leaflet or MapLibre |
| Deployment | Docker container, Nginx Proxy Manager, behind Authelia |
## Database Schema
```sql
photos (
id, filepath, thumbnail_path, date_taken, date_imported,
camera_model, gps_lat, gps_lon, phash, width, height, filesize
)
albums (id, name, created_at)
photo_albums (photo_id, album_id)
tags (id, name)
photo_tags (photo_id, tag_id)
```
## API Endpoints (planned)
```
GET /photos paginated timeline (filter by date, tag, album)
GET /photos/:id full detail + EXIF
GET /photos/duplicates grouped by pHash similarity
GET /photos/map GPS-tagged photos for map view
POST /albums create album
POST /photos/:id/tags tag a photo
```
## Deployment Notes
- Mount photo folder(s) **read-only** (worker doesn't need write access to originals)
- Writable volume for thumbnails + DB
- Route: `photos.necloud.us` via Nginx Proxy Manager
- Same homelab pattern as other services