Skip to content

URL: https://mkdocs.justinsforge.com/memory/general/reference_creatortrack_task_primitives/

CreatorTrack Generic Task Primitives (Workstream A)

Status: DEPLOYED to prod 2026-07-11 (merged to main b34d8e4, plain code merge, no migration; ensureTasksApp seeds props on tasks-app access, ws 90 seeded, other workspaces on-access). Built on branch feat/task-dev-primitives off main b67e7ca. Plan: creatortrack-task-dev-primitives-2026-07-11. Running report: forge/comms/results/creatortrack-task-dev-primitives.md.

Turns CreatorTrack's task layer into a real project/dev tracker WITHOUT ever looking like one. North Star: every primitive reads as sensible for a content creator too (a dev types bug/feature, a creator types Reel/Sponsored; same code, same UI, configured by the user). NEVER a "dev mode", "software" label, or dev-only preset.

What shipped (per commit, on the branch)

Task Commit What
1. Board group-by any field 52850a6 Kanban board groups by Status (default), Priority, or ANY custom SELECT field. Group-by picker in the board header; drag writes the grouped field's value; "No " column for unset. One change = milestones + swimlanes + campaign-columns.
2. Type + Milestone selects 27eaa9f Two idempotent default select props (Type, Milestone), empty-optioned, seeded via ensureTasksApp (lib/system-apps.ts). Not in CORE_TASK_PROPS, so they surface as ordinary editable selects and auto-appear as board/timeline group-by options.
3. External-URL field kind 0d7fc6e The url prop kind now renders as a clickable external link (new tab, rel="noopener noreferrer nofollow", bare-domain coerced to https). components/workspace/database/Cell.tsx UrlCell. Dev links a PR, creator links a published video.
4. Task -> page relation 8548b91 Un-hardwires collection_relations targets to allow standalone PAGE nodes (target_kind:"page" on PropConfig). Seeds a "Related pages" relation prop. Forward direction here; the reverse-direction UI landed in follow-up B.
5. Bulk paste -> tasks 66acfe2 The shared Composer splits a multi-line title into one task per non-empty line (shares the composer chips). Dev pastes a bug list, creator a content-idea dump.
6. Timeline view 9058b6f New shared TimelineView (components/apps/shared/TimelineView.tsx + timeline.css): dated bars on a day axis from start+due/dueEnd, dependency links from the blockedBy relation, optional row grouping by any select-or-status field (reuses Task 1's taskValue/columnKeys/BoardGroupField, exported from ProjectBoardView.tsx). Registered as a tasks view surface (timeline SurfaceViewType) alongside list/calendar/matrix/database/search. Called Timeline, never "gantt", in every user-visible string. Read-only bars in this commit; drag-to-reschedule = follow-up A.
A. Timeline drag-to-reschedule a8527fa Drag a bar body to move both dates, drag an edge handle to resize; single PATCH on mouse-up via the same updateTask write path the board's onMove uses (Start = bar left, Due = bar right).
B. Reverse-relations UI cfbcf78 Closes the Task 4 gap: a page/doc node shows a "Linked tasks" strip of the tasks whose "Related pages" relation points at it. listRelationBacklinks (lib/node-actions.ts) queries collection_relations by toRow; the existing /api/node/[id]/backlinks route now returns { pages, tasks }; LinkedTasksStrip in PageBody.tsx renders it on page/doc nodes.

Key files

  • New: components/apps/shared/TimelineView.tsx, components/apps/shared/timeline.css, app/api/collection/pages/route.ts.
  • Registration: lib/tasks.ts (SurfaceViewType adds timeline; exported SURFACE_VIEW_TYPES as the single source of truth), components/apps/tasks/ViewTabsBar.tsx, components/apps/tasks/TasksClient.tsx, components/apps/tasks/tasks.css.
  • Prop/relation plumbing: lib/system-apps.ts (prop seeds), lib/collection.ts, lib/prop-types.ts, lib/data.ts, app/api/collection/relation/route.ts, components/workspace/database/Cell.tsx, components/apps/tasks/Peek.tsx (PeekPatch widened with start/dueEnd).
  • Root-cause fix folded into commit 9058b6f: the settings PATCH route (app/api/tasks/settings/route.ts) was validating surface view types against its own stale inline list that omitted even database, silently coercing database + timeline to list on save. Now uses the exported SURFACE_VIEW_TYPES.

Merge-day notes

  • No SQL migration. Despite the plan's assumption, the build added NO db/migrations file and did NOT touch db/schema.ts. All new props/relations (Type, Milestone, Related pages, the target_kind relation config) seed idempotently at runtime via ensureTasksApp/ensureProjectsProps (lib/system-apps.ts), the same lazy-backfill path Status/Priority/Tags use. On merge they backfill on next tasks-app touch; nothing manual to run.
  • Merge is a plain code merge to main; the standard CT deploy (which does NOT run migrations) is sufficient.

Dev verification

Verified on a worktree dev server (next dev --webpack, WORKSPACE_DEV_AUTH=1, DB clone ct_feat_task_dev_primitives). Timeline: two ws74 tasks given dates + a blockedBy link render as bars with the dependency arrow drawn between them; group-by Priority splits into HIGH/LOW/NO PRIORITY headers with the cross-group dependency line staying aligned. Drag (follow-up A): a real mouse drag of a bar body persisted the shifted start+due, a right-edge drag persisted a +2-day resize, both via PATCH /api/tasks/{id}. Reverse-relations (follow-up B): linking two tasks to a page shows a "2 linked tasks" strip below the page title with clickable chips.

Gotchas seen (worth reusing): (1) the original :3062 slot server had died and another worktree grabbed the port; confirm the process serving a slot's port actually has that worktree's cwd (readlink /proc/<pid>/cwd) before trusting a runtime check. (2) A page's client fetch (a useEffect strip) can stall on the Next dev server when the page fires many concurrent load-time polls (notifications, etc.) that saturate the browser's 6-per-host connection pool; blocking the noisy polls in the test made it deterministic. It is a dev on-demand-compile artifact, not a bug: a warm prod build resolves the fetch immediately.

Follow-on: work hierarchy Board surface (branch feat/work-hierarchy-dashboard, 2026-07-12)

The task primitives above (board group-by, Type/Milestone selects, Timeline) are extended by the work hierarchy build (NOT yet merged): the Tasks app now has its own Board surface (reusing ProjectBoardView) whose columns are the workspace's real Status prop options exposed as a new taskStatuses field on the /api/tasks aggregate (lib/tasks.ts listTasks) -- the pipeline is data, never hardcoded. The filter bar gains Status + any-custom-field axes (persisted in the tasks_app prefs blob), and the Composer gains a Status quick-add chip. Dragging a board card writes {status} ONLY (the /api/tasks/[id] PATCH done fast-path drops a co-sent status; the server derives done from status). Milestone (a select prop here) now also drives per-project milestone rollups + roadmap markers in the Projects app.