Manyangles
Event photo collection for a wedding day — and for any gathering that needs the same guest-upload, host-moderate, public-gallery loop.
Guests open a shareable event link, optionally add a name, email, and note, and upload photos. Event people approve what appears in the gallery. Originals stay full quality in S3-compatible object storage.
Image processing
Uploads go directly to object storage; the background worker creates WebP derivatives with Sharp. Displays fit within 2048 × 2048 (quality 82), thumbnails within 400 × 400 (quality 75), and cropped 8:3 banners within 2400 × 900 (quality 82). Encoding uses effort 4. Small images are not enlarged. Display copies are auto-oriented and omit source metadata; original uploads and exports retain their original bytes.
Existing JPEG derivatives remain supported through their saved database keys.
Only newly processed images use .webp keys and image/webp; this change does
not bulk-regenerate existing images or delete their JPEGs.
Repository
apps/
web/ Public site, guest pages, dashboard, platform admin
worker/ image variants, EXIF/GPS strip, HEIC conversion
packages/
contracts/ shared Zod payloads
database/ Drizzle schema, migrations, seed
storage/ S3/Garage client, object keys, presign
email/ Mailpit (dev) / Resend (prod) for auth and guest mail
Quick start
Requirements: Bun 1.4+ and Docker.
cp .env.example .env
bun install
bun run docker:up
bun run db:migrate
bun run auth:seed
bun run db:seed
bun run dev
The app runs at http://localhost:3000. Garage S3 is at
http://localhost:3900. Mailpit is at http://localhost:8027.
- Public:
/(listed events) and/e/demo - Dashboard:
/dashboard - Platform:
/admin
Example accounts (password host, admin password admin):
admin@example.com— platform super-adminhost@example.com/partner@example.com— event ownersmanager@example.com— event manager
Authentik sign-in
Production Docker/Compose setup and original-quality exports are documented in the deployment guide.
Manyangles can use an Authentik OAuth2/OpenID Connect provider alongside email and
password authentication. In Authentik, create a confidential OAuth2/OpenID
provider and application with the openid, profile, and email scopes.
Add a strict redirect URI for each Manyangles deployment:
https://photos.example.com/api/auth/oauth2/callback/authentik
For local development, use
http://localhost:3000/api/auth/oauth2/callback/authentik.
Set all three variables to enable the Authentik button:
AUTHENTIK_ISSUER=https://auth.example.com/application/o/manyangles/
AUTHENTIK_CLIENT_ID=your-client-id
AUTHENTIK_CLIENT_SECRET=your-client-secret
AUTHENTIK_ISSUER is the application issuer URL, not the Authentik root URL.
Manyangles discovers the authorization, token, user-info, and signing-key endpoints
from <issuer>/.well-known/openid-configuration. If none of these variables are
set, Authentik support stays disabled. A partial configuration fails at startup
instead of silently hiding a broken provider.