104 lines
4.0 KiB
Markdown
104 lines
4.0 KiB
Markdown
# 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 via `djangorestframework-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](mobile/README.md).
|
||
|
|
|
||
|
|
### Storage
|
||
|
|
|
||
|
|
Original uploads and derived renditions (thumbnail/feed/large) go through
|
||
|
|
`MEDIA_BACKEND` in `.env`:
|
||
|
|
|
||
|
|
- `filesystem` (default) — written to `MEDIA_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, ...)
|
||
|
|
via `django-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`, or `only_me`.
|
||
|
|
- `family` and `custom` currently fall back to owner-only visibility — full
|
||
|
|
circle/custom-audience membership is a V1.5 feature (see
|
||
|
|
`apps.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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
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:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
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).
|