diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-02-07 21:21:53 -1000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-02-07 21:21:53 -1000 |
| commit | 82c2f701823e19e375a8c854181a763a96620234 (patch) | |
| tree | e76947f50bf56562e03461b2bdab1e2b5a25fd1a /DESIGN.md | |
| parent | 6278a82751c720d9c306393fc3dbf3ba484509cf (diff) | |
Update project docs: fix stale references, add missing sections
- CLAUDE.md: fix data sources, add debugging/deploy sections, test checklist
- DESIGN.md: update directory tree, fix h.templates→h.renderer, add endpoints/env vars
- Role files: fix Go version to 1.24, update tool names to Edit/Read/Glob
- scripts/logs: fix CRLF line endings for WSL compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'DESIGN.md')
| -rw-r--r-- | DESIGN.md | 111 |
1 files changed, 73 insertions, 38 deletions
@@ -4,7 +4,7 @@ Task Dashboard is a personal productivity web application that aggregates tasks, meals, calendar events, and shopping lists from multiple external services into a unified, mobile-friendly interface. Built with Go backend, HTMX frontend, Tailwind CSS styling, and SQLite storage. -**Stack:** Go 1.21+ | chi router | HTMX 1.x | Tailwind CSS | SQLite (WAL mode) +**Stack:** Go 1.24 | chi router | HTMX 1.x | Tailwind CSS | SQLite (WAL mode) --- @@ -12,7 +12,7 @@ Task Dashboard is a personal productivity web application that aggregates tasks, The dashboard serves as a **personal consolidation hub** designed to: -1. **Aggregate multiple data sources** into one view (Trello, Todoist, PlanToEat, Google Calendar, Google Tasks) +1. **Aggregate multiple data sources** into one view (Trello, Todoist, PlanToEat, Google Calendar, Google Tasks, user-reported bugs) 2. **Prioritize reliability** over speed - graceful degradation when APIs fail 3. **Support mobile-first usage** - optimized for phone/tablet in-store or on-the-go 4. **Minimize context switching** - complete tasks from any source without opening multiple apps @@ -22,15 +22,15 @@ The dashboard serves as a **personal consolidation hub** designed to: ## Development Workflow -This project uses a **multi-agent development workflow** with three specialized roles that collaborate through shared documents. +This project supports a **multi-agent development workflow** with three specialized roles. The primary workflow is single-agent (Claude Code reading CLAUDE.md + DESIGN.md directly). The role files exist for optional multi-agent use. ### Roles -| Role | Agent | Responsibilities | -|------|-------|------------------| -| **Architect** | Gemini | Plans features, creates issues, writes surgical instructions. Does NOT edit source code. | -| **Implementor** | Claude Code | Executes plans, writes code, runs tests. Updates state after completing work. | -| **Reviewer** | QA Agent | Reviews code quality, runs tests, provides feedback. Does NOT edit source code. | +| Role | Responsibilities | +|------|------------------| +| **Architect** | Plans features, creates issues, writes surgical instructions. Does NOT edit source code. | +| **Implementor** | Executes plans, writes code, runs tests. Updates state after completing work. | +| **Reviewer** | Reviews code quality, runs tests, provides feedback. Does NOT edit source code. | ### Role Definitions @@ -89,7 +89,7 @@ Tasks flow through these states: ``` task-dashboard/ ├── cmd/dashboard/ -│ └── main.go # Application entry point, route registration +│ └── main.go # Entry point, route registration, ldflags ├── internal/ │ ├── api/ # External API clients │ │ ├── interfaces.go # API client contracts (interfaces) @@ -100,40 +100,54 @@ task-dashboard/ │ │ ├── google_calendar.go # Google Calendar integration │ │ └── google_tasks.go # Google Tasks integration │ ├── auth/ -│ │ ├── auth.go # Authentication service (bcrypt) -│ │ ├── handlers.go # Login/logout handlers +│ │ ├── auth.go # Authentication service (bcrypt + WebAuthn) +│ │ ├── handlers.go # Login/logout/passkey handlers │ │ └── middleware.go # Session + CSRF protection │ ├── config/ │ │ ├── config.go # Environment configuration │ │ ├── constants.go # App constants (timeouts, limits) │ │ └── timezone.go # Display timezone helpers │ ├── handlers/ -│ │ ├── handlers.go # Main HTTP handlers (~2000 LOC) -│ │ ├── response.go # JSON/HTML response utilities -│ │ ├── cache.go # Generic cache fetcher pattern -│ │ ├── atoms.go # Unified task aggregation +│ │ ├── handlers.go # Main HTTP handlers + aggregation +│ │ ├── settings.go # Settings page handlers +│ │ ├── shopping.go # Shopping tab + mode handlers +│ │ ├── agent.go # Agent auth + context API +│ │ ├── websocket.go # WebSocket notification hub │ │ ├── timeline.go # Timeline view handler -│ │ └── timeline_logic.go # Timeline data processing +│ │ ├── timeline_logic.go # Timeline data processing +│ │ ├── atoms.go # Unified task aggregation +│ │ ├── cache.go # Generic cache fetcher pattern +│ │ ├── helpers.go # Form parsing helpers +│ │ ├── renderer.go # Template renderer interface +│ │ └── response.go # JSON/HTML response utilities │ ├── middleware/ │ │ └── security.go # Security headers + rate limiting │ ├── models/ -│ │ ├── types.go # Data models (Task, Card, Meal, etc.) +│ │ ├── types.go # Data models (Task, Card, Meal, Agent, etc.) │ │ ├── atom.go # Unified Atom model + converters │ │ └── timeline.go # TimelineItem + DaySection models │ └── store/ -│ └── sqlite.go # SQLite database layer (~700 LOC) -├── migrations/ # SQL migration files (001-009) +│ └── sqlite.go # SQLite database layer +├── migrations/ # SQL migration files (001-014) +├── scripts/ +│ ├── bugs # List bugs from production DB +│ ├── logs # Fetch production journalctl +│ └── resolve-bug # Resolve a production bug ├── web/ │ ├── templates/ │ │ ├── index.html # Main dashboard shell │ │ ├── login.html # Authentication page +│ │ ├── settings.html # Settings + passkeys page │ │ ├── conditions.html # Standalone live feeds page │ │ ├── shopping-mode.html # Full-screen shopping mode -│ │ └── partials/ # HTMX partial templates +│ │ ├── passkeys_list.html # Passkeys list partial +│ │ ├── agent-*.html # Agent auth flow pages (4 files) +│ │ └── partials/ # HTMX partial templates (12 files) │ └── static/ │ ├── css/input.css # Tailwind source │ ├── css/output.css # Compiled CSS -│ └── js/app.js # Client-side logic +│ └── js/app.js # Client-side logic + WebSocket +├── deploy.sh # Build + deploy script (ldflags injection) └── tailwind.config.js ``` @@ -524,7 +538,7 @@ func (h *Handler) HandleNewFeature(w http.ResponseWriter, r *http.Request) { _ = h.store.SaveResult(result) // 5. Respond - HTMLResponse(w, h.templates, "partial-name", result) + HTMLResponse(w, h.renderer, "partial-name", result) } ``` @@ -576,10 +590,10 @@ r.Post("/newfeature/action", h.HandleNewAction) **Example:** ```go // Standalone page - use filename -h.templates.ExecuteTemplate(w, "shopping-mode.html", data) +h.renderer.Render(w, "shopping-mode.html", data) // Partial - use define name -HTMLResponse(w, h.templates, "shopping-tab", data) +HTMLResponse(w, h.renderer, "shopping-tab", data) ``` ### HTMX Patterns @@ -641,21 +655,25 @@ func TestHandler_HandleDashboard(t *testing.T) { ### Debugging Tips -1. **Check logs:** All errors logged with `log.Printf` -2. **Cache issues:** Check `cache_metadata` table for stale timestamps -3. **API failures:** Look for `"Warning:"` or `"ERROR:"` prefixes -4. **Template errors:** Check for `html/template: "name" is undefined` -5. **HTMX issues:** Browser DevTools Network tab shows all requests +1. **Production logs:** `bash scripts/logs -n 200 2>&1 | grep -i error` +2. **Production bugs:** `bash scripts/bugs` to list, `bash scripts/resolve-bug <id>` to close +3. **Cache issues:** Check `cache_metadata` table for stale timestamps +4. **API failures:** Look for `"Warning:"` or `"ERROR:"` prefixes in logs +5. **Template errors:** Check for `html/template: "name" is undefined` +6. **HTMX issues:** Browser DevTools Network tab shows all requests +7. **WebAuthn issues:** Check for "WebAuthn initialized" in startup logs; requires `WEBAUTHN_RP_ID` + `WEBAUTHN_ORIGIN` env vars ### Files You'll Modify Most | Task | Primary Files | |------|--------------| -| New feature | `handlers.go`, `main.go`, new template | -| Bug fix | Usually `handlers.go` or specific API client | +| New feature | `handlers.go` or new handler file, `main.go`, new template | +| Bug fix | Relevant handler file or API client | | UI change | Template in `partials/`, maybe `input.css` | | API integration | New file in `internal/api/`, update `interfaces.go` | -| Database change | New migration, update `sqlite.go` | +| Database change | New migration in `migrations/`, update `sqlite.go` | +| Settings | `settings.go`, `settings.html` | +| Shopping | `shopping.go`, `shopping-tab.html` or `shopping-mode.html` | ### Configuration Reference @@ -668,13 +686,19 @@ func TestHandler_HandleDashboard(t *testing.T) { **Optional:** - `DEFAULT_USER` (default: "admin") - `PLANTOEAT_SESSION` - PlanToEat session cookie +- `PLANTOEAT_API_KEY` - PlanToEat API key - `GOOGLE_CREDENTIALS_FILE` - OAuth credentials JSON path -- `GOOGLE_CALENDAR_ID` (default: "primary") +- `GOOGLE_CALENDAR_ID` (default: "primary") — comma-separated for multiple - `GOOGLE_TASKS_LIST_ID` (default: "@default") +- `WEBAUTHN_RP_ID` - Passkey Relying Party ID (e.g., "doot.terst.org") +- `WEBAUTHN_ORIGIN` - Passkey expected origin (e.g., "https://doot.terst.org") - `DATABASE_PATH` (default: "./dashboard.db") - `PORT` (default: "8080") - `CACHE_TTL_MINUTES` (default: 5) - `TIMEZONE` (default: "Pacific/Honolulu") +- `TEMPLATE_DIR` (default: "web/templates") +- `STATIC_DIR` (default: "web/static") +- `MIGRATION_DIR` (default: "migrations") - `DEBUG` (default: false) ### Common Mistakes to Avoid @@ -745,7 +769,7 @@ Short summary (50 chars or less) Optional longer description explaining the why, not the what. Reference bug numbers with #N format. -Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> +Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> ``` **If history diverges:** Use `git pull --rebase=false` to merge, never force push. @@ -787,8 +811,11 @@ Bugs appear as atoms in the Tasks view (🐛 icon) until resolved. | Component | Test File | |-----------|-----------| | Store methods | `internal/store/sqlite_test.go` | -| Handlers | `internal/handlers/*_test.go` | +| Handlers | `internal/handlers/handlers_test.go` | +| Timeline logic | `internal/handlers/timeline_logic_test.go` | +| Agent handlers | `internal/handlers/agent_test.go` | | API clients | `internal/api/*_test.go` | +| Auth | `internal/auth/*_test.go` | | Integration | `test/acceptance_test.go` | **Running tests:** @@ -915,11 +942,16 @@ npx tailwindcss -i web/static/css/input.css -o web/static/css/output.css --watch | GET | `/` | Main dashboard | | GET | `/tabs/timeline` | Timeline partial | | GET | `/tabs/tasks` | Tasks partial | +| GET | `/tabs/planning` | Planning partial | +| GET | `/tabs/meals` | Meals partial | | GET | `/tabs/shopping` | Shopping partial | +| GET | `/tabs/conditions` | Conditions partial | | GET | `/conditions` | Live feeds page (public) | -| POST | `/complete-atom` | Complete task/card | +| POST | `/complete-atom` | Complete task/card/bug | | POST | `/uncomplete-atom` | Reopen task/card | | POST | `/unified-add` | Quick add task | +| GET | `/bugs` | List bug reports | +| POST | `/bugs` | Submit bug report | | POST | `/shopping/add` | Add shopping item | | GET | `/shopping/mode/{store}` | Shopping mode view | | POST | `/shopping/mode/{store}/toggle` | Toggle shopping item | @@ -927,6 +959,9 @@ npx tailwindcss -i web/static/css/input.css -o web/static/css/output.css --watch | GET | `/settings` | Settings page | | POST | `/settings/features` | Create feature toggle | | POST | `/settings/features/toggle` | Toggle feature on/off | +| GET | `/settings/passkeys` | List passkeys (requires WebAuthn) | +| POST | `/passkeys/register/begin` | Start passkey registration | +| POST | `/passkeys/register/finish` | Complete passkey registration | | GET | `/ws/notifications` | WebSocket for agent notifications | | POST | `/agent/auth/request` | Agent requests access | | GET | `/agent/auth/poll` | Agent polls for approval | @@ -945,8 +980,8 @@ func (h *Handler) HandleName(w http.ResponseWriter, r *http.Request) { ### Response Helpers ```go -JSONResponse(w, data) // 200 + JSON +JSONResponse(w, data) // 200 + JSON + no-cache JSONError(w, status, "message", err) // Error + log -HTMLResponse(w, h.templates, "name", data) // Partial render +HTMLResponse(w, h.renderer, "name", data) // Partial render + no-cache HTMLString(w, "<html>...</html>") // Raw HTML ``` |
