Django/DRF + PostgreSQL/Redis/Celery backend with accounts, library, moments, and notifications apps; React/TypeScript/Vite frontend with Instagram-style sidebar nav, feed, profiles, nested comment replies, notifications, and photo/video upload with ffmpeg-generated posters. Co-Authored-By: Claude Sonnet 5 <[email protected]>
4.0 KiB
Aurora Moments
Aurora Moments is not a social network that stores your pictures. It's your photo library with a social network built around it.
A self-hostable photo/video platform: a private, full-resolution photo library (like iCloud Photos) with an explicit, opt-in social layer ("Moments") built on top of it. Uploading never equals publishing — a photo only enters the social graph when its owner chooses to share it as a Moment.
Architecture
docker-compose
│
├── postgres PostgreSQL — primary datastore
├── redis Celery broker/result backend
├── api Django + Django REST Framework
├── worker Celery worker (thumbnail/feed/large renditions, EXIF)
└── web React + TypeScript (Vite), talks to the API over REST
- api/ — Django project. Apps:
accounts(users, follows),library(private originals, renditions, albums),moments(the social posts, comments, reactions). JWT auth viadjangorestframework-simplejwt. - web/ — React + TypeScript SPA (Vite). Login/Register, a private Library grid with upload, and a Home feed of Moments.
- mobile/ — not started; see mobile/README.md.
Storage
Original uploads and derived renditions (thumbnail/feed/large) go through
MEDIA_BACKEND in .env:
filesystem(default) — written toMEDIA_ROOT, which you can bind-mount to a NAS path in a self-hosted deployment.s3— any S3-compatible object store (AWS S3, MinIO, Backblaze B2, ...) viadjango-storages, no code changes needed.
Privacy model
- Everything uploaded to a user's Library is private by default.
- A Moment is one or more Library items + caption/location, shared with
an explicit
audience:public,followers,friends,family,custom, oronly_me. familyandcustomcurrently fall back to owner-only visibility — full circle/custom-audience membership is a V1.5 feature (seeapps.moments.models.MomentQuerySet.visible_to); shipping that stub now was a deliberate choice to never over-share by default.- Shared Albums (
apps.library.models.Album+AlbumCollaborator) let multiple people contribute full-resolution photos to one place (e.g. a wedding), without the audience/feed logic of Moments.
Running locally
cp .env.example .env
docker compose up --build
- Web: http://localhost:5173
- API: http://localhost:8000/api/
- Django admin: http://localhost:8000/admin/ (create a superuser first, see below)
Create a superuser for the Django admin:
docker compose exec api python manage.py createsuperuser
Migrations run automatically on api container start.
What's in V1
- Registration/login (JWT), profiles, follow/followers
- Private full-resolution photo/video upload with async thumbnail/feed/large rendition generation and EXIF extraction (Celery + Pillow)
- Share a Moment from existing Library items, with audience controls
- Home feed, comments, reactions (likes)
- Shared Albums with per-user roles (viewer/contributor/admin)
- Original-quality downloads (the original file is never deleted or resized in place)
Deliberately not in V1 (see the original concept notes this repo is based on): automatic iOS backup, push notifications, messaging, Memories, maps, facial recognition, semantic AI search, Stories, video transcoding, and server federation. Those come in V1.5/V2 once the core loop — private library, explicit sharing — is proven.
Backend layout
api/
├── config/ settings, urls, celery app
└── apps/
├── core/ shared abstract models (TimeStampedModel, Audience enum)
├── accounts/ User, Follow
├── library/ LibraryItem, MediaRendition, Album, AlbumItem, AlbumCollaborator
└── moments/ Moment, MomentItem, Comment, Reaction
REST API root: /api/accounts/, /api/library/, /api/moments/,
/api/auth/token/ (JWT obtain/refresh).