docs: refresh project documentation against current codebase
Publish / publish (push) Successful in 26s

This commit is contained in:
Lucas Berger
2026-06-18 06:44:29 -04:00
parent 18d3ee6a4f
commit 1e2cc52659
11 changed files with 872 additions and 178 deletions
+33 -1
View File
@@ -192,7 +192,39 @@ FamilySync is a self-hosted, Dockerized family organization hub for a two-person
## Architecture
Architecture not yet mapped. Follow existing patterns found in the codebase.
FamilySync is a pnpm monorepo with two apps: `apps/api` (Hono 4.x on Node 22 LTS, Drizzle ORM + MariaDB 11, TypeScript) and `apps/pwa` (React 19 + Vite 8 + vite-plugin-pwa). A single Docker Compose stack runs the API container (which also serves the PWA static build) and a MariaDB container, exposed through a Pangolin/Newt tunnel.
The backend handles two auth paths: local username/password (scrypt + HS256 JWT `local-session` cookie) and Authelia OIDC (authorization code + PKCE via `@hono/oidc-auth`). Both populate `c.get('user')`; the OIDC guard is skipped when a valid local session is present. A local user may link an OIDC identity later.
Calendar data lives exclusively in Fastmail CalDAV. The broker layer (`apps/api/src/broker/`) uses `tsdav` for PROPFIND/REPORT/PUT/DELETE, `ical.js` for VCALENDAR parsing, and `rrule` for server-side recurrence expansion. Writes are enqueued in a `calendarOutbox` table and drained asynchronously every 15 seconds; a ctag-based poller re-syncs calendars every 5 minutes.
Lists are persisted in MariaDB. Live list updates flow over SSE (`text/event-stream`) via an in-process Node.js `EventEmitter`; a 30-second polling fallback is always active. Push notifications (reminders + calendar change alerts) are dispatched via `web-push` (VAPID) to APNs/FCM. Redis is present in the stack but not yet used at runtime (reserved for future multi-process pub/sub).
The PWA uses TanStack Query for all server state (events, lists, user, sync status, auth mode) and Zustand for UI-only state (selected date, open panels, active tab).
```text
familysync/
├── apps/
│ ├── api/src/
│ │ ├── index.ts # App entry: mounts routes, starts background workers
│ │ ├── routes/ # HTTP handlers (events, lists, me, push, sse, auth, admin, setup)
│ │ ├── auth/ # Local session + OIDC middleware + dev-bypass + OIDC-link
│ │ ├── broker/ # CalDAV client, sync, poller, outbox worker, RRULE expand, write
│ │ ├── db/ # Drizzle schema, mysql2 pool, migrations
│ │ └── lib/ # List/event emitters, push dispatcher, rank, guards, admin/setup helpers
│ └── pwa/src/
│ ├── App.tsx # BrowserRouter shell
│ ├── routes/ # Page-level components
│ ├── components/ # Shared UI components
│ ├── api/ # Typed fetch wrappers (client.ts, listsClient.ts)
│ ├── hooks/ # useListSSE, usePushSubscription
│ ├── store/ # Zustand stores (calendarStore, listsStore)
│ └── sw.ts # Custom Workbox service worker
├── docker-compose.yml # Production stack (api + mariadb + redis)
└── docker-compose.dev.yml # Dev overrides
```
See `docs/ARCHITECTURE.md` for the full Mermaid component diagram, data-flow walkthroughs, and key abstractions table.
<!-- GSD:architecture-end -->