Services¶
The backend is organized into vertical domains under backend/internal/services/<domain>/. Each domain package owns its full request path: store.go (persistence), service.go (business logic), handler.go (HTTP binding + response shaping), routes.go (route registration), and wire.go (Google Wire provider set). Multi-aggregate domains prefix files and types by aggregate (event_service.go / EventService); some carry deps.go for cross-domain interfaces and colocated *_test.go.
Constructors are named New<Thing>. Response shapes live inside each domain, but small cross-cutting summaries (models.UserSummary, models.EventSummary) are shared from the models package. Cross-cutting infrastructure lives in the platform/ bundle (cache, ws, email, audit, assets, taxonomy, llm, notify) and the boot-time drivers (internal/storage for S3, internal/database for Migrate). Domains are composed in internal/wiring/ (router.go mounts routes, Wire generates the object graph).
Each domain exposes RegisterRoutes(r chi.Router, handler, ...gates): JWT, optional-auth, rate limiters, and access.Require gates are passed in as func(http.Handler) http.Handler middleware, so routes.go never imports middleware or access packages. See Wiring.
Domain catalog¶
| Domain | Summary |
|---|---|
| auth | Registration, login (password, Google, Apple, LINE, WebAuthn), OTP, sessions, JWT, API keys |
| user | Lean user card, profile, preferences, denormalized stats, account lifecycle (deactivate + GDPR delete) |
| friend | Friendship graph, requests, close friends, live friend-location sharing |
| event | Event CRUD, participants, lifecycle state machine, promoted event-item snapshots |
| plan | Collaborative planner: item board, capture pipeline, place/availability votes, promote-to-event |
| chat | Event chat, 1:1 DM, group chat, reactions, disappearing messages, WebSocket transport |
| moment | Ephemeral photo drops, likes, journaled vs. expiring |
| presence | Heartbeat, active-location sharing sessions, check-ins |
| discovery | Read-aggregation query surface: map, radar, unified search, location + profile detail, taxonomy |
| maps | Map detail reads plus personalization (saves, dismissals, category affinity) |
| location | Place search, autocomplete, geocode, reverse, resolve, dedup + merge |
| catalog seeding | Generate + load the global place catalog (countries, cities, curated lists) from open data |
| content | Curated catalog: stamp guide, curio store, challenges, per-catalog asset URLs |
| passport | Earned state: append-only visit ledger, passport counts, progress, retroactive awards |
| gameengine | Evaluates content rules against activity, writes earned passport progress |
| notification | In-app and push notifications, push-token registration |
| media | Direct-to-S3 upload starters, Klipy GIF/sticker proxy, SSRF-guarded link-preview proxy |
| payment | Stripe checkout, billing portal, webhook subscription sync |
| admin | Platform stats, user moderation, location merge, async queue (DLQ) operations |
| partner | Multi-tenant scoping: Partner entity, memberships, per-partner role gating |