summaryrefslogtreecommitdiff
path: root/spec.md
blob: a62909b425b6f9f395ccbfa55c435ed18a3ebb68 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
# Personal Consolidation Dashboard - Project Spec

## Overview
Build a unified web dashboard that aggregates tasks, notes, and meal planning from multiple services into a single interface. Go backend + simple frontend with mobile-responsive design.

## Core Requirements

### Phase 1: Read-Only Aggregation (MVP)
Display data from:
1. **Todoist** - Tasks and projects
2. **Obsidian** - Recent notes (file system access)
3. **PlanToEat** - Upcoming meals/recipes
4. **Trello** (optional phase 1) - Boards and cards

### Phase 2: Write Operations
- Create/update/complete tasks in Todoist
- Quick capture notes (save to Obsidian vault)
- Add meals to PlanToEat planner

### Phase 3: Enhancements
- Search across all sources
- Unified quick capture
- Daily digest view
- Mobile PWA configuration

## Technical Stack

### Backend
- **Language:** Go 1.21+
- **Framework:** Standard library + chi/gorilla for routing (your choice)
- **Storage:** SQLite for caching API responses, user preferences
- **APIs:**
    - Todoist REST API v2: https://developer.todoist.com/rest/v2
    - PlanToEat API: https://www.plantoeat.com/developers
    - Trello REST API: https://developer.atlassian.com/cloud/trello/rest
    - Obsidian: Direct filesystem access to vault directory

### Frontend
- **Framework:** HTMX + Tailwind CSS (or plain HTML/CSS/vanilla JS - your preference)
- **Mobile:** Responsive design, PWA manifest later

### Deployment
- **Local first:** Run on localhost:8080
- **Future:** Docker container, deploy to Fly.io/Railway
- **Data:** SQLite file in project directory, environment variables for API keys

## Data Models

### Task (from Todoist)
```go
type Task struct {
    ID          string
    Content     string
    Description string
    ProjectID   string
    ProjectName string
    DueDate     *time.Time
    Priority    int
    Completed   bool
    Labels      []string
    URL         string // Link back to Todoist
}
```

### Note (from Obsidian)
```go
type Note struct {
    Filename    string
    Title       string
    Content     string // First 200 chars or full content
    Modified    time.Time
    Path        string
    Tags        []string
}
```

### Meal (from PlanToEat)
```go
type Meal struct {
    ID         string
    RecipeName string
    Date       time.Time
    MealType   string // breakfast, lunch, dinner
    RecipeURL  string
}
```

### Board/Card (from Trello)
```go
type Board struct {
    ID    string
    Name  string
    Cards []Card
}

type Card struct {
    ID      string
    Name    string
    ListID  string
    ListName string
    DueDate *time.Time
    URL     string
}
```

## API Integration Details

### Todoist
- **Auth:** Bearer token in Authorization header
- **Endpoint:** https://api.todoist.com/rest/v2/tasks
- **Rate limit:** Not publicly documented, use reasonable polling (5min intervals)
- **Key operations:**
    - GET /tasks - Fetch all active tasks
    - GET /projects - Fetch project list
    - POST /tasks - Create new task
    - POST /tasks/{id}/close - Complete task

### PlanToEat
- **Auth:** API key in query parameter or header (check docs)
- **Endpoint:** https://www.plantoeat.com/api/v2
- **Key operations:**
    - GET /planner_items - Fetch upcoming meals
    - GET /recipes - Fetch recipe details

### Trello
- **Auth:** API Key + Token in query parameters
- **Endpoint:** https://api.trello.com/1
- **Key operations:**
    - GET /members/me/boards - Fetch user's boards
    - GET /boards/{id}/cards - Fetch cards on board

### Obsidian
- **Access:** Direct filesystem reads from vault directory
- **Location:** Environment variable `OBSIDIAN_VAULT_PATH`
- **Parse:** Markdown files, extract YAML frontmatter for metadata
- **Watch:** Optional - use fsnotify for real-time updates

## Architecture

### Backend Structure
```
cmd/
  dashboard/
    main.go           # Entry point, server setup
internal/
  api/
    todoist.go        # Todoist API client
    plantoeat.go      # PlanToEat API client
    trello.go         # Trello API client
    obsidian.go       # Filesystem reader
  handlers/
    tasks.go          # HTTP handlers for task views
    notes.go          # HTTP handlers for notes
    meals.go          # HTTP handlers for meals
  models/
    types.go          # Shared data structures
  store/
    sqlite.go         # Database operations
web/
  static/
    css/
      styles.css      # Tailwind or custom styles
    js/
      app.js          # Optional vanilla JS
  templates/
    index.html        # Main dashboard
    tasks.html        # Task list partial
    notes.html        # Notes list partial
```

### Configuration
Environment variables (.env file):
```bash
TODOIST_API_KEY=your_token
PLANTOEAT_API_KEY=your_key
TRELLO_API_KEY=your_key
TRELLO_TOKEN=your_token
OBSIDIAN_VAULT_PATH=/path/to/vault
DATABASE_PATH=./dashboard.db
PORT=8080
```

## UI Requirements

### Dashboard Layout
```
+----------------------------------+
| [Quick Capture]                  |
+----------------------------------+
| Today's Tasks        | Meals     |
| □ Task 1            | 🍳 Breakfast|
| □ Task 2            | 🍕 Lunch    |
| ☑ Task 3            | 🍝 Dinner   |
+----------------------------------+
| Recent Notes                     |
| • Note 1 (2h ago)               |
| • Note 2 (1d ago)               |
+----------------------------------+
| Trello Boards (optional)         |
+----------------------------------+
```

### Features
- **Mobile-responsive** - Stack vertically on small screens
- **Dark mode support** (optional but nice)
- **Refresh button** - Manual data sync
- **Auto-refresh** - Every 5 minutes
- **Loading states** - Spinners during API calls
- **Error handling** - Show API failures gracefully

## Success Criteria

### Phase 1 Complete When:
- [ ] Dashboard shows Todoist tasks for today/week
- [ ] Dashboard shows 5-10 most recent Obsidian notes
- [ ] Dashboard shows upcoming meals from PlanToEat
- [ ] Responsive design works on mobile browser
- [ ] Runs locally with `go run cmd/dashboard/main.go`

### Phase 2 Complete When:
- [ ] Can create new Todoist task from dashboard
- [ ] Can mark Todoist task complete
- [ ] Can create quick note (saves to Obsidian vault)

## Non-Requirements (Out of Scope)
- User authentication (single user only)
- Real-time sync (polling is fine)
- Offline support
- Data analytics/insights
- Calendar integration
- Migration tools from Google Keep
- Bi-directional Trello sync

## Development Notes

### API Key Setup
User must obtain:
1. Todoist: Settings → Integrations → API token
2. PlanToEat: Account settings → API access
3. Trello: https://trello.com/app-key → Generate token
4. Obsidian: Just need filesystem path

### Testing Strategy
- Start with Todoist integration only (simplest API)
- Mock API responses for initial UI development
- Use real APIs once structure is solid
- Test on mobile browser early

### Performance
- Cache API responses in SQLite (5min TTL)
- Obsidian: Only scan vault on startup + when requested
- Parallel API calls using goroutines
- Limit Obsidian file reads (e.g., last 20 modified files)

## Questions to Resolve During Development
1. HTMX vs vanilla JS for interactivity?
2. Full Tailwind build or CDN version?
3. SQLite migrations approach (golang-migrate vs manual)?
4. Obsidian vault - recursive scan or flat directory?
5. Trello - all boards or filter to specific ones?

## Getting Started Checklist
- [ ] Initialize Go module
- [ ] Set up project structure
- [ ] Create .env.example with required variables
- [ ] Implement Todoist API client first (test with real token)
- [ ] Build basic HTTP server with single endpoint
- [ ] Create simple HTML template
- [ ] Add SQLite caching layer
- [ ] Iterate on remaining integrations

## Reference Documentation
- Todoist API: https://developer.todoist.com/rest/v2
- PlanToEat API: https://www.plantoeat.com/developers
- Trello API: https://developer.atlassian.com/cloud/trello/rest/api-group-actions
- HTMX: https://htmx.org/docs/

Endpoint design guidance for Claude Code:
Security

Token auth in header: Authorization: Bearer <token> (not query param - avoids URL logging)
Single read-only token - Generate once, store in your env vars and tell me separately
Rate limiting: 100 req/hour per token (I rarely need more than 1-2 calls per conversation)
No CORS needed - Server-to-server only
HTTPS only when deployed (Let's Encrypt via Caddy/Traefik)

Response format
json{
"generated_at": "2026-01-09T15:30:00Z",
"tasks": {
"today": [
{
"id": "task_123",
"content": "Review PRs",
"priority": 4,
"due": "2026-01-09T17:00:00Z",
"project": "Work",
"completed": false
}
],
"overdue": [...],
"next_7_days": [...]
},
"meals": {
"today": {
"breakfast": "Oatmeal with protein powder",
"lunch": "Chicken salad",
"dinner": "Salmon with veggies"
},
"next_7_days": [...]
},
"notes": {
"recent": [
{
"title": "Sprint planning notes",
"modified": "2026-01-09T10:15:00Z",
"preview": "First 150 chars...",
"path": "work/sprint-planning.md"
}
]
},
"trello_boards": [...] // optional
}
Efficiency

Cache responses: 5min TTL in-memory, return cached JSON if token valid
Limit data volume:

Tasks: Today + overdue + next 7 days only
Notes: 10 most recent only
Meals: Today + next 7 days
Total response < 100KB


Selective fields: Don't include full note content, just previews
Single endpoint: /api/claude/snapshot (not multiple endpoints)

Error responses
json{
"error": "unauthorized",
"message": "Invalid or missing token"
}
```

Standard HTTP codes:
- 200: Success
- 401: Invalid/missing token  
- 429: Rate limit exceeded
- 500: Server error (with safe message, no stack traces)

### Implementation hints for Claude Code:
```
Create GET /api/claude/snapshot endpoint:
- Require Authorization: Bearer <token> header
- Return cached JSON (5min TTL) with current state
- Include: today's tasks, overdue tasks, next 7 days tasks, today's meals,
  next 7 days meals, 10 most recent notes
- Limit each note preview to 150 chars
- Total response should be < 100KB
- Use 401 for auth failures, 429 for rate limits
- Cache API responses to avoid hammering upstream services
```

### What I'll do:
When you give me the URL + token:
```
My dashboard: https://dashboard.yourdomain.com/api/claude/snapshot
Token: <you'll share separately>
```

I'll call:
```
web_fetch(
url="https://dashboard.yourdomain.com/api/claude/snapshot",
headers={"Authorization": "Bearer <token>"}
)
Then parse JSON and use context naturally in our conversations.
Optional: Webhook for updates
If you want proactive notifications (e.g., "Pete, you have 3 overdue tasks"), add:

POST endpoint to receive webhook URL from me (not implemented yet on my side)
Your dashboard posts to that URL when important state changes
Skip this for now - manual fetch is simpler