docs(02): capture phase context
This commit is contained in:
@@ -0,0 +1,142 @@
|
|||||||
|
# Phase 2: Calendar Display - Context
|
||||||
|
|
||||||
|
**Gathered:** 2026-06-04
|
||||||
|
**Status:** Ready for planning
|
||||||
|
|
||||||
|
<domain>
|
||||||
|
## Phase Boundary
|
||||||
|
|
||||||
|
A unified, color-coded, **read-only** calendar that aggregates every accessible Fastmail
|
||||||
|
calendar (shared family + each member's personal) into one view, with day / week / month /
|
||||||
|
agenda views, correct rendering of recurring events (server-side expansion), all-day events
|
||||||
|
(no timezone shift), and DST boundaries. Built on the broker confirmed in Phase 1.
|
||||||
|
|
||||||
|
**Out of scope (other phases):** event create/edit/delete write-back (Phase 3), PWA install
|
||||||
|
(Phase 3), shared lists (Phase 4), web push (Phase 5), the tablet/wall-display **kiosk mode**
|
||||||
|
and a runtime theme-switcher (v2 — see Deferred), per-member show/hide filtering (deferred
|
||||||
|
until >2 members), single-occurrence recurring edits (v1.x).
|
||||||
|
</domain>
|
||||||
|
|
||||||
|
<decisions>
|
||||||
|
## Implementation Decisions
|
||||||
|
|
||||||
|
### Theming architecture (the load-bearing decision)
|
||||||
|
- **D-01:** Build a **design-token layer** — color, spacing, density, and typography expressed
|
||||||
|
as CSS custom properties + a small theme object — and build the UI exclusively against those
|
||||||
|
tokens. No hard-coded colors/spacing in components.
|
||||||
|
- **D-02:** Ship **only the "clean" theme** in Phase 2. A future Skylight/tablet "display" theme
|
||||||
|
must be achievable as a **token-set swap, not a refactor**. Do NOT build the second theme or a
|
||||||
|
runtime theme-switcher UI now (those are v2 kiosk work).
|
||||||
|
- **D-03:** Even the clean theme is tuned to be **legible and informational at tablet distance**,
|
||||||
|
not ultra-minimal — the v2 north star is a tablet wall-display, so the clean theme must not be
|
||||||
|
so sparse that it can't carry information. (Rationale: user's real end goal is a tablet display;
|
||||||
|
see [[project-familysync]] / PROJECT.md Out-of-Scope note on wall display.)
|
||||||
|
|
||||||
|
### Views & default
|
||||||
|
- **D-04:** Provide all four views: **day, week, month, agenda** (CAL-03).
|
||||||
|
- **D-05:** **Device-adaptive default view:** phone → **Agenda** (lowest friction for the
|
||||||
|
non-technical iPhone member); tablet/desktop → **Month** (spatial overview, closest to the v2
|
||||||
|
display). Remember the last-used view per device.
|
||||||
|
|
||||||
|
### Color & ownership legibility
|
||||||
|
- **D-06:** **Per-member color fill** using the color already assigned on the user row in Phase 1
|
||||||
|
(6-color palette already scales as members are added); the **shared-family calendar gets one
|
||||||
|
reserved, distinct color**. This is the "whose is this" signal and must read at a glance.
|
||||||
|
- **D-07:** Show a small **color legend / key** (member → color) so ownership is decodable. A
|
||||||
|
per-member show/hide **filter is deferred** until there are more than two members (same trigger
|
||||||
|
as the future display theme) — a 2-person household doesn't need it yet.
|
||||||
|
|
||||||
|
### Event detail density
|
||||||
|
- **D-08:** **Informational + tap-to-expand.** Month = colored bars with the event title (not bare
|
||||||
|
dots); Week/Day = time + title; Agenda = time + title + location. Tapping any event opens a
|
||||||
|
**read-only detail popover** (title, time, location, description) — this popover is intended to
|
||||||
|
be **reused as the edit surface in Phase 3**, so build it with that in mind.
|
||||||
|
|
||||||
|
### Recurrence / time (carried forward — not re-discussed)
|
||||||
|
- **D-09:** Recurring events are **expanded server-side** (`CALDAV:expand` / broker emits concrete
|
||||||
|
occurrences for the requested window) — locked in STATE/CLAUDE. The client renders occurrences;
|
||||||
|
it does not run rrule expansion itself for the primary path.
|
||||||
|
- **D-10:** **Single local timezone** for v1 — all-day events render with no date shift (D-13 split
|
||||||
|
already in the schema). Secondary-timezone display toggle is deferred to v1.x.
|
||||||
|
|
||||||
|
### Claude's Discretion
|
||||||
|
- Week start day (Sunday vs Monday): default **Sunday** (US locale — the account has a "USA
|
||||||
|
Holidays" calendar); expose as a token/config so it's trivial to flip. Planner/researcher may
|
||||||
|
confirm.
|
||||||
|
- Exact rendering library is the **researcher's call** — but it must support headless/custom
|
||||||
|
styling against the token layer (D-01), all four views, server-expanded occurrences, all-day
|
||||||
|
banners, and good touch UX on iOS. (Candidates to evaluate, not locked: Schedule-X,
|
||||||
|
react-big-calendar, FullCalendar, or a Temporal-based custom grid. Avoid libs that force their
|
||||||
|
own opinionated theme and can't be token-styled.)
|
||||||
|
- Skeleton/loading and empty states: build them, polished enough for the "slick" constraint.
|
||||||
|
|
||||||
|
### Dev-auth bypass (from D-14, project-level)
|
||||||
|
- `/api/*` is OIDC-gated, but live Authelia is deferred (D-14). Plan a **documented dev-auth
|
||||||
|
bypass** (e.g., an env-flagged middleware that injects a fixed dev user) so Phase 2 UI can be
|
||||||
|
built and tested locally without a live OIDC provider. Must be off by default / impossible in
|
||||||
|
production builds.
|
||||||
|
</decisions>
|
||||||
|
|
||||||
|
<canonical_refs>
|
||||||
|
## Canonical References
|
||||||
|
|
||||||
|
**Downstream agents MUST read these before planning or implementing.**
|
||||||
|
|
||||||
|
### Project decisions & scope
|
||||||
|
- `.planning/PROJECT.md` — core value, constraints, Key Decisions incl. D-14/D-15; wall-display is v2 (informs D-02/D-03).
|
||||||
|
- `.planning/ROADMAP.md` §"Phase 2: Calendar Display" — goal + success criteria; §Phase 3/4 for scope boundaries.
|
||||||
|
- `.planning/REQUIREMENTS.md` — CAL-02 (unified color-coded view), CAL-03 (day/week/month/agenda), and the recurring-event *display* portion of CAL-07.
|
||||||
|
|
||||||
|
### Phase 1 foundation this builds on
|
||||||
|
- `.planning/phases/01-foundation-broker-spike/01-03-SUMMARY.md` — broker API surface (syncCalendar, poller), event cache shape.
|
||||||
|
- `.planning/phases/01-foundation-broker-spike/01-04-SUMMARY.md` — index.ts route wiring, `/api/events`, `/api/me`.
|
||||||
|
- `.planning/phases/01-foundation-broker-spike/CAL-08-DECISION.md` — per-member app-password model (how multiple members' calendars aggregate).
|
||||||
|
- `apps/api/src/routes/events.ts` — current `/api/events` (raw cache dump; will need expansion + parsed fields + color/owner for display).
|
||||||
|
- `apps/api/src/db/schema.ts` — `users.color`, `calendars.userId`, `calendarEvents` (dtstartUtc/dtstartDate/allDay/rawVevent) — the D-13 split the display relies on.
|
||||||
|
- `CLAUDE.md` — locked stack (React 19, Vite, TanStack Query, Zustand, ical.js, rrule), CalDAV/expand guidance, iOS constraints.
|
||||||
|
- `docs/deployment.md` — dev-auth bypass context lives alongside Gate 2 (D-14).
|
||||||
|
</canonical_refs>
|
||||||
|
|
||||||
|
<code_context>
|
||||||
|
## Existing Code Insights
|
||||||
|
|
||||||
|
### Reusable Assets
|
||||||
|
- `apps/pwa/src/api/client.ts` — typed fetch client (`fetchMe`, `credentials: 'include'`); extend with a typed `fetchEvents(range)`.
|
||||||
|
- `apps/pwa/src/components/EventProof.tsx` — proof-of-concept that already fetches `/api/events` and parses a VEVENT; the calendar replaces/absorbs it.
|
||||||
|
- `apps/pwa/src/App.tsx` — member badge (name + color via `/api/me`); the per-member color source for D-06.
|
||||||
|
- `apps/pwa/src/main.tsx` — `QueryClientProvider` already set up (TanStack Query is the server-state owner).
|
||||||
|
|
||||||
|
### Established Patterns
|
||||||
|
- Server state → TanStack Query; UI-only state (selected date, current view) → Zustand (locked; do not put events in Zustand).
|
||||||
|
- Broker is the ONLY Fastmail I/O boundary; `/api/events` reads the MariaDB cache only (no tsdav in routes) — recurrence expansion belongs server-side near the broker/route, never a direct Fastmail call from the UI.
|
||||||
|
- Hono app exported from `index.ts` without auto-starting (testable); add display-oriented endpoints there.
|
||||||
|
|
||||||
|
### Integration Points
|
||||||
|
- `/api/events` must evolve from "raw row dump" to a display-ready shape: expanded occurrences within a requested date window, parsed title/time/location, all-day flag, and member color / shared-vs-personal indicator (join calendarEvents → calendars → users.color). This is the main backend work of Phase 2.
|
||||||
|
- Dev-auth bypass middleware sits in front of `/api/*` (see D-14).
|
||||||
|
</code_context>
|
||||||
|
|
||||||
|
<specifics>
|
||||||
|
## Specific Ideas
|
||||||
|
|
||||||
|
- "Clean theme now, switch to **Skylight style** later" — Skylight = large, glanceable, high-contrast family dashboard. It's the reference for the future display theme; the token layer (D-01) exists to make that swap cheap.
|
||||||
|
- The **real end goal is a tablet wall-display** — legibility and information density are first-class even in v1's clean theme (D-03).
|
||||||
|
- Theme/aesthetic reference target: Apple/Fantastical-style clean for v1.
|
||||||
|
</specifics>
|
||||||
|
|
||||||
|
<deferred>
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- **Tablet / wall-display kiosk mode** + the actual Skylight "display" theme + runtime theme-switcher UI — **v2** (PROJECT.md Out-of-Scope). Phase 2 only guarantees the token architecture makes this a swap, not a rewrite.
|
||||||
|
- **Per-member show/hide filter** — add when membership grows beyond two (D-07).
|
||||||
|
- **Secondary timezone display toggle** — v1.x (already in roadmap deferred items).
|
||||||
|
- **Single-occurrence / "this and following" recurring edits** — v1.x; Phase 3 does create + whole-series only.
|
||||||
|
|
||||||
|
### Reviewed Todos (not folded)
|
||||||
|
- `kickoff-new-project.md` ("Kick off FamilySync with /gsd:new-project") — matched only on generic keywords (date/requirements/phase); a stale project-bootstrap todo, not Phase 2 scope.
|
||||||
|
</deferred>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Phase: 2-Calendar Display*
|
||||||
|
*Context gathered: 2026-06-04*
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# Phase 2: Calendar Display - Discussion Log
|
||||||
|
|
||||||
|
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
|
||||||
|
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
|
||||||
|
|
||||||
|
**Date:** 2026-06-04
|
||||||
|
**Phase:** 2-Calendar Display
|
||||||
|
**Areas discussed:** Visual model / theming, Default view & per-device, Color & shared-vs-personal, Event detail density
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Visual model → Theming architecture
|
||||||
|
|
||||||
|
Initial framing (pick one aesthetic) was reformulated after the user clarified they want a
|
||||||
|
**modular** approach: start clean, but be able to switch to a Skylight/tablet "display" theme
|
||||||
|
later as family members are added — the real end goal being a **legible tablet wall-display**.
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Token layer + clean theme only | Design tokens (CSS vars + theme object); ship only clean; future display theme = token swap; no switcher UI yet | ✓ |
|
||||||
|
| Token layer + two themes + toggle now | Build clean + first-cut display theme + runtime toggle now | |
|
||||||
|
| Hardcode clean, refactor later | No abstraction; retrofit theming at v2 | |
|
||||||
|
|
||||||
|
**User's choice:** Token layer + clean theme only.
|
||||||
|
**Notes:** Claude flagged that building two themes + a switcher now is v2 gold-plating (wall-display
|
||||||
|
is deferred in PROJECT.md); the disciplined "modular" is a token layer with one clean theme. Also
|
||||||
|
agreed the clean theme must stay legible/informational at tablet distance (D-03), and the color
|
||||||
|
model must scale past two members.
|
||||||
|
|
||||||
|
## Default view & per-device
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Phone→Agenda, Tablet/Desktop→Month | Device-adaptive default; remember last-used per device | ✓ |
|
||||||
|
| Month everywhere | Consistent grid; cramped on phone | |
|
||||||
|
| Agenda everywhere | List-first; underuses tablet/desktop | |
|
||||||
|
|
||||||
|
**User's choice:** Phone→Agenda, Tablet/Desktop→Month.
|
||||||
|
|
||||||
|
## Color & shared-vs-personal
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Per-member fill + reserved shared color | Phase-1 member colors; shared calendar gets one distinct color | ✓ |
|
||||||
|
| Per-member fill + shared marked by icon | Icon instead of reserved color | |
|
||||||
|
| Per-calendar color | Hue per Fastmail collection, member secondary | |
|
||||||
|
|
||||||
|
**User's choice:** Per-member fill + reserved shared color.
|
||||||
|
**Notes:** Per-member show/hide filter deferred until >2 members; a color legend is shown.
|
||||||
|
|
||||||
|
## Event detail density
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Informational + tap-to-expand | Bars w/ title (month), time+title (week/day), +location (agenda); read-only popover reused for Phase 3 edit | ✓ |
|
||||||
|
| Minimal | Dots + agenda titles, no popover | |
|
||||||
|
| Maximal inline | time+title+location everywhere | |
|
||||||
|
|
||||||
|
**User's choice:** Informational + tap-to-expand.
|
||||||
|
|
||||||
|
## Claude's Discretion
|
||||||
|
- Rendering library choice (must be token-styleable, headless-friendly, all 4 views, server-expanded occurrences, good iOS touch) — researcher decides.
|
||||||
|
- Week start day — default Sunday (US locale), exposed as a token.
|
||||||
|
- Skeleton/loading + empty states — build, polished for the "slick" constraint.
|
||||||
|
|
||||||
|
## Deferred Ideas
|
||||||
|
- Tablet/wall-display kiosk mode + Skylight display theme + runtime theme-switcher — v2.
|
||||||
|
- Per-member show/hide filter — when membership > 2.
|
||||||
|
- Secondary timezone toggle — v1.x.
|
||||||
|
- Single-occurrence recurring edits — v1.x.
|
||||||
Reference in New Issue
Block a user