7.7 KiB
7.7 KiB
2026-01-28
Todo App Deployment & Features
Deployed to Dokploy
- API (
todo-app-v2) deployed and running athttps://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
- Source: raw compose, builds from
- Frontend (
todo-app-web) deployed athttps://app.todo.donovankelly.xyz- Source: raw compose, builds from
https://git.infra.nkode.tech/hammer/todo-app-web.git - Compose ID:
ofMFmzQhEYK-3LfH5QmU_
- Source: raw compose, builds from
- DB (
todo-app-db) Postgres running on Dokploy- Postgres ID:
WrvHLAc1kaqsrpTaSGOG4 - Not externally exposed (firewall blocks)
- Postgres ID:
- Dokploy API:
https://app.dokploy.com, auth viaX-API-Keyheader, key in Bitwarden ("dokploy api key") - Dokploy server: 191.101.0.153 (Hostzinger kvm2), server ID: QppaqcotG-I-6fUYCNolg
- Deploy pattern:
compose.deployvia tRPC API, polldeployment.allByComposefor status
Fixed cross-subdomain auth
- BetterAuth cookies were scoped to
api.todo.donovankelly.xyzonly - Added
crossSubDomainCookiesconfig with domain.donovankelly.xyz - Added
https://app.todo.donovankelly.xyzto trustedOrigins
Fixed project loading
getProjectAPI route had invalidisArchivedfilter 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/boardwith 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:
giteafor todo-app,originfor 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: rawwith git URL in build context (notsourceType: git) - BetterAuth password hashing: don't try to manually hash with bcrypt — use
auth.api.setPassword()orauth.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.allByComposeworks with API key auth for listing deployments
Deploy Debugging Saga
- 7 consecutive deploy failures, root causes:
- Unused
useStateimport in TaskCard.tsx — TypeScript strict mode (tsc -b) rejected it, Docker frontend build failed silently serialcolumn type —drizzle-kit pushcan't add serial to existing table with data. Fixed by usinginteger+ app-level sequencing + startup backfill
- Unused
- Key lesson: ALWAYS run
bun run buildlocally 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.deployvia Dokploy API → polldeployment.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)