# 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)