Project Hub with Kanban board for task/idea tracking
Go to file
2026-02-27 15:11:05 -06:00
comps Add sprint support to data model and API 2026-02-19 17:21:21 -06:00
docs Signed-off-by: Max <ai-agent@topdoglabs.com> 2026-02-24 17:53:20 -06:00
public Initial commit from Create Next App 2026-02-17 22:55:29 -06:00
screenshots Add sorting to main Kanban board in page.tsx 2026-02-21 22:22:47 -06:00
scripts Add --no-color flag to task.sh CLI for machine-readable output 2026-02-26 19:53:35 -06:00
src Signed-off-by: OpenClaw Bot <ai-agent@topdoglabs.com> 2026-02-26 13:22:29 -06:00
supabase Signed-off-by: Max <ai-agent@topdoglabs.com> 2026-02-25 13:59:10 -06:00
.env.example Signed-off-by: Max <ai-agent@topdoglabs.com> 2026-02-24 20:21:54 -06:00
.gitignore Signed-off-by: Max <ai-agent@topdoglabs.com> 2026-02-24 20:21:54 -06:00
AGENTS.md Signed-off-by: Max <ai-agent@topdoglabs.com> 2026-02-24 17:56:25 -06:00
CLI_STANDARD.md Signed-off-by: Max <ai-agent@topdoglabs.com> 2026-02-24 17:55:38 -06:00
docker-compose.yml Signed-off-by: OpenClaw Bot <ai-agent@topdoglabs.com> 2026-02-27 15:11:05 -06:00
Dockerfile Signed-off-by: OpenClaw Bot <ai-agent@topdoglabs.com> 2026-02-27 14:51:00 -06:00
eslint.config.mjs Initial commit from Create Next App 2026-02-17 22:55:29 -06:00
next.config.js Signed-off-by: Max <ai-agent@topdoglabs.com> 2026-02-22 14:23:22 -06:00
next.config.ts Signed-off-by: Max <ai-agent@topdoglabs.com> 2026-02-22 14:23:22 -06:00
package-lock.json Signed-off-by: Max <ai-agent@topdoglabs.com> 2026-02-22 14:23:22 -06:00
package.json Signed-off-by: Max <ai-agent@topdoglabs.com> 2026-02-24 17:48:19 -06:00
postcss.config.mjs Initial commit from Create Next App 2026-02-17 22:55:29 -06:00
README.md Signed-off-by: Max <ai-agent@topdoglabs.com> 2026-02-25 15:40:15 -06:00
SEARCH_FEATURE.md feat: Add machine token auth for cron automation 2026-02-26 08:25:29 -06:00
SUPABASE_SETUP.md Signed-off-by: Max <ai-agent@topdoglabs.com> 2026-02-22 18:07:15 -06:00
tsconfig.json Complete rewrite: Project Hub with Kanban board and threaded notes 2026-02-18 09:32:47 -06:00

Gantt Board

Task and sprint board built with Next.js + Zustand and Supabase-backed API persistence.

Current Product Behavior

Feb 20, 2026 updates

  • Added task attachments with Supabase persistence.
  • Added URL-based task detail pages (/tasks/{taskId}) so tasks can be opened/shared by link.
  • Replaced flat notes/comments with threaded comments.
  • Added unlimited nested replies (reply to comment, reply to reply, no depth limit).
  • Updated UI wording from "notes" to "comments".
  • Improved attachment opening/rendering by coercing MIME types (including .md as text) and using blob URLs for reliable in-browser viewing.
  • Added lightweight collaborator identity tracking for task/comment authorship.

Feb 21, 2026 updates

  • Stabilized auth and settings flows with Supabase Auth credentials.
  • Login/password validation now uses Supabase Auth credentials.
  • Reset password flow no longer depends on public.users.password_hash.
  • Settings API response handling was hardened to avoid client script errors.
  • Avatar preset key collision warning in settings was fixed.

Feb 22, 2026 updates

  • Fixed sprint date timezone drift (for example 2026-02-22 rendering as 2/21 in US time zones).
  • Standardized sprint date parsing across Kanban, Backlog, Sprint Board, Archive, and task detail sprint pickers.
  • POST /api/sprints and PATCH /api/sprints now normalize startDate/endDate to YYYY-MM-DD before writing to Supabase.

Feb 23, 2026 updates

  • Removed non-live fallback data paths from the task store; board data now comes from Supabase-backed APIs only.
  • Removed legacy schema expectations from API code and docs (legacy_id, meta dependency, non-existent task columns).
  • Task detail now includes explicit Project + Sprint selection; sprint selection no longer rewrites task projectId.
  • API validation now accepts UUID-shaped IDs used by existing data and returns clearer error payloads for failed writes.

Feb 24, 2026 updates

  • Standardized CLI tools to API passthrough mode only (no direct DB logic in scripts).
  • Consolidated shared CLI transport into scripts/lib/api_client.sh.
  • Added refactor safety tests:
    • sprint selection unit tests
    • mocked CLI API-contract tests across task/project/sprint/auth/debug command paths

Feb 25, 2026 updates

  • Added a dedicated /sprints page (previously missing, caused route 404).
  • Added sprint management UI on /sprints to view all sprints and perform create/edit/delete actions.
  • Added a dedicated /tasks list page with URL-based filtering and scope controls.
  • Removed sprint-to-project coupling across app/API/CLI. Tasks remain project-scoped; sprints are now global.
  • Added DB migration script to drop sprints.project_id: supabase/remove_sprint_project_id.sql.

Sprint date semantics (important)

  • Sprint dates are treated as local calendar-day boundaries:
    • startDate means local 12:00:00 AM of that date.
    • endDate means local 11:59:59.999 PM of that date.
  • Supabase stores sprint dates as SQL DATE (YYYY-MM-DD) in sprints.start_date and sprints.end_date.
  • API contract for /api/sprints:
    • Accepts date strings with a YYYY-MM-DD prefix (YYYY-MM-DD or ISO timestamp).
    • Normalizes and persists only the date part (YYYY-MM-DD).
    • PATCH returns 400 for invalid startDate/endDate format.
    • Example request payloads:
    • POST /api/sprints
      • { "name": "Sprint 1", "startDate": "2026-02-16", "endDate": "2026-02-22", "status": "active" }
    • PATCH /api/sprints
      • { "id": "<sprint-id>", "startDate": "2026-02-16T00:00:00.000Z", "endDate": "2026-02-22T23:59:59.999Z" }
      • persisted as start_date = '2026-02-16', end_date = '2026-02-22'
  • Do not use new Date("YYYY-MM-DD") for sprint display logic. Use shared helpers:
    • parseSprintStart(...)
    • parseSprintEnd(...)
    • toLocalDateInputValue(...)

Data model and status rules

  • Tasks use labels (tags: string[]) and can have multiple labels.
  • Tasks support attachments (attachments: TaskAttachment[]).
  • Tasks persist identity references via createdById, updatedById, and assigneeId.
  • Display fields (createdByName, updatedByName, assigneeName, avatar/email) are resolved from users data in API/UI, not stored as separate task table columns.
  • There is no active backlog status in workflow logic.
  • A task is considered in Backlog when sprintId is empty.
  • Current status values:
    • open
    • todo
    • blocked
    • in-progress
    • review
    • validate
    • archived
    • canceled
    • done
  • New tasks default to status: open.

Authentication and sessions

  • Added account-based authentication with:
    • POST /api/auth/register
    • POST /api/auth/login
    • POST /api/auth/logout
    • GET /api/auth/session
  • Added a dedicated login/register screen at /login.
  • Added account settings at /settings for authenticated users.
  • Main board (/) and task detail pages (/tasks/{taskId}) require an authenticated session.
  • Main board and task detail headers include quick access to Settings and Logout.
  • API routes now enforce auth on task read/write/delete (/api/tasks returns 401 when unauthenticated).
  • Added PATCH /api/auth/account to update profile and password for the current user.
  • Session cookie: gantt_session (HTTP-only, same-site lax, secure in production).
  • Optional machine-to-machine auth for API routes:
    • Set GANTT_MACHINE_TOKEN in server env.
    • Send either Authorization: Bearer <token> or x-gantt-machine-token: <token>.
    • Optional identity fields: GANTT_MACHINE_USER_ID, GANTT_MACHINE_USER_NAME, GANTT_MACHINE_USER_EMAIL.
  • Added Remember me in auth forms:
    • Checked: persistent 30-day cookie/session.
    • Unchecked: browser-session cookie (clears on browser close), with server-side short-session expiry.
  • Forgot-password currently uses a dev reset-link flow unless an external email provider is integrated.
  • Task/comment authorship now uses authenticated user identity.
  • Added GET /api/auth/users so task forms can load assignable users.
  • User records now include optional avatarUrl profile photos.

Task assignment

  • You can assign or unassign tasks in:
    • New Task modal
    • Task detail popup on board
    • URL task detail page (/tasks/{taskId})
  • New tasks default to the current signed-in user as assignee.
  • Kanban and Backlog cards show a visible assignee avatar/initial pill.
  • When someone else updates status (for example closes a task), updater fields still track who made that change.

Profile photos and account settings

  • Account Settings (/settings) has separate save actions:
    • Save Profile for name/email/photo
    • Update Password for password-only changes
  • Profile photos can be uploaded/removed in settings.
  • Users without uploaded photos get a generated default avatar (unique by user seed).
  • Settings also provides multiple preset avatar choices.
  • Profile photos appear in:
    • Board/task header identity chips
    • Assignee pills on Kanban and Backlog
    • Threaded comment author avatars
    • Creator/updater identity rows on task detail views
  • Avatar updates persist in Supabase profile tables and propagate through session/user APIs.

Labels

  • Labels are independent of project/sprint selection.
  • You can add/remove labels inline in:
    • New Task modal
    • Task Detail page
  • Label entry supports:
    • Enter/comma to add
    • Existing-label suggestions
    • Quick-add chips
    • Case-insensitive de-duplication

Task detail pages

  • Clicking a task from Kanban or Backlog opens a dedicated route:
    • /tasks/{taskId}
  • Task detail is no longer popup-only behavior.
  • Each task now has a shareable deep link.
  • Task detail includes explicit Project and Sprint dropdowns.

Task list route

  • Added a dedicated task list route at /tasks.
  • Supported query params:
    • scope=active-sprint|all (default: all)
    • status=<comma-separated status list> (for example in-progress,review)
    • priority=<comma-separated priority list> (for example urgent,high)
  • Unknown status/priority tokens are ignored.
  • Filtering is client-side against the synced task dataset.
  • Results are sorted by updatedAt descending.

Attachments

  • Task detail page supports adding multiple attachments per task.
  • Attachments are stored with each task in Supabase and survive refresh/restart.
  • Attachment UI supports:
    • Upload multiple files
    • Open/view file
    • Markdown (.md) preview rendering in browser tab
    • Text/code preview for common file types including iOS project/code files (.swift, .plist, .pbxproj, .storyboard, .xib, .xcconfig, .entitlements)
    • Syntax-highlighted source rendering (highlight.js) with copy-source action
    • CSV table preview and sandboxed HTML preview with source view
    • Download file
    • Remove attachment

Threaded comments

  • Comments are now threaded, not flat.
  • You can:
    • Add top-level comments
    • Reply to any comment
    • Reply to replies recursively (unlimited depth)
    • Delete any comment or reply from the thread
  • Thread data is persisted in Supabase through the existing /api/tasks sync flow.

Current persisted comment shape:

{
  "id": "string",
  "text": "string",
  "createdAt": "2026-02-23T19:00:00.000Z",
  "commentAuthorId": "user-uuid-or-assistant",
  "replies": []
}
  • commentAuthorId is required.
  • Legacy author objects are not supported by the UI parser.

Backlog drag and drop

Backlog view supports moving tasks between:

  • Current sprint
  • Other sprint sections
  • Backlog

Status behavior on drop:

  • Drop into any sprint section: status -> open
  • Drop into backlog section: status -> open
  • sprintId is set/cleared based on destination

Changes persist through store sync to Supabase.

Kanban drag and drop

Kanban supports drag by visible left handle on each task card.

Columns:

  • To Do contains statuses: open, todo
  • In Progress contains statuses: blocked, in-progress, review, validate
  • Done contains statuses: archived, canceled, done

Drop behavior:

  • Drop on column body: applies that column's default status
    • To Do -> open
    • In Progress -> in-progress
    • Done -> done
  • Drop on status chip target: applies exact status
  • Drop on a task: adopts that task's exact status

During drag, the active target column shows expanded status drop zones for clarity.

Layout

  • Left sidebar cards (Current Sprint and Labels quick view) were removed.
  • Main board now uses full width for Kanban/Backlog views.

Persistence

  • Client state is managed with Zustand.
  • Persistence is handled through Supabase-backed API routes:
    • /api/tasks
    • /api/projects
    • /api/sprints
  • No local task/project/sprint fallback dataset is used.
  • API reads/writes Supabase tables only.

Run locally

npm install
npm run dev

Open http://localhost:3000. Task URLs follow http://localhost:3000/tasks/{taskId}.

Scripts

npm run dev
npm run build
npm run start
npm run lint

CLI Tools for AI Access

Located in scripts/ directory. These allow programmatic access without browser automation.

# Full wrapper
./scripts/gantt.sh task list open
./scripts/gantt.sh task create "Fix login issue" todo high p1
./scripts/gantt.sh sprint close <sprint-id>
./scripts/gantt.sh auth session

# Focused helpers
./scripts/task.sh list --json
./scripts/project.sh list --json
./scripts/sprint.sh list --active --json
./scripts/attach-file.sh <task-id> <file-path>
./scripts/view-attachment.sh <task-id> [index]

Architecture: CLI is API passthrough only. Business logic lives in API/server code.

Docs:

  • scripts/README.md (command details and env vars)
  • docs/API_CLI_PASSTHROUGH_PATTERN.md (refactor/architecture standard)

Refactor test suite:

npm run test:refactor

Notes

  • You may see a Next.js warning about multiple lockfiles and inferred workspace root. This is non-blocking for local dev.