Project Hub with Kanban board for task/idea tracking
- Add api_call_machine() function for GANTT_MACHINE_TOKEN auth - Update api_call() to use machine token when available - Same pattern applied to both api_client.sh and gantt.sh - Allows cron jobs to authenticate without cookie-based login - No breaking changes - cookie auth still works for interactive use |
||
|---|---|---|
| comps | ||
| docs | ||
| public | ||
| screenshots | ||
| scripts | ||
| src | ||
| supabase | ||
| .env.example | ||
| .gitignore | ||
| AGENTS.md | ||
| CLI_STANDARD.md | ||
| eslint.config.mjs | ||
| next.config.js | ||
| next.config.ts | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| README.md | ||
| SEARCH_FEATURE.md | ||
| SUPABASE_SETUP.md | ||
| tsconfig.json | ||
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
.mdas 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-22rendering as2/21in US time zones). - Standardized sprint date parsing across Kanban, Backlog, Sprint Board, Archive, and task detail sprint pickers.
POST /api/sprintsandPATCH /api/sprintsnow normalizestartDate/endDatetoYYYY-MM-DDbefore 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,metadependency, 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
/sprintspage (previously missing, caused route 404). - Added sprint management UI on
/sprintsto view all sprints and perform create/edit/delete actions. - Added a dedicated
/taskslist 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:
startDatemeans local12:00:00 AMof that date.endDatemeans local11:59:59.999 PMof that date.
- Supabase stores sprint dates as SQL
DATE(YYYY-MM-DD) insprints.start_dateandsprints.end_date. - API contract for
/api/sprints:- Accepts date strings with a
YYYY-MM-DDprefix (YYYY-MM-DDor ISO timestamp). - Normalizes and persists only the date part (
YYYY-MM-DD). PATCHreturns400for invalidstartDate/endDateformat.- 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'
- Accepts date strings with a
- 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, andassigneeId. - Display fields (
createdByName,updatedByName,assigneeName, avatar/email) are resolved fromusersdata in API/UI, not stored as separate task table columns. - There is no active
backlogstatus in workflow logic. - A task is considered in Backlog when
sprintIdis empty. - Current status values:
opentodoblockedin-progressreviewvalidatearchivedcanceleddone
- New tasks default to
status: open.
Authentication and sessions
- Added account-based authentication with:
POST /api/auth/registerPOST /api/auth/loginPOST /api/auth/logoutGET /api/auth/session
- Added a dedicated login/register screen at
/login. - Added account settings at
/settingsfor 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/tasksreturns401when unauthenticated). - Added
PATCH /api/auth/accountto 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_TOKENin server env. - Send either
Authorization: Bearer <token>orx-gantt-machine-token: <token>. - Optional identity fields:
GANTT_MACHINE_USER_ID,GANTT_MACHINE_USER_NAME,GANTT_MACHINE_USER_EMAIL.
- Set
- Added
Remember mein 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/usersso task forms can load assignable users. - User records now include optional
avatarUrlprofile 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 Profilefor name/email/photoUpdate Passwordfor 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 examplein-progress,review)priority=<comma-separated priority list>(for exampleurgent,high)
- Unknown status/priority tokens are ignored.
- Filtering is client-side against the synced task dataset.
- Results are sorted by
updatedAtdescending.
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/taskssync flow.
Current persisted comment shape:
{
"id": "string",
"text": "string",
"createdAt": "2026-02-23T19:00:00.000Z",
"commentAuthorId": "user-uuid-or-assistant",
"replies": []
}
commentAuthorIdis required.- Legacy
authorobjects 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 sprintIdis 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 Docontains statuses:open,todoIn Progresscontains statuses:blocked,in-progress,review,validateDonecontains statuses:archived,canceled,done
Drop behavior:
- Drop on column body: applies that column's default status
To Do->openIn Progress->in-progressDone->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.