# ADR 002: Timeline Aggregation Architecture ## Status Accepted ## Context The dashboard aggregates data from multiple sources (Todoist, Trello, PlanToEat, Google Calendar, Google Tasks). Users need a unified chronological view of upcoming items across all sources without opening multiple apps. Key challenges: - Different data sources have different models (Task, Card, Meal, Event) - Some sources have time-of-day, others only have dates - Meals have no explicit time but should appear at logical meal times - Need to support grouping by day section (Today, Tomorrow, Later) ## Decision Implement a **polymorphic TimelineItem model** that normalizes all data sources into a single sortable structure. ### Technical Details: **Unified Model (`internal/models/timeline.go`):** ```go type TimelineItem struct { ID string Type TimelineItemType // task, meal, card, event, gtask Title string Description string Time time.Time AllDay bool URL string DaySection string // overdue, today, tomorrow, later // ... additional fields } ``` **Meal Time Defaults:** - Breakfast → 08:00 - Lunch → 12:00 - Dinner → 19:00 - Other → 12:00 **Implementation:** - `internal/handlers/timeline_logic.go` - `BuildTimeline()` aggregation function - `internal/handlers/timeline.go` - HTTP handler - `internal/models/timeline.go` - Data models - Store methods: `GetTasksByDateRange()`, `GetMealsByDateRange()`, `GetCardsByDateRange()` **Grouping Strategy:** Items are grouped into collapsible day sections: - **Overdue** - Past due items (expanded) - **Today** - Due today (expanded) - **Tomorrow** - Due tomorrow (expanded) - **Later** - 2+ days out (collapsed by default) ## Consequences **Pros:** - Single unified view reduces context switching - Consistent sorting regardless of data source - Extensible - new sources just need a converter to TimelineItem - Collapsible sections reduce cognitive load **Cons:** - Meal times are assumed, not actual (user might eat breakfast at 10am) - All-day items appear at midnight, requiring special handling - Multiple API calls per request (mitigated by caching) ## Alternatives Considered **Option A: Source-specific views only** - Rejected: Defeats the purpose of a unified dashboard **Option B: Store normalized items in database** - Rejected: Adds complexity, staleness issues, harder to keep in sync **Option C: Client-side aggregation (JavaScript)** - Rejected: More complex, slower on mobile, harder to test