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 keycore-authentication- Authenticate users before using commentscore-document-setup- Configure document context for comments
2. Comment Modes (HIGH)
mode-freestyle- Pin comments anywhere on pagemode-popover- Google Sheets-style cell commentsmode-stream- Google Docs-style sidebar streammode-text- Text highlight commentsmode-page- Page-level comments via sidebarmode-inline-comments- Traditional inline thread stylemode-tiptap- TipTap editor integrationmode-slatejs- SlateJS editor integrationmode-lexical- Lexical editor integrationmode-canvas- Canvas/drawing commentsmode-lottie-player- Lottie animation frame commentsmode-video-player-prebuilt- Velt prebuilt video playermode-video-player-custom- Custom video player integrationmode-chart-highcharts- Highcharts data point commentsmode-chart-chartjs- ChartJS data point commentsmode-chart-nivo- Nivo charts data point commentsmode-chart-custom- Custom chart integrationmode-apryse- Apryse WebViewer (PDF/docx) integration via@veltdev/apryse-velt-comments—ApryseVeltComments.configure(...).attach(instance),addComment({ instance }),renderComments({ instance, commentAnnotations }), durableTextEditorConfiganchors (text+occurrence+pageNumber)
3. Standalone Components (MEDIUM-HIGH)
standalone-comment-pin- Manual comment pin positioningstandalone-comment-thread- Render comment threadsstandalone-comment-composer- Add comments programmatically
4. Comment Surfaces (MEDIUM-HIGH)
surface-sidebar- Comments sidebar componentsurface-sidebar-setup- Sidebar setup, display modes (embed/floating/page/focused-thread/fullscreen), filterConfig, groupConfig, sortOrder, V2 sidebar, navigation eventssurface-sidebar-v2- Primitive-architecture V2 sidebar with 27+ composable primitives, unified filter model, and focused-thread viewsurface-sidebar-button- Toggle sidebar button
5. UI Customization (MEDIUM)
ui-comment-dialog- Customize comment dialogui-comment-bubble- Customize comment bubbleui-wireframes- Use wireframe componentsui-autocomplete-primitives- Use standalone autocomplete primitive components to build custom autocomplete UIs without requiring the full VeltAutocomplete panelui-agent-suggestion-primitives- 21 VeltCommentDialogAgentSuggestion* primitives for custom AI suggestion accept/reject UIs, resolution banners, header menus, and footer navigationui-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 metadatadata-comment-annotations- Work with annotationsdata-filtering-grouping- Filter and group commentsdata-activity-action-types- Use CommentActivityActionTypes constant for type-safe comment activity filtering instead of raw stringsdata-trigger-activities- Set triggerActivities on CommentData to auto-create activity records via POST /v2/commentannotations/adddata-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 removaldata-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 solutionsdebug-verification- Verification checklist
8. Moderation & Permissions (LOW)
permissions-private-mode- Control global comment visibility with enablePrivateMode/disablePrivateMode and update per-annotation visibility with updateVisibilitypermissions-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 eventspermissions-comment-save-triggered-event- Use commentSaveTriggered for immediate UI feedback (spinners, disabled states) on save button click — before the async database write completespermissions-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 hostspermissions-comment-interaction-events- Prefer past-tense event aliases commentToolClicked and sidebarButtonClicked over the present-tense originals in new codepermissions-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, autocompleteconfig-status-priority- Custom status and priority levels, resolve/update workflowsconfig-reactions- Emoji reactions — enable, customize, add/delete/toggleconfig-attachments- File attachments — enable, upload, delete, allowed typesconfig-text-formatting- Rich text formatting options in composerconfig-navigation- Navigation, deep linking, scroll-to-comment, shareable linksconfig-dom-controls- Restrict comment placement to specific DOM elementsconfig-sidebar-management- Programmatic sidebar data, filtering, and configurationconfig-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-onlyconfig-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/commentIndexloop-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 canonicalglobalConfig.featureState.*/componentConfig.*pathswireframe-variables-inline-comments-section- Bind the Inline Comments Section wireframe ({annotations},{skeletonLoading},{filterState.*}/{sortState.*}, per-row loop-scopefilter/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 withisSelectedloop-scope,data.user/uiState.shadowDomconflict-paths)wireframe-variables-autocomplete- Bind the Autocomplete @-mention picker wireframes (flat-configcomponentConfig.<path>access forflattenedItems/customGroupsEnabled/newUserContactError, loop-scopeoption/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 flagsisUserAllowed/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 (mappedfocusedAnnotation/appliedFiltersCount/unreadCommentAnnotationCountalongside flatcomponentConfig.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
executionIdfilter for a specific run - Use
agentSuggestions: truefor 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