summaryrefslogtreecommitdiff
path: root/CLAUDE.md
diff options
context:
space:
mode:
Diffstat (limited to 'CLAUDE.md')
-rw-r--r--CLAUDE.md284
1 files changed, 284 insertions, 0 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..bf9caa8
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,284 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Project Overview
+
+A unified web dashboard that aggregates tasks (Todoist & **Trello**), notes (Obsidian), and meal planning (PlanToEat) into a single interface. Built with Go backend + HTMX + Tailwind CSS frontend.
+
+**Current Status:** ✅ Phase 1 COMPLETE
+- Trello integration (PRIMARY feature - all boards + cards)
+- Todoist integration (tasks + projects)
+- Obsidian integration (20 most recent notes)
+- PlanToEat integration (optional - API not public)
+- Mobile-responsive web UI
+- SQLite caching (5-min TTL)
+- Auto-refresh (5 min)
+- AI agent endpoint (`/api/claude/snapshot`)
+- Full test coverage (9/9 tests passing)
+- Binary builds successfully (17MB)
+
+**IMPORTANT:** Trello is the PRIMARY task management system - it's more heavily used than Todoist and is a core required feature.
+
+## Essential Commands
+
+### Development
+```bash
+# Run the application
+go run cmd/dashboard/main.go
+
+# Run with live reload (requires air)
+go install github.com/cosmtrek/air@latest
+air
+
+# Install/update dependencies
+go mod download
+go mod tidy
+
+# Run tests
+go test ./...
+
+# Build production binary
+go build -o dashboard cmd/dashboard/main.go
+./dashboard
+```
+
+### Database
+Database migrations run automatically on startup. Migration files in `migrations/` are executed in alphabetical order.
+
+## Architecture
+
+### Request Flow
+1. HTTP request hits chi router in `cmd/dashboard/main.go`
+2. Router delegates to handler in `internal/handlers/` (needs implementation)
+3. Handler checks cache validity via `internal/store/sqlite.go`
+4. If cache is stale, handler fetches fresh data from API clients in `internal/api/`
+5. Fresh data is saved to cache and returned to handler
+6. Handler renders template from `web/templates/` or returns JSON
+
+### Cache Strategy
+- **TTL-based caching**: Default 5 minutes (configurable via `CACHE_TTL_MINUTES`)
+- **Cache metadata tracking**: `cache_metadata` table stores last fetch time per data source
+- **Parallel API calls**: Use goroutines to fetch tasks, notes, and meals concurrently
+- **Graceful degradation**: If one API fails, show partial data with error message
+
+### Data Sources
+
+**Trello API (`internal/api/trello.go`) - ✅ IMPLEMENTED**
+- Endpoint: `https://api.trello.com/1`
+- Auth: API Key + Token in query parameters (`key=XXX&token=YYY`)
+- **Implemented operations**:
+ - `GetBoards()` - Fetch user's boards from `/1/members/me/boards`
+ - `GetCards(boardID)` - Fetch cards from specific board
+ - `GetBoardsWithCards()` - Fetch all boards with their cards
+ - Full board/list/card hierarchy parsing
+- Store operations: `SaveBoards()`, `GetBoards()`
+- Future: Create/update cards (Phase 2)
+- **Status: COMPLETE** - This is the primary task management system
+
+**Todoist API (`internal/api/todoist.go`)**
+- Endpoint: `https://api.todoist.com/rest/v2`
+- Auth: Bearer token in Authorization header
+- Key operations: `GetTasks()`, `GetProjects()` (both implemented)
+- Future: `CreateTask()`, `CompleteTask()` (Phase 2)
+
+**Obsidian (`internal/api/obsidian.go`)**
+- Direct filesystem access to markdown files
+- Uses `filepath.Walk()` to recursively scan vault
+- Limits to 20 most recent files by modification time
+- Parses YAML frontmatter for tags, extracts inline #tags
+- Content preview limited to ~500 chars
+
+**PlanToEat API (`internal/api/plantoeat.go`)** - OPTIONAL
+- Endpoint: `https://www.plantoeat.com/api/v2`
+- Auth: Bearer token in Authorization header
+- Key operations: `GetUpcomingMeals(days)` (implemented)
+- **Note:** PlanToEat API is not publicly available. Leave `PLANTOEAT_API_KEY` empty if you don't have access
+- The dashboard works fine without it - meals section will simply be empty
+- Future: `GetRecipes()`, `AddMealToPlanner()` (Phase 2)
+
+### Configuration System
+
+All configuration via environment variables (see `.env.example`):
+- **Required**: `TODOIST_API_KEY`, `TRELLO_API_KEY`, `TRELLO_TOKEN` (core task management systems)
+- **Optional**: `PLANTOEAT_API_KEY` (API not publicly available), `OBSIDIAN_VAULT_PATH`, `AI_AGENT_API_KEY`
+- **Helper methods**: `cfg.HasPlanToEat()`, `cfg.HasObsidian()`, `cfg.HasTrello()`
+
+Configuration struct in `internal/config/config.go` validates on load and provides typed access.
+
+**Trello Setup:** Get both API key and token from https://trello.com/power-ups/admin
+- Create a Power-Up (or use existing one)
+- Go to "API Key" tab and generate a new API key
+- **Important:** Copy the API Key, NOT the Secret
+- In the description, follow the "testing/for-yourself" instructions
+- Click the Token link to generate a personal token
+- You need API Key + Token (Secret is not used)
+
+## Project Structure
+
+```
+task-dashboard/
+├── cmd/dashboard/main.go # Entry point, router setup, graceful shutdown
+├── internal/
+│ ├── api/ # External API clients
+│ │ ├── interfaces.go # API interfaces for testing
+│ │ ├── trello.go # ✅ Trello client - GetBoards(), GetCards(), GetBoardsWithCards()
+│ │ ├── todoist.go # ✅ Todoist client - GetTasks(), GetProjects()
+│ │ ├── obsidian.go # ✅ Obsidian client - GetNotes() with filesystem scanning
+│ │ └── plantoeat.go # ✅ PlanToEat client - GetUpcomingMeals()
+│ ├── config/ # Environment variable loading and validation
+│ ├── handlers/ # HTTP request handlers
+│ │ ├── handlers.go # ✅ Web handlers - dashboard, tasks, notes, meals, boards, refresh
+│ │ ├── handlers_test.go # ✅ Unit tests (5 tests)
+│ │ └── ai_handlers.go # ✅ AI agent endpoint - /api/claude/snapshot
+│ ├── middleware/
+│ │ └── ai_auth.go # ✅ Bearer token authentication for AI endpoint
+│ ├── models/types.go # Data models: Task, Note, Meal, Board, Card, CacheMetadata, DashboardData
+│ └── store/sqlite.go # Database layer with cache operations
+├── web/
+│ ├── static/ # CSS and JS files
+│ └── templates/
+│ └── index.html # ✅ Main dashboard template with Trello, Todoist, Obsidian, PlanToEat
+├── migrations/ # SQL migration files (run automatically on startup)
+└── test/
+ └── acceptance_test.go # ✅ Acceptance tests (4 test suites)
+```
+
+## Key Implementation Details
+
+### Handler Pattern (✅ IMPLEMENTED)
+Handlers use interface-based design for testability:
+```go
+type Handler struct {
+ store *store.Store
+ todoistClient api.TodoistAPI // Interface, not concrete type
+ trelloClient api.TrelloAPI // Interface for testing
+ obsidianClient api.ObsidianAPI
+ planToEatClient api.PlanToEatAPI
+ config *config.Config
+ templates *template.Template
+}
+
+// Implemented endpoints:
+// - HandleDashboard() - Main web UI
+// - HandleGetTasks() - JSON endpoint for tasks
+// - HandleGetBoards() - JSON endpoint for Trello boards
+// - HandleGetNotes() - JSON endpoint for Obsidian notes
+// - HandleGetMeals() - JSON endpoint for meals
+// - HandleRefresh() - Force cache refresh
+// - HandleAISnapshot() - AI-optimized endpoint with auth
+```
+
+### Database Operations
+- **Batch inserts**: Use transactions for saving multiple items
+- **Automatic timestamps**: `updated_at` set via `CURRENT_TIMESTAMP`
+- **JSON encoding**: Arrays (labels, tags) stored as JSON strings
+- **Ordering**: Tasks by completion status, due date, priority; Notes by modification time; Meals by date and meal type
+
+### Error Handling Philosophy
+- **Partial data is better than no data**: If Todoist fails but Obsidian succeeds, show tasks with error message
+- **Cache as fallback**: If API call fails and cache exists (even if stale), use cached data
+- **Graceful degradation**: Skip unavailable services rather than failing completely
+- **User-visible errors**: Store error messages in `DashboardData.Errors` for display
+
+## Development Status
+
+### ✅ Phase 1 Complete
+All core features implemented and tested:
+- ✅ Trello API client (PRIMARY feature - GetBoards, GetCards, GetBoardsWithCards)
+- ✅ All API clients (Todoist, Obsidian, PlanToEat)
+- ✅ Complete handler implementation (web + JSON endpoints)
+- ✅ Frontend with Trello prominence (mobile-responsive, auto-refresh)
+- ✅ Unit tests (5 tests in handlers_test.go)
+- ✅ Acceptance tests (4 test suites in test/acceptance_test.go)
+- ✅ AI agent endpoint with Bearer token auth
+- ✅ Binary builds successfully (17MB)
+- ✅ All 9 tests passing
+
+### Statistics
+- **Binary size:** 17MB
+- **Code:** 2,667 lines
+- **Dependencies:** chi router, sqlite3, Go 1.21+
+- **Tests:** 5 unit tests, 4 acceptance tests (9/9 passing)
+
+### Phase 2 Ideas (Future)
+Write operations:
+- Create Todoist tasks via web UI and AI endpoint
+- Mark tasks complete
+- Create Trello cards
+- Create Obsidian notes
+
+Enhancements:
+- Unified search across all data sources
+- Daily digest view
+- PWA support
+- Rate limiting for AI endpoint
+
+## AI Agent Access
+
+**NEW:** The dashboard now has a dedicated API endpoint optimized for AI agents like Claude.
+
+### Quick Start
+1. Generate API key: `openssl rand -hex 32`
+2. Add to `.env`: `AI_AGENT_API_KEY=your_key_here`
+3. Restart server
+4. Endpoint: `GET /api/claude/snapshot`
+5. Auth: `Authorization: Bearer your_key_here`
+
+### Response Format
+Optimized JSON with:
+- `tasks`: today, overdue, next_7_days
+- `meals`: today, next_7_days
+- `notes`: 10 most recent (150 char previews)
+- `trello_boards`: all boards with cards
+
+### Implementation
+- Middleware: `internal/middleware/ai_auth.go` - Bearer token validation
+- Handler: `internal/handlers/ai_handlers.go` - `/api/claude/snapshot`
+- Uses existing cache (5min TTL)
+- Response size: <100KB
+
+See `AI_AGENT_SETUP.md` for full documentation.
+
+## Important Notes
+
+- **No user authentication**: Single-user application, no auth needed (except AI endpoint)
+- **Trello is PRIMARY**: The most heavily used feature - fully implemented and tested
+- **Trello auth**: Requires both API key AND token as query parameters (different from Todoist/PlanToEat Bearer token pattern)
+- **API rate limits**: Respected via caching (5min default), no aggressive polling
+- **Obsidian performance**: Limited file scanning (max 20 files, ~500 chars per note) to avoid slowdowns on large vaults
+- **Router**: Uses chi for HTTP routing with Logger, Recoverer, and 60s timeout middleware
+- **Graceful shutdown**: Signal handling implemented in main.go
+- **Testing**: Interface-based design allows full mocking of API clients
+- **AI Agent**: Bearer token authentication for /api/claude/snapshot endpoint
+
+## Testing
+
+All tests passing (9/9):
+
+**Unit Tests** (`internal/handlers/handlers_test.go`):
+- TestHandleGetTasks
+- TestHandleGetBoards
+- TestHandleRefresh
+- TestHandleGetNotes
+- TestHandleGetMeals
+
+**Acceptance Tests** (`test/acceptance_test.go`):
+- TestFullWorkflow - Complete dashboard fetch and cache
+- TestCaching - Cache TTL and invalidation
+- TestErrorHandling - Graceful degradation
+- TestConcurrentRequests - Race condition testing
+
+Run with: `go test ./...`
+
+## Troubleshooting
+
+**Import errors**: Run `go mod tidy` to resolve missing dependencies (chi router, sqlite3 driver)
+
+**Database locked**: Only one app instance can run at a time with SQLite
+
+**API errors**: Check `.env` file has correct API keys; verify keys in respective service dashboards
+- Todoist: https://todoist.com/app/settings/integrations
+- Trello: https://trello.com/power-ups/admin (create Power-Up, get Key and Token from API Key tab)
+
+**Tests failing**: Ensure you're in project root when running tests (migrations need to be found)