# 2026-01-28 ## Todo App Deployment & Features ### Deployed to Dokploy - **API** (`todo-app-v2`) deployed and running at `https://api.todo.donovankelly.xyz` - Source: raw compose, builds from `https://git.infra.nkode.tech/hammer/todo-app.git` - Compose ID: `e07fMO8TXcHI_SkKqBWrl` - ENV: APP_URL=https://app.todo.donovankelly.xyz (was wrong before, pointed to API) - Hammer API key: stored in Dokploy env as HAMMER_API_KEY - **Frontend** (`todo-app-web`) deployed at `https://app.todo.donovankelly.xyz` - Source: raw compose, builds from `https://git.infra.nkode.tech/hammer/todo-app-web.git` - Compose ID: `ofMFmzQhEYK-3LfH5QmU_` - **DB** (`todo-app-db`) Postgres running on Dokploy - Postgres ID: `WrvHLAc1kaqsrpTaSGOG4` - Not externally exposed (firewall blocks) - Dokploy API: `https://app.dokploy.com`, auth via `X-API-Key` header, key in Bitwarden ("dokploy api key") - Dokploy server: 191.101.0.153 (Hostzinger kvm2), server ID: QppaqcotG-I-6fUYCNolg - Deploy pattern: `compose.deploy` via tRPC API, poll `deployment.allByCompose` for status ### Fixed cross-subdomain auth - BetterAuth cookies were scoped to `api.todo.donovankelly.xyz` only - Added `crossSubDomainCookies` config with domain `.donovankelly.xyz` - Added `https://app.todo.donovankelly.xyz` to trustedOrigins ### Fixed project loading - `getProject` API route had invalid `isArchived` filter on tasks table (column doesn't exist on tasks) - Removed the bad filter, projects load correctly now ### Fixed invite links - APP_URL env was set to API domain, generating wrong invite URLs - Updated to `https://app.todo.donovankelly.xyz` ### User accounts - Donovan's admin account: `donovan@donovankelly.xyz`, creds in BW shared vault "Todo App (donovankelly.xyz)" - Hammer service account: `hammer@donovankelly.xyz`, ID: `1HltUpL3R0qZkVxIu0oQ3UoqBCHuuMpV`, role: service - BetterAuth has `auth.api.setPassword({ body: { userId, newPassword } })` for password resets ### Features implemented (frontend) - **Unit tests:** 60 tests (API client, auth store, tasks store, utils) - **Project creation:** Inline form in sidebar with color picker - **Task assignment:** Assignee selector + avatar display on tasks - **Kanban board:** Board view at `/project/:id/board` with section columns - **Collapsible sidebar:** Toggle to icon-only mode, persists in localStorage - **Task detail panel:** Right slide-over with editable fields (title, description, due date, priority, assignee, project) - **Due date picker:** Fixed broken hidden input, now visible styled input with clear button - **Completed tasks archive:** Collapsible "Completed" section at bottom of views + "Done" column in board - **Project selector in task detail:** Move tasks between projects - **Section management:** Add/rename/delete sections from board view - **Admin: role selector on invites** — pick admin/user when inviting - **Admin: change user roles** — dropdown in users table - **Admin: password reset** — key icon to reset any user's password ### Infrastructure notes - Local Caddy container (`todo-caddy`) on this VPS is unnecessary — domains point to Dokploy - Git remotes: `gitea` for todo-app, `origin` for todo-app-web ### Network App Frontend - Built SPA at `/home/clawdbot/clawd/network-app-web` (Vite + React + TS + Tailwind) - Gitea: `hammer/network-app-web` - Dokploy compose ID: `Sa1LrtH5uu-a7chrtebXb` - Domain: `https://app.donovankelly.xyz` - API at: `https://api.donovankelly.xyz` (compose ID: `UKrNvUyMCdaSWkl6DcAGA`) - DB: `network-app-db` (Postgres, compose ID: `KzFkJETXrW_oMaiPsUb2o`) - Features: Clients CRM, Events tracking, AI email generation, Profile/settings - Pages: Dashboard, Clients list, Client detail, Events, Emails, Settings, Login ### Bitwarden rule - Donovan confirmed: ALWAYS store credentials in Hammer's Credentials org → Default collection - Updated TOOLS.md with org/collection IDs ### Lessons learned - Always create BW items in shared org vault from the start - Dokploy compose services: use `sourceType: raw` with git URL in build context (not `sourceType: git`) - BetterAuth password hashing: don't try to manually hash with bcrypt — use `auth.api.setPassword()` or `auth.api.signUpEmail()` - APP_URL must point to frontend, not API (used for invite link generation) ### Hammer Queue — Task System - **URL:** https://queue.donovankelly.xyz - **API auth:** Bearer token from BW "Hammer Queue (donovankelly.xyz)" → API_BEARER_TOKEN - **Creds saved to:** ~/.clawdbot/.env as HAMMER_QUEUE_URL + HAMMER_QUEUE_TOKEN - **Purpose:** When Donovan asks me to do something, log it here immediately so it survives context compaction - **Active tasks:** "update queue app" (detail panel, webhook integration) - **High priority queued:** That2ndGuy pitch deck, Network App dev - **Lesson:** ALWAYS write tasks to the queue when asked to do something. Don't rely on conversation memory. ### Dokploy API Key Rotated - Donovan added new key to BW "dokploy api key" (64 chars) - Updated ~/.clawdbot/.env with DOKPLOY_API_KEY - Old key was expiring/rotating — new one works ### Hammer Queue — Continued Development (Late Session) #### Dokploy Access - Created Dokploy account: hammer7839283@gmail.com, role: member - Creds in BW: "Dokploy (app.dokploy.com)" in shared org vault - Member role can't access compose services (authorization error) — need admin for full UI access - Dokploy API has NO endpoint to read deployment build logs — logs only via UI WebSocket or SSH - Learned: `deployment.allByCompose` works with API key auth for listing deployments #### Deploy Debugging Saga - 7 consecutive deploy failures, root causes: 1. **Unused `useState` import** in TaskCard.tsx — TypeScript strict mode (`tsc -b`) rejected it, Docker frontend build failed silently 2. **`serial` column type** — `drizzle-kit push` can't add serial to existing table with data. Fixed by using `integer` + app-level sequencing + startup backfill - **Key lesson:** ALWAYS run `bun run build` locally before deploying. A 2-second local build catches what 30 minutes of API spelunking can't. - Created debugging skill at `skills/debugging/SKILL.md` — living document, update with every new lesson #### Features Shipped (HQ-15 completed) - Sequential task IDs: HQ-1, HQ-2, etc. (integer column + backfill on startup) - API resolves tasks by UUID, number, or HQ-N prefix - GET /api/tasks/:id endpoint - Editable task fields in detail panel: click-to-edit title/description, clickable priority/source selectors - Webhook env vars (CLAWDBOT_HOOK_URL, CLAWDBOT_HOOK_TOKEN) deployed to Dokploy compose - Compose file updated to pass webhook vars to backend service #### Queue App Infrastructure - Compose ID: `kBdwrcZodIRyNIvQ-wrzG` - Git remote: `origin` → `https://git.infra.nkode.tech/hammer/hammer-queue.git` - Deploy pattern: push to Gitea → `compose.deploy` via Dokploy API → poll `deployment.allByCompose` - Frontend: Vite + React + TS + Tailwind, builds with `bun run build` (tsc -b && vite build) - Backend: Elysia + Drizzle + Postgres, starts with `bun run db:push && bun run start` #### Task Management Rules (from Donovan) - When asked to do something → add to Hammer Queue immediately (survives context compaction) - If task stalls or stops → mark it as such, move out of active - Don't leave tasks "active" while doing something else - Break large tasks into smaller ones when shipping partial work #### New Tasks Created - HQ-16: Maintain Debugging Skill (living document) - HQ-17: Queue App: Projects with Context (remaining from HQ-15) #### Hammer Queue Connection Info - URL: https://queue.donovankelly.xyz - API auth: Bearer token from BW "Hammer Queue (donovankelly.xyz)" → API_BEARER_TOKEN - Creds in ~/.clawdbot/.env: HAMMER_QUEUE_URL, HAMMER_QUEUE_TOKEN - Also has HAMMER_QUEUE_API_KEY (older, may be redundant)