docs/solutions/performance-issues/2026-04-05-block-discussion-should-build-a-shared-annotation-index-once-per-editor-version.md
block-discussion.tsx and block-suggestion.tsx were doing too much work at render time.
The discussion card needed one core answer: which top-level block owns a given comment or suggestion thread. The old implementation answered that indirectly:
uniquePathMap in plugin optionsThat kept the behavior working, but it made the render path harder to reason about and more expensive than necessary.
editor.api.nodes({ at: [] }) inside an id loop, so one render could trigger many full-document scans.Build a shared derived index once per editor version, then let each block read from that index.
Create a dedicated helper that walks editor entries once and derives:
Instead of rescanning the full editor per suggestion id, reuse the grouped entries collected during the single document pass.
That keeps suggestion reconstruction local to each id's collected entries while preserving cross-block ownership rules.
Use useEditorVersion() as the invalidation signal and store the derived index in a WeakMap keyed by editor.
That gives one index build per editor version, even if many BlockDiscussion wrappers render in the same pass.
BlockDiscussion now asks for resolved discussions and suggestions with:
const { resolvedDiscussions, resolvedSuggestions } =
useBlockDiscussionItems(blockPath);
The UI component no longer owns the cross-block resolution algorithm.
The expensive question is not "what should this one block render?" The expensive question is "what annotation ids exist in the editor, and which top-level block owns each one?"
That second question is global. Treating it as per-block local work forces repeated scans and state repair.
Treating it as a shared derived index makes the ownership rule explicit:
This removes render-time plugin mutation and changes the hot path from repeated document rescans to one shared pass.
editor.api.nodes({ at: [] }) inside per-id loops when the ids all come from the same document snapshot.These checks passed:
bun test apps/www/src/registry/ui/block-discussion-index.spec.ts
corepack pnpm install
corepack pnpm turbo build --filter=./apps/www
corepack pnpm turbo typecheck --filter=./apps/www
corepack pnpm lint:fix
The focused spec covers the critical ownership behavior: