Files
clawd/memory/2026-01-28.md

7.7 KiB

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
  • 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 typedrizzle-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: originhttps://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)