What I Built
A private photo archive for family use. The premise is straightforward: upload photos, organise them by family, browse by timeline. The interesting engineering is in the cross-family linking system — a photo can belong to multiple family groups simultaneously, so a photo from a family gathering appears in both the Hughes and the extended family archives without being duplicated.
This project was also a deliberate exercise in using Python for the backend rather than Node.js. FastAPI handles the API layer with async route handlers, Pydantic for request validation, and SQLAlchemy for database access. The frontend is Next.js talking to it over REST.
Architecture
Key Features
Cross-Family Linking
A photo can be linked to multiple family groups via a junction table. Uploading a group photo once makes it visible in every relevant family's archive. No duplication, no separate upload per family.
Deterministic Colour Schemes
Each family gets a consistent colour identity derived deterministically from their family ID. The same family always gets the same accent colour — no manual assignment, no colour clashes, and new families get a colour automatically on creation.
Share Codes
Generate a time-limited share code for a specific album or family view. Recipients can browse that view without an account. Codes expire and can be revoked. No public URL that stays live indefinitely.
Timeline UI
Photos are displayed in chronological order with date grouping. Scroll through years and months. Filter by family or by individual. The timeline reads EXIF date data from uploads where available, falling back to upload date.
The App
Album View — Photo Gallery
Login Screen
Historic Family Photo
Full Album — Extended Family Members
Archived Family Photo
Why FastAPI
Most of my backend work is in Node.js/Express. Memories was a deliberate choice to build a full production backend in Python to confirm I can operate comfortably in that stack. FastAPI specifically was chosen for its async-first design, automatic OpenAPI documentation, and Pydantic's request validation — all of which make the API surface well-defined and easy to reason about.
The result: a fully typed Python API with auto-generated docs, running in Docker alongside the Next.js frontend and PostgreSQL, deployed on the same self-managed VPS as the other projects.