Calendars as entities, uniform widget contract, multi-dashboard tasks
Architecture refinements before module work begins: - Calendars become first-class entities (mirror of lists). Each calendar has its own visibility (private | household) and is independently shareable. Updated CLAUDE.md data model and task 10. - Drop the singleton/parameterized split for dashboard widgets. Every widget declares a configSchema + defaultConfig + resolveConfigOptions and every placement is an independent instance — same widgetId can appear multiple times on one dashboard pointed at different things. Updated task 04 contract; tasks 11/12 widget sections aligned. - Add tasks 25 (multiple dashboards per user) and 26 (customizable layout + widget configuration). Replaces the previously-considered three-task plan with a cleaner two-task split that the uniform contract enables. Phase 3 index updated; STATUS records the rationale. - Task 20 reframed as a single-dashboard MVP that exercises the new contract end-to-end before the customization layer lands.
This commit is contained in:
@@ -60,7 +60,7 @@ src/
|
||||
### Core primitives every module gets
|
||||
|
||||
- **Entity registry.** Modules declare entity types; share-link, activity log, search, reminders all work against any registered entity.
|
||||
- **Dashboard contribution API.** Each module exports a widget + priority. Dashboard composes whatever's installed.
|
||||
- **Dashboard widget registry.** Every widget is uniformly configurable (no singleton/parameterized split) and reusable — each placement on a dashboard is an independent instance with its own config. Each user has multiple dashboards; the active dashboard composes whatever widgets they've placed.
|
||||
- **Quick-add registry.** Modules register quick actions for the dashboard's `+` menu.
|
||||
- **Share-link service.** `createShareLink(entityType, entityId, { expiresAt, capabilities })` → `fam.ginnoir.com/s/<token>`. Generic.
|
||||
- **Notification bus.** `notify(userId, { title, body, url })` fans out to web push + in-app + (optional) ntfy.
|
||||
@@ -74,15 +74,17 @@ src/
|
||||
## Data model (v1)
|
||||
|
||||
- `users`, `households`, `household_members`
|
||||
- `calendar_events` — title, start, end, all_day, location, notes, color, owner. `rrule` text column reserved (no recurrence in v1). `external_source`/`external_id` nullable for future Google/Apple sync.
|
||||
- `lists` (type enum: `shopping` | `task` | future), `list_items`
|
||||
- `calendars` — name, color, owner_id, visibility (`private` | `household`). First-class entity; users create as many as they want, each independently shareable via the share-link service.
|
||||
- `calendar_events` — `calendar_id` fk, title, start, end, all_day, location, notes, owner. `rrule` text column reserved (no recurrence in v1). `external_source`/`external_id` nullable for future Google/Apple sync.
|
||||
- `lists` (type text — not enum, to allow extension), `list_items`
|
||||
- `notes` — title, body, pinned, remind_at
|
||||
- `dashboards` — per-user named dashboards (any user can have many), `layout` jsonb of placed widgets `[{ widgetId, config, x, y, w, h }]`.
|
||||
- `share_links` — entity_type, entity_id, token, capabilities jsonb, expires_at
|
||||
- `activity_log` — entity_type, entity_id, actor, action, payload jsonb
|
||||
- `push_subscriptions`
|
||||
- `reminders` — entity_type, entity_id, fire_at, channel. Generic; used by notes/events/anything.
|
||||
|
||||
All entity tables include `household_id`. All mutations are scoped to the caller's household.
|
||||
All household-scoped entity tables include `household_id`. Sub-entities (`calendar_events`, `list_items`) inherit scope via their parent. All reads/mutations are gated by the caller's household membership and, where relevant, per-entity visibility (e.g. private calendars).
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user