Skip to content

CreatorTrack, Notion-Parity Audit (2026-07-01)

URL: https://mkdocs.justinsforge.com/memory/plans/creatortrack-notion-parity-audit-2026-07-01/

Five parallel read-only agents audited /home/justinwieb/forge-suite (editor, database engine, shell/nav, API/data layer, polish sweep). Verdict: the foundation is real, not fake. RLS discipline is solid (every mutation through asUser(), DB-backed sessions, cycle guards, ON CONFLICT idempotency). The editor and table view are genuinely deep. The "rushed" feel comes from three things: a save path you cannot trust (silent failures), missing muscle-memory features (undo, search, multi-select), and UI that advertises features that do not exist (dead buttons, shortcut labels with no handlers).

Tier 1, trust and data safety (fix first)

Issue Evidence Fix
Fire-and-forget saves: block edits persist with no error handling, no rollback; network failure = silent data loss BlockList.tsx:289,350,530; optimistic setList before persist Central mutation helper with retry + error toast + rollback; surface the existing Saving/Saved indicator on failure
Silent JSON/error swallowing across API: .catch(() => ({})) turns malformed requests into empty bodies; UI-side .catch(() => {}) everywhere api/block/route.ts:97, block/[id]/route.ts:64, workspace/switch, workspace/update; ShareMenu.tsx:33, PageActionsMenu.tsx:53,76,83 Parse failures return 400 + log; violates fail-loud doctrine
Date.now() block ordering collides within the same millisecond; drag persists integer positions client-side api/block/route.ts:23, BlockList.tsx:325,421; lib/mutations.ts:41, node-actions.ts:50 max(position)+1 in-transaction or fractional keys
Non-atomic reorders: reorderSiblings/reorderFavorites/reorderProps loop N UPDATEs; move-then-reorder is two client fetches, can half-apply lib/node-actions.ts:97-102, lib/mutations.ts:212-217 Single UPDATE with CASE or unnest, one transaction
createRow position race: SELECT max then INSERT inside tx, two concurrent creates get same position lib/mutations.ts:99-103 Insert with subquery or advisory lock
No global auth middleware; every route relies on remembering currentUser() app/api/** per-handler checks middleware.ts auth gate on /api/**
allowDangerousEmailAccountLinking: true with email verification deferred auth.ts:27 Acceptable while Justin+Michael only; MUST fix before any external signup
No undo/redo anywhere in the editor BlockList.tsx (no history store) Command-pattern history stack; biggest single trust feature

Tier 2, daily muscle memory (the "feels rushed" layer)

Issue Evidence
Sidebar search icon is a dead click target; no page/full-text search (Ctrl+K palette works but is commands) WorkspaceShell.tsx:75
Keyboard shortcuts displayed but not wired: Ctrl+D, Ctrl+Shift+R, Ctrl+Shift+P, Ctrl+Shift+Enter; toolbar shows Cmd+B/I/U labels PageTree.tsx:295-303, InlineToolbar.tsx:163-165
No multi-block selection, no rich copy/paste (browser default only), no Cmd+A BlockList.tsx
Trash is soft-delete with a sidebar link but no restore UI PageTree.tsx:298, PageActionsMenu.tsx:135
Board view has no kanban card drag between columns; calendar has no reschedule drag database/Views.tsx
No empty states in database views (blank canvas), no error UI on mutation failure (throws), no loading states in IconPicker/icon search DatabasePage context line 94
Zero mobile breakpoints in the suite shell (workspace.css has only prefers-reduced-motion); sidebar never collapses workspace.css:178

Tier 3, parity gaps (known/deferred, sequence them)

  • Formula + rollup: config UI exists, no evaluation engine (lib/prop-types.ts:314-340, values from db.computed with no visible populator)
  • Files property upload + button property automation: stubs gated on the files backend (Cell.tsx:277,291), which is already next on the roadmap (migration 0035 landed)
  • Timeline view absent (DatabaseClient.tsx:32)
  • Relation/person sort on ids not names (Tier 2 comment in prop-types.ts)
  • Chat panel fully stubbed "Coming soon" (ChatPanel.tsx:24,30)
  • Comments, page history/versions, @mentions: absent
  • "Turn into wiki" + "Open in side peek" toast Coming soon in two menus (PageTree.tsx:300,303, PageActionsMenu.tsx:137,140)
  • Deferred blocks: synced_block, video/file/audio (files backend), button (blocks/types.ts:7)
  • Background/highlight color, text alignment in toolbar
  • A11y: SidebarSection dots menu has no onKeyDown (SidebarSection.tsx:73)
  • Progress.tsx:38 still runtime-injects styles (same FOUC class as the PageTree bug fixed today)
  • Server-side filtering/sorting (all client-side today; fine at current scale)
  • Number() NaN coercion in files/footage range parsing (api/files/[id]/route.ts:547, footage/[id]/route.ts:684)
  • Table block: max 4 columns, no row/cell deletion (SpecialBlocks.tsx:151-183); 20k char server truncation is silent (api/block/[id]/route.ts:15)
  • No workspace members/invites UI (switcher + create + rename work)

What is genuinely solid (do not rebuild)

Editor: 19 block types, slash menu, markdown shortcuts, Enter/Backspace split-merge, Tab nesting, drag with droplines. Database: table view near-parity (resize, reorder, grouping, calc footer), 23 property types registered, compound AND/OR filters + multi-sort persisted per view, view CRUD, row-as-page. Shell: Ctrl+K palette, real share/permissions menu, full breadcrumbs, favorites, section customize, workspace switcher, saving indicator. Data layer: RLS via asUser() everywhere, Drizzle types, DB sessions, move-cycle guard, idempotent cell writes. Assets: emoji JSON lazy-loaded, Iconify proxied.

Suggested order of attack

  1. Save-path hardening (error surfacing + rollback + fail-loud API) , makes everything else trustworthy
  2. Undo/redo
  3. Wire the advertised shortcuts + sidebar search (palette already exists to build on)
  4. Ordering fixes (positions, atomic reorder) while traffic is one user
  5. Board/calendar drag + empty/error states + trash restore
  6. Files backend (already roadmap-next), which unblocks files property, media blocks, uploads
  7. Formula/rollup evaluator
  8. Mobile breakpoints, a11y pass, then the deferred surfaces (chat, comments, history)

[Claude Code]