From 9fe0998436488537a8a2e8ffeefb0c4424b41c60 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Mon, 12 Jan 2026 09:27:16 -1000 Subject: 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 --- CLAUDE.md | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 CLAUDE.md (limited to 'CLAUDE.md') 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) -- cgit v1.2.3