Velt Comments Best Practices
Comprehensive implementation guide for Velt's collaborative comments feature in React and Next.js applications. Contains 87 rules across 13 categories, prioritized by impact to guide automated code generation and integration patterns.
When to Apply
Reference these guidelines when:
- Adding collaborative commenting to a React/Next.js application
- Implementing any Velt comment mode (Freestyle, Popover, Stream, Text, Page, Inline)
- Integrating comments with rich text editors (TipTap, SlateJS, Lexical)
- Integrating comments with the Apryse WebViewer for PDF/docx documents
- Adding comments to media players (Video, Lottie animations)
- Adding comments to charts (Highcharts, ChartJS, Nivo)
- Building custom comment interfaces with standalone components
Rule Categories by Priority
| Priority |
Category |
Impact |
Prefix |
| 1 |
Core Setup |
CRITICAL |
core- |
| 2 |
Comment Modes |
HIGH |
mode- |
| 3 |
Standalone Components |
MEDIUM-HIGH |
standalone- |
| 4 |
Comment Surfaces |
MEDIUM-HIGH |
surface- |
| 5 |
UI Customization |
MEDIUM |
ui- |
| 6 |
Data Model |
MEDIUM |
data- |
| 7 |
Debugging & Testing |
LOW-MEDIUM |
debug- |
| 8 |
Moderation & Permissions |
LOW |
permissions- |
| 9 |
Attachments & Reactions |
MEDIUM |
attach- |
| 10 |
Wireframe Variables |
MEDIUM |
wireframe-variables- |
Quick Reference
1. Core Setup (CRITICAL)
core-provider-setup - Initialize VeltProvider with API key
core-authentication - Authenticate users before using comments
core-document-setup - Configure document context for comments
2. Comment Modes (HIGH)
mode-freestyle - Pin comments anywhere on page
mode-popover - Google Sheets-style cell comments
mode-stream - Google Docs-style sidebar stream
mode-text - Text highlight comments
mode-page - Page-level comments via sidebar
mode-inline-comments - Traditional inline thread style
mode-tiptap - TipTap editor integration
mode-slatejs - SlateJS editor integration
mode-lexical - Lexical editor integration
mode-canvas - Canvas/drawing comments
mode-lottie-player - Lottie animation frame comments
mode-video-player-prebuilt - Velt prebuilt video player
mode-video-player-custom - Custom video player integration
mode-chart-highcharts - Highcharts data point comments
mode-chart-chartjs - ChartJS data point comments
mode-chart-nivo - Nivo charts data point comments
mode-chart-custom - Custom chart integration
mode-apryse - Apryse WebViewer (PDF/docx) integration via @veltdev/apryse-velt-comments — ApryseVeltComments.configure(...).attach(instance), addComment({ instance }), renderComments({ instance, commentAnnotations }), durable TextEditorConfig anchors (text + occurrence + pageNumber)
3. Standalone Components (MEDIUM-HIGH)
standalone-comment-pin - Manual comment pin positioning
standalone-comment-thread - Render comment threads
standalone-comment-composer - Add comments programmatically
4. Comment Surfaces (MEDIUM-HIGH)
surface-sidebar - Comments sidebar component
surface-sidebar-setup - Sidebar setup, display modes (embed/floating/page/focused-thread/fullscreen), filterConfig, groupConfig, sortOrder, V2 sidebar, navigation events
surface-sidebar-v2 - Primitive-architecture V2 sidebar with 27+ composable primitives, unified filter model, and focused-thread view
surface-sidebar-button - Toggle sidebar button
5. UI Customization (MEDIUM)
ui-comment-dialog - Customize comment dialog
ui-comment-bubble - Customize comment bubble
ui-wireframes - Use wireframe components
ui-autocomplete-primitives - Use standalone autocomplete primitive components to build custom autocomplete UIs without requiring the full VeltAutocomplete panel
ui-agent-suggestion-primitives - 21 VeltCommentDialogAgentSuggestion* primitives for custom AI suggestion accept/reject UIs, resolution banners, header menus, and footer navigation
ui-v2-primitives - Set defaultCondition={false} on V2 primitive sub-components to bypass SDK default show/hide logic when overriding sections in wireframe compositions
6. Data Model (MEDIUM)
data-context-metadata - Add custom metadata
data-comment-annotations - Work with annotations
data-filtering-grouping - Filter and group comments
data-activity-action-types - Use CommentActivityActionTypes constant for type-safe comment activity filtering instead of raw strings
data-trigger-activities - Set triggerActivities on CommentData to auto-create activity records via POST /v2/commentannotations/add
data-comment-annotation-data-provider - Use config-based URL endpoints on CommentAnnotationDataProvider without placeholder callbacks; additionalFields replicates fields to resolver while retaining in Velt storage; fieldsToRemove strips fields from Velt's DB for PII removal
data-agent-fields-query - Use agentFields on CommentRequestQuery to filter getCommentAnnotationCount() to agent-tagged annotations; unread count equals total count when agentFields is set
7. Debugging & Testing (LOW-MEDIUM)
debug-common-issues - Common issues and solutions
debug-verification - Verification checklist
8. Moderation & Permissions (LOW)
permissions-private-mode - Control global comment visibility with enablePrivateMode/disablePrivateMode and update per-annotation visibility with updateVisibility
permissions-comment-saved-event - Subscribe to the commentSaved event for reliable post-persist side-effects (webhooks, analytics, external sync)
permissions-visibility-option-dropdown - Enable the visibility dropdown in the comment composer to let users select public or private before submitting, and subscribe to visibilityOptionClicked events
permissions-comment-save-triggered-event - Use commentSaveTriggered for immediate UI feedback (spinners, disabled states) on save button click — before the async database write completes
permissions-visibility-routing - Use isAnnotationPrivate() utility for unified privacy checks across legacy iam.accessMode and new visibilityConfig.type (restricted, organizationPrivate)
permissions-submit-in-flight - Use CommentDialogActionService.isSubmitInFlight(dialogInstanceId) to guard against duplicate submits in custom-actions sidebar hosts
permissions-comment-interaction-events - Prefer past-tense event aliases commentToolClicked and sidebarButtonClicked over the present-tense originals in new code
permissions-anonymous-user-data-provider - Register setAnonymousUserDataProvider() to resolve tagged contact emails to userIds at comment save time
9. Attachments & Reactions (MEDIUM)
attach-download-control - Control attachment download behavior and intercept clicks
10. Configuration (MEDIUM)
config-mentions-contacts - @Mentions, contacts, user assignment, autocomplete
config-status-priority - Custom status and priority levels, resolve/update workflows
config-reactions - Emoji reactions — enable, customize, add/delete/toggle
config-attachments - File attachments — enable, upload, delete, allowed types
config-text-formatting - Rich text formatting options in composer
config-navigation - Navigation, deep linking, scroll-to-comment, shareable links
config-dom-controls - Restrict comment placement to specific DOM elements
config-sidebar-management - Programmatic sidebar data, filtering, and configuration
config-sidebar-access-modes - Use accessModes filter in setCommentSidebarFilters() for privacy-based sidebar filtering (public/private)
config-ui-behavior - UI/UX toggle methods — display, interaction, behavior (20+ methods)
config-moderation - Moderation workflows — approve, accept, reject, read-only
config-component-props - Typed props interfaces for VeltComments, VeltCommentDialog, VeltCommentsSidebar, VeltInlineCommentsSection — edit-mode placeholder overrides, assignToType, focus behavior
11. Wireframe Variables (MEDIUM)
wireframe-variables-comment-bubble - Bind Comment Bubble + Comment Pin wireframe slots via {annotation.*}, {selectedAnnotationsMap[...]}, globalConfigSignal.featureState.*
wireframe-variables-comment-dialog - Bind the ~110-slot Comment Dialog wireframe family (App / Data / UI / Feature State namespaces, comment / commentIndex loop-scope, root-level placeholder + unread-map paths, v1 aliases)
wireframe-variables-comment-tool - Bind the Comment Tool wireframe via the flat-config {addCommentMode} / {commentToolEnabled} aliases and the canonical globalConfig.featureState.* / componentConfig.* paths
wireframe-variables-inline-comments-section - Bind the Inline Comments Section wireframe ({annotations}, {skeletonLoading}, {filterState.*} / {sortState.*}, per-row loop-scope filter / sortOption / isActive / isAscending, featureState.* conflict-paths, nested Comment Dialog primitives in list + composer)
wireframe-variables-multithread-comments - Bind the Multithread Comments wireframe ({nonDraftCommentsCount}, {minimalFilter}, empty-state + reset-filter gates, minimal filter / sort + bulk-actions dropdowns with isSelected loop-scope, data.user / uiState.shadowDom conflict-paths)
wireframe-variables-autocomplete - Bind the Autocomplete @-mention picker wireframes (flat-config componentConfig.<path> access for flattenedItems / customGroupsEnabled / newUserContactError, loop-scope option / chip, option / group-option / chip / empty-state subcomponents, chip tooltip descendants)
wireframe-variables-text-comment - Bind the Text Comment toolbar wireframes ({selectedWordsCount} / {selectedCharactersCount} / {position.*}, capability flags isUserAllowed / enableTextComments / rewriterEnabled, five conflict-name explicit paths)
wireframe-variables-comment-sidebar-button - Bind the Comment Sidebar Button wireframe via flat-config (globalConfig.featureState.sidebarVisible, componentConfig.data.unreadCount / annotations.length, componentConfig.uiState.commentCountType / floatingMode)
wireframe-variables-comment-sidebar - Bind the ~80-tag Comment Sidebar wireframe family — hybrid access (mapped focusedAnnotation / appliedFiltersCount / unreadCommentAnnotationCount alongside flat componentConfig.skeletonLoading / noCommentsFound* / virtualScrollData / filterConfig.*), loop-scope (focusedAnnotation, filter, item, group, tag), nested Comment Dialog scope in list / focused-thread / page-mode composer
Agent Comments — Critical API Reference
When the task involves AI agents creating comments or handling agent suggestion accept/reject, use these exact patterns:
Creating agent annotations — POST /v2/commentannotations/add:
data: {
organizationId: "...",
documentId: "...",
commentAnnotations: [{
type: "suggestion", // REQUIRED for Accept/Reject buttons
commentData: [{
commentText: "Finding text",
from: { userId: "agent-id" },
agent: { // On commentData[0], NOT annotation root
agentSource: "external", // "external" for non-Velt agents
agentName: "My Agent", // REQUIRED for external agents
agentId: "my-agent",
executionId: "run_123",
reason: { // REQUIRED — finding details
title: "Issue title",
description: "Details",
severity: "high",
},
},
}],
}],
}
Reading agent annotations — POST /v2/commentannotations/get:
- Use
executionId filter for a specific run
- Use
agentSuggestions: true for only pending (unaccepted) suggestions
Handling accept/reject on the client — use dedicated events, NOT commentSaved:
import { useCommentEventCallback } from '@veltdev/react';
const accepted = useCommentEventCallback('suggestionAccepted');
const rejected = useCommentEventCallback('suggestionRejected');
How to Use
Read individual rule files for detailed explanations and code examples:
rules/shared/core/core-provider-setup.md
rules/shared/mode/mode-popover.md
Each rule file contains:
- Brief explanation of why it matters
- Incorrect code example with explanation
- Correct code example with explanation
- Source pointers to official documentation
Compiled Documents
AGENTS.md — Compressed index of all rules with file paths (start here)
AGENTS.full.md — Full verbose guide with all rules expanded inline
1---2name: velt-comments-best-practices3description: Velt Comments implementation patterns and best practices for React, Next.js, and web applications. Use when adding collaborative commenting features, comment modes (Freestyle, Popover, Stream, Text, Page), rich text editor comments (TipTap, SlateJS, Lexical), Apryse WebViewer (PDF/docx) comments, media player comments, chart comments, comments sidebar setup and customization (embed mode, floating mode, focused thread, V2 sidebar), sidebar filtering with accessModes for privacy, isAnnotationPrivate() visibility routing, CommentDialogActionService.isSubmitInFlight() for duplicate-submit guards, VeltCommentDialogAgentSuggestion primitives for AI suggestion accept/reject UIs, agent comment annotations via REST API (agent block with agentSource/agentId/executionId, agent-specific GET filters, suggestionAccepted/suggestionRejected client events, sourceType "agent" UI rendering), or binding Comment Bubble / Comment Dialog / Comment Tool wireframe slots via template variables (velt-data, velt-if, velt-class).4license: MIT5---67# Velt Comments Best Practices89Comprehensive implementation guide for Velt's collaborative comments feature in React and Next.js applications. Contains 87 rules across 13 categories, prioritized by impact to guide automated code generation and integration patterns.1011## When to Apply1213Reference these guidelines when:14- Adding collaborative commenting to a React/Next.js application15- Implementing any Velt comment mode (Freestyle, Popover, Stream, Text, Page, Inline)16- Integrating comments with rich text editors (TipTap, SlateJS, Lexical)17- Integrating comments with the Apryse WebViewer for PDF/docx documents18- Adding comments to media players (Video, Lottie animations)19- Adding comments to charts (Highcharts, ChartJS, Nivo)20- Building custom comment interfaces with standalone components2122## Rule Categories by Priority2324| Priority | Category | Impact | Prefix |25|----------|----------|--------|--------|26| 1 | Core Setup | CRITICAL | `core-` |27| 2 | Comment Modes | HIGH | `mode-` |28| 3 | Standalone Components | MEDIUM-HIGH | `standalone-` |29| 4 | Comment Surfaces | MEDIUM-HIGH | `surface-` |30| 5 | UI Customization | MEDIUM | `ui-` |31| 6 | Data Model | MEDIUM | `data-` |32| 7 | Debugging & Testing | LOW-MEDIUM | `debug-` |33| 8 | Moderation & Permissions | LOW | `permissions-` |34| 9 | Attachments & Reactions | MEDIUM | `attach-` |35| 10 | Wireframe Variables | MEDIUM | `wireframe-variables-` |3637## Quick Reference3839### 1. Core Setup (CRITICAL)4041- `core-provider-setup` - Initialize VeltProvider with API key42- `core-authentication` - Authenticate users before using comments43- `core-document-setup` - Configure document context for comments4445### 2. Comment Modes (HIGH)4647- `mode-freestyle` - Pin comments anywhere on page48- `mode-popover` - Google Sheets-style cell comments49- `mode-stream` - Google Docs-style sidebar stream50- `mode-text` - Text highlight comments51- `mode-page` - Page-level comments via sidebar52- `mode-inline-comments` - Traditional inline thread style53- `mode-tiptap` - TipTap editor integration54- `mode-slatejs` - SlateJS editor integration55- `mode-lexical` - Lexical editor integration56- `mode-canvas` - Canvas/drawing comments57- `mode-lottie-player` - Lottie animation frame comments58- `mode-video-player-prebuilt` - Velt prebuilt video player59- `mode-video-player-custom` - Custom video player integration60- `mode-chart-highcharts` - Highcharts data point comments61- `mode-chart-chartjs` - ChartJS data point comments62- `mode-chart-nivo` - Nivo charts data point comments63- `mode-chart-custom` - Custom chart integration64- `mode-apryse` - Apryse WebViewer (PDF/docx) integration via `@veltdev/apryse-velt-comments` — `ApryseVeltComments.configure(...).attach(instance)`, `addComment({ instance })`, `renderComments({ instance, commentAnnotations })`, durable `TextEditorConfig` anchors (`text` + `occurrence` + `pageNumber`)6566### 3. Standalone Components (MEDIUM-HIGH)6768- `standalone-comment-pin` - Manual comment pin positioning69- `standalone-comment-thread` - Render comment threads70- `standalone-comment-composer` - Add comments programmatically7172### 4. Comment Surfaces (MEDIUM-HIGH)7374- `surface-sidebar` - Comments sidebar component75- `surface-sidebar-setup` - Sidebar setup, display modes (embed/floating/page/focused-thread/fullscreen), filterConfig, groupConfig, sortOrder, V2 sidebar, navigation events76- `surface-sidebar-v2` - Primitive-architecture V2 sidebar with 27+ composable primitives, unified filter model, and focused-thread view77- `surface-sidebar-button` - Toggle sidebar button7879### 5. UI Customization (MEDIUM)8081- `ui-comment-dialog` - Customize comment dialog82- `ui-comment-bubble` - Customize comment bubble83- `ui-wireframes` - Use wireframe components84- `ui-autocomplete-primitives` - Use standalone autocomplete primitive components to build custom autocomplete UIs without requiring the full VeltAutocomplete panel85- `ui-agent-suggestion-primitives` - 21 VeltCommentDialogAgentSuggestion* primitives for custom AI suggestion accept/reject UIs, resolution banners, header menus, and footer navigation86- `ui-v2-primitives` - Set defaultCondition={false} on V2 primitive sub-components to bypass SDK default show/hide logic when overriding sections in wireframe compositions8788### 6. Data Model (MEDIUM)8990- `data-context-metadata` - Add custom metadata91- `data-comment-annotations` - Work with annotations92- `data-filtering-grouping` - Filter and group comments93- `data-activity-action-types` - Use CommentActivityActionTypes constant for type-safe comment activity filtering instead of raw strings94- `data-trigger-activities` - Set triggerActivities on CommentData to auto-create activity records via POST /v2/commentannotations/add95- `data-comment-annotation-data-provider` - Use config-based URL endpoints on CommentAnnotationDataProvider without placeholder callbacks; additionalFields replicates fields to resolver while retaining in Velt storage; fieldsToRemove strips fields from Velt's DB for PII removal96- `data-agent-fields-query` - Use agentFields on CommentRequestQuery to filter getCommentAnnotationCount() to agent-tagged annotations; unread count equals total count when agentFields is set9798### 7. Debugging & Testing (LOW-MEDIUM)99100- `debug-common-issues` - Common issues and solutions101- `debug-verification` - Verification checklist102103### 8. Moderation & Permissions (LOW)104105- `permissions-private-mode` - Control global comment visibility with enablePrivateMode/disablePrivateMode and update per-annotation visibility with updateVisibility106- `permissions-comment-saved-event` - Subscribe to the commentSaved event for reliable post-persist side-effects (webhooks, analytics, external sync)107- `permissions-visibility-option-dropdown` - Enable the visibility dropdown in the comment composer to let users select public or private before submitting, and subscribe to visibilityOptionClicked events108- `permissions-comment-save-triggered-event` - Use commentSaveTriggered for immediate UI feedback (spinners, disabled states) on save button click — before the async database write completes109- `permissions-visibility-routing` - Use isAnnotationPrivate() utility for unified privacy checks across legacy iam.accessMode and new visibilityConfig.type (restricted, organizationPrivate)110- `permissions-submit-in-flight` - Use CommentDialogActionService.isSubmitInFlight(dialogInstanceId) to guard against duplicate submits in custom-actions sidebar hosts111- `permissions-comment-interaction-events` - Prefer past-tense event aliases commentToolClicked and sidebarButtonClicked over the present-tense originals in new code112- `permissions-anonymous-user-data-provider` - Register setAnonymousUserDataProvider() to resolve tagged contact emails to userIds at comment save time113114### 9. Attachments & Reactions (MEDIUM)115116- `attach-download-control` - Control attachment download behavior and intercept clicks117118### 10. Configuration (MEDIUM)119120- `config-mentions-contacts` - @Mentions, contacts, user assignment, autocomplete121- `config-status-priority` - Custom status and priority levels, resolve/update workflows122- `config-reactions` - Emoji reactions — enable, customize, add/delete/toggle123- `config-attachments` - File attachments — enable, upload, delete, allowed types124- `config-text-formatting` - Rich text formatting options in composer125- `config-navigation` - Navigation, deep linking, scroll-to-comment, shareable links126- `config-dom-controls` - Restrict comment placement to specific DOM elements127- `config-sidebar-management` - Programmatic sidebar data, filtering, and configuration128- `config-sidebar-access-modes` - Use accessModes filter in setCommentSidebarFilters() for privacy-based sidebar filtering (public/private)129- `config-ui-behavior` - UI/UX toggle methods — display, interaction, behavior (20+ methods)130- `config-moderation` - Moderation workflows — approve, accept, reject, read-only131- `config-component-props` - Typed props interfaces for VeltComments, VeltCommentDialog, VeltCommentsSidebar, VeltInlineCommentsSection — edit-mode placeholder overrides, assignToType, focus behavior132133### 11. Wireframe Variables (MEDIUM)134135- `wireframe-variables-comment-bubble` - Bind Comment Bubble + Comment Pin wireframe slots via `{annotation.*}`, `{selectedAnnotationsMap[...]}`, `globalConfigSignal.featureState.*`136- `wireframe-variables-comment-dialog` - Bind the ~110-slot Comment Dialog wireframe family (App / Data / UI / Feature State namespaces, `comment` / `commentIndex` loop-scope, root-level placeholder + unread-map paths, v1 aliases)137- `wireframe-variables-comment-tool` - Bind the Comment Tool wireframe via the flat-config `{addCommentMode}` / `{commentToolEnabled}` aliases and the canonical `globalConfig.featureState.*` / `componentConfig.*` paths138- `wireframe-variables-inline-comments-section` - Bind the Inline Comments Section wireframe (`{annotations}`, `{skeletonLoading}`, `{filterState.*}` / `{sortState.*}`, per-row loop-scope `filter` / `sortOption` / `isActive` / `isAscending`, `featureState.*` conflict-paths, nested Comment Dialog primitives in list + composer)139- `wireframe-variables-multithread-comments` - Bind the Multithread Comments wireframe (`{nonDraftCommentsCount}`, `{minimalFilter}`, empty-state + reset-filter gates, minimal filter / sort + bulk-actions dropdowns with `isSelected` loop-scope, `data.user` / `uiState.shadowDom` conflict-paths)140- `wireframe-variables-autocomplete` - Bind the Autocomplete @-mention picker wireframes (flat-config `componentConfig.<path>` access for `flattenedItems` / `customGroupsEnabled` / `newUserContactError`, loop-scope `option` / `chip`, option / group-option / chip / empty-state subcomponents, chip tooltip descendants)141- `wireframe-variables-text-comment` - Bind the Text Comment toolbar wireframes (`{selectedWordsCount}` / `{selectedCharactersCount}` / `{position.*}`, capability flags `isUserAllowed` / `enableTextComments` / `rewriterEnabled`, five conflict-name explicit paths)142- `wireframe-variables-comment-sidebar-button` - Bind the Comment Sidebar Button wireframe via flat-config (`globalConfig.featureState.sidebarVisible`, `componentConfig.data.unreadCount` / `annotations.length`, `componentConfig.uiState.commentCountType` / `floatingMode`)143- `wireframe-variables-comment-sidebar` - Bind the ~80-tag Comment Sidebar wireframe family — hybrid access (mapped `focusedAnnotation` / `appliedFiltersCount` / `unreadCommentAnnotationCount` alongside flat `componentConfig.skeletonLoading` / `noCommentsFound*` / `virtualScrollData` / `filterConfig.*`), loop-scope (`focusedAnnotation`, `filter`, `item`, `group`, `tag`), nested Comment Dialog scope in list / focused-thread / page-mode composer144145## Agent Comments — Critical API Reference146147When the task involves AI agents creating comments or handling agent suggestion accept/reject, use these exact patterns:148149**Creating agent annotations** — `POST /v2/commentannotations/add`:150```javascript151data: {152 organizationId: "...",153 documentId: "...",154 commentAnnotations: [{155 type: "suggestion", // REQUIRED for Accept/Reject buttons156 commentData: [{157 commentText: "Finding text",158 from: { userId: "agent-id" },159 agent: { // On commentData[0], NOT annotation root160 agentSource: "external", // "external" for non-Velt agents161 agentName: "My Agent", // REQUIRED for external agents162 agentId: "my-agent",163 executionId: "run_123",164 reason: { // REQUIRED — finding details165 title: "Issue title",166 description: "Details",167 severity: "high",168 },169 },170 }],171 }],172}173```174175**Reading agent annotations** — `POST /v2/commentannotations/get`:176- Use `executionId` filter for a specific run177- Use `agentSuggestions: true` for only pending (unaccepted) suggestions178179**Handling accept/reject on the client** — use dedicated events, NOT `commentSaved`:180```tsx181import { useCommentEventCallback } from '@veltdev/react';182const accepted = useCommentEventCallback('suggestionAccepted');183const rejected = useCommentEventCallback('suggestionRejected');184```185186## How to Use187188Read individual rule files for detailed explanations and code examples:189190```191rules/shared/core/core-provider-setup.md192rules/shared/mode/mode-popover.md193```194195Each rule file contains:196- Brief explanation of why it matters197- Incorrect code example with explanation198- Correct code example with explanation199- Source pointers to official documentation200201## Compiled Documents202203- `AGENTS.md` — Compressed index of all rules with file paths (start here)204- `AGENTS.full.md` — Full verbose guide with all rules expanded inline