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¶
- Save-path hardening (error surfacing + rollback + fail-loud API) , makes everything else trustworthy
- Undo/redo
- Wire the advertised shortcuts + sidebar search (palette already exists to build on)
- Ordering fixes (positions, atomic reorder) while traffic is one user
- Board/calendar drag + empty/error states + trash restore
- Files backend (already roadmap-next), which unblocks files property, media blocks, uploads
- Formula/rollup evaluator
- Mobile breakpoints, a11y pass, then the deferred surfaces (chat, comments, history)
[Claude Code]