summaryrefslogtreecommitdiff
path: root/spec.md
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-01-12 09:27:16 -1000
committerPeter Stone <thepeterstone@gmail.com>2026-01-12 09:27:16 -1000
commit9fe0998436488537a8a2e8ffeefb0c4424b41c60 (patch)
treece877f04e60a187c2bd0e481e80298ec5e7cdf80 /spec.md
Initial commit: Personal Consolidation Dashboard (Phase 1 Complete)
Implemented a unified web dashboard aggregating tasks, notes, and meal planning: Core Features: - Trello integration (PRIMARY feature - boards, cards, lists) - Todoist integration (tasks and projects) - Obsidian integration (20 most recent notes) - PlanToEat integration (optional - 7-day meal planning) - Mobile-responsive web UI with auto-refresh (5 min) - SQLite caching with 5-minute TTL - AI agent endpoint with Bearer token authentication Technical Implementation: - Go 1.21+ backend with chi router - Interface-based API client design for testability - Parallel data fetching with goroutines - Graceful degradation (partial data on API failures) - .env file loading with godotenv - Comprehensive test coverage (9/9 tests passing) Bug Fixes: - Fixed .env file not being loaded at startup - Fixed nil pointer dereference with optional API clients (typed nil interface gotcha) Documentation: - START_HERE.md - Quick 5-minute setup guide - QUICKSTART.md - Fast track setup - SETUP_GUIDE.md - Detailed step-by-step instructions - PROJECT_SUMMARY.md - Complete project overview - CLAUDE.md - Guide for Claude Code instances - AI_AGENT_ACCESS.md - AI agent design document - AI_AGENT_SETUP.md - Claude.ai integration guide - TRELLO_AUTH_UPDATE.md - New Power-Up auth process Statistics: - Binary: 17MB - Code: 2,667 lines - Tests: 5 unit + 4 acceptance tests (all passing) - Dependencies: chi, sqlite3, godotenv Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'spec.md')
-rw-r--r--spec.md383
1 files changed, 383 insertions, 0 deletions
diff --git a/spec.md b/spec.md
new file mode 100644
index 0000000..a62909b
--- /dev/null
+++ b/spec.md
@@ -0,0 +1,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