Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
README.md
Deployment #
Local Docker stack mirroring the planned Fly.io topology: a public Caddy front that serves our built SPA and reverse-proxies the AppView, plus a private HappyView instance. Same-origin, so no CORS and the atproto OAuth admin UI is reachable.
browser ─▶ http://127.0.0.1:8099 (caddy)
/ → our SPA (../dist)
/hv/* → happyview (dashboard, admin API, OAuth, client-metadata)
/xrpc/* → happyview (rewritten to /hv/xrpc/*)
/health → happyview
First run #
# 1. Build the HappyView image from source (several minutes the first time)
./build-happyview.sh
# 2. Create secrets
cp .env.example .env
printf 'SESSION_SECRET=%s\n' "$(openssl rand -base64 48)" >> .env # or edit .env by hand
printf 'TOKEN_ENCRYPTION_KEY=%s\n' "$(openssl rand -base64 32)" >> .env
# 3. Build the SPA (from the project root)
cd .. && npm run build && cd deploy
# 4. Up
docker compose up -d
Then:
- App SPA — http://127.0.0.1:8099/
- HappyView dashboard — http://127.0.0.1:8099/hv/ (first user to log in becomes super user)
- XRPC — http://127.0.0.1:8099/xrpc/...
Rebuild the SPA (npm run build) and refresh; Caddy serves ../dist live (no container rebuild).
Notes #
- HappyView is not published to the host — only Caddy is. Caddy reaches it as
happyview:3000over the compose network (the Fly.internalequivalent). PUBLIC_URLmust be the Caddy origin and must NOT include/hv; HappyView appendsBASE_PATHautomatically when building OAuth callbacks.- The HappyView API client credentials (key
hvc_…+ secrethvs_…) are injected server-side by Caddy as theX-Client-Key/X-Client-Secretheaders (see the(happyview_key)snippet inCaddyfile), sourced fromHAPPYVIEW_CLIENT_KEYandHAPPYVIEW_CLIENT_SECRETindeploy/.env. Caddy strips any client-supplied values first, so they never have to ship in the SPA bundle and can't be spoofed by callers.{env.…}is read from Caddy's process at startup — after changing either value, rundocker compose up -d --force-recreate caddy(a reload alone won't pick up a new env var). - The SPA is local-first (records in IndexedDB); wiring it to HappyView XRPC for sync is a later phase. This stack proves the serving + proxy topology.
- After editing
Caddyfile, rundocker compose up -d --force-recreate caddy. Docker on macOS bind-mounts a single file by inode, so replacing the file (any editor that writes atomically) leaves the container on the stale copy —caddy reloadthen validates the old content. Force-recreating re-binds the current file. - Host port is 8099 (8080 was already taken locally). Change it in
docker-compose.ymlandPUBLIC_URLtogether —PUBLIC_URLfeeds OAuth redirect URIs.