# FamilySync ## What This Is FamilySync is a self-hosted, Dockerized family organization hub for a two-person household, modeled loosely on Skylight. It gives the family one unified, color-coded calendar and shared collaborative lists (groceries, gift ideas), reachable from a single low-friction React PWA — across a mixed Android/Fastmail and Apple ecosystem — built as one custom app on top of the family's existing paid Fastmail account. Email stays with members' existing mail clients and is out of scope. ## Core Value The household can see and co-edit one color-coded family calendar (shared + each member's personal) and shared lists from a single low-friction PWA — cross-ecosystem, no app store, no per-member calendar credential juggling. ## Requirements ### Validated (None yet — ship to validate) ### Active - [ ] Unified, color-coded calendar view aggregating all Fastmail-hosted calendars (shared family + each member's personal) - [ ] Create / edit / delete events written back to the correct Fastmail calendar via the app's single broker token - [ ] Shared collaborative lists (groceries, gift ideas) that both members co-edit, stored in MariaDB - [ ] Live list sync so co-edits appear without manual refresh (Redis optional) - [ ] Authelia OIDC login for every member (true SSO) - [ ] React PWA installable on iPhone and Android via "Add to Home Screen" (no App Store) - [ ] Web Push notifications for event reminders and list changes - [ ] Low-friction onboarding for the non-technical Apple member — visit one URL, sign in ### Out of Scope - Wall-display / kiosk dashboard — deferred to v2; calendar + lists are the v1 core, display is the deferrable piece - Email features — members keep existing mail clients; never the product's job - Self-hosted calendar server (Baikal) — Fastmail hosts all calendars; one fewer service. Reversible if self-hosted calendar is ever wanted - Vikunja / external task backend — lists live in the custom MariaDB; cross-ecosystem native task sync is impossible anyway - DAVx5 — not needed - React Native / App Store publishing — PWA delivers app-like UX without publishing overhead - PostgreSQL — not in the existing stack; MariaDB is the database - Forking existing apps — the value is the aggregation/display layer, not the backends ## Context - **Household:** Primary user (project owner) on Fastmail + Android, uses the Fastmail app natively. Other member (wife) on Apple (iPhone/Mac). Wife adoption is a hard UX constraint. - **One app to build:** backend + MariaDB + React PWA behind Authelia, sitting on top of Fastmail. This is far lighter than the prior Baikal + Vikunja + PWA design that was evaluated and dropped. - **Calendars are all on Fastmail.** Personal calendars are also Fastmail-hosted calendar collections, so the app reads and writes everything (shared + personal) through a single Fastmail JMAP/CalDAV broker token — no external ICS feeds, no per-member credential management. The primary user gets the shared calendar natively in the Fastmail app; Apple members use the PWA (optionally subscribe in native Apple Calendar via CalDAV). - **Prior exploration:** Architecture was revised across two sessions (explore → Opus verification). See `.planning/notes/familysync-architecture.md` for full reasoning behind the dropped options. - **Open questions (for phase research):** - Fastmail API — JMAP vs CalDAV for the app's calendar read/write. Which is cleaner to build against? - PWA Web Push — sufficient/reliable enough for family alerts on iOS, or is a fallback needed? - Mechanics of surfacing each member's *personal* Fastmail calendar to the broker token (calendar sharing/ACLs within Fastmail). ## Constraints - **Tech stack**: MariaDB for the database — PostgreSQL is not available in the stack - **Tech stack**: Redis available (optional, for live list sync / push) - **Infrastructure**: Unraid host running Docker + Docker Compose - **Auth**: Authelia (already deployed) — OIDC/OAuth2 for the custom app; all members authenticate through it - **Calendar backend**: Fastmail (paid, existing) is the single source for all calendars via JMAP/CalDAV - **Frontend**: React PWA only — no React Native, no App Store - **Networking**: Split-DNS internal domain, private IPs internally; public exposure via Pangolin/Newt tunnel, no open ports - **UX**: Must be slick and low-friction for a non-technical Apple member — hard constraint, drives design tradeoffs - **Scope**: No email features; no forking existing apps ## Key Decisions | Decision | Rationale | Outcome | |----------|-----------|---------| | Calendar hosted on Fastmail, not self-hosted (Baikal dropped) | Fastmail reaches the whole household native-or-PWA with one fewer self-hosted service; Fastmail Android app can't show self-hosted CalDAV anyway | — Pending | | Personal calendars also Fastmail-hosted collections, aggregated via one broker token | Avoids external ICS feeds and per-member credential management; uniform read/write path | — Pending | | Shared lists in custom MariaDB, not Vikunja | Cross-ecosystem native task sync is impossible; a list table in the backend being built anyway is trivial vs another container + SSO integration | — Pending | | React PWA only, no React Native / App Store | App-like UX with one codebase for all surfaces; lowest onboarding friction (one URL) | — Pending | | Authelia OIDC for all members | True SSO consistent with existing infra; no separate calendar-credential problem | — Pending | | Web Push notifications in v1 (not deferred) | Family alerts judged essential day one; build push into the foundation | — Pending | | Personal-calendar overlay in v1 (not shared-only) | Unified view of everyone's schedules is the Skylight magic worth shipping early | — Pending | ## Evolution This document evolves at phase transitions and milestone boundaries. **After each phase transition** (via `/gsd-transition`): 1. Requirements invalidated? → Move to Out of Scope with reason 2. Requirements validated? → Move to Validated with phase reference 3. New requirements emerged? → Add to Active 4. Decisions to log? → Add to Key Decisions 5. "What This Is" still accurate? → Update if drifted **After each milestone** (via `/gsd-complete-milestone`): 1. Full review of all sections 2. Core Value check — still the right priority? 3. Audit Out of Scope — reasons still valid? 4. Update Context with current state --- *Last updated: 2026-06-03 after initialization*