Source of truth: exhaustive for what it covers. Generated from Velt hook metadata. If a name isn’t on this page, it doesn’t exist: don’t use it (a missing identifier resolves to undefined / renders nothing). Never invent or guess a name; use only identifiers that appear verbatim here or that you verified against ground truth and added here. Scope: exhaustive over @veltdev/react’s hook exports. Comment + notification + core hooks are documented in full; the remaining other-feature hooks are listed by name + return type + one-line purpose in “Other features (brief)” below: enough to keep the “a hook not listed doesn’t exist” invariant true, without full per-hook depth.
The hooks you use to build custom UI (Headless) or to add data-driven extras alongside any approach. All from @veltdev/react. Types from @veltdev/types.
Grouped by purpose: read (data/state you render), mutate (actions you call), events (callbacks), control (init/scope/imperative). This lists the commonly-used comment hooks plus a brief map of other features; the SDK exports many more hooks following the same naming, but everything you need for the patterns in this guide is here.
Exhaustive over @veltdev/react’s hook exports: a hook not listed here doesn’t exist (source-of-truth invariant).
Read: data & state
| Hook | Returns / use |
|---|
useCommentAnnotations() | Reactive CommentAnnotation[] (or null before load) on the current document. The main data source. Use useCommentAnnotations() ?? []. |
useGetCommentAnnotations(query?) | Reactive, filtered query → GetCommentAnnotationsResponse ({ annotations, count, … }), not a bare array. |
useCommentAnnotationById({ annotationId }) | One annotation by id. |
useCommentAnnotationsCount(query?) | GetCommentAnnotationsCountResponse (read its count field), not a bare number. |
useCommentModeState() | Whether comment mode is active. |
useCommentSidebarData() | Data backing the sidebar (filters/sorted list). |
useUnreadCommentCountOnCurrentDocument() | Unread comment count on the current document → UnreadCommentsCount object { count } | null. Read .count. |
useCurrentUser() | The identified user. |
useCurrentUserPermissions() | Current user’s permissions. |
useUnreadCommentAnnotationCountOnCurrentDocument() | Returns UnreadCommentsCount: an object { count } | null, not a number. Read .count (e.g. data?.count ?? 0). Great for badges. |
useUnreadCommentCountByAnnotationId() / useUnreadCommentCountByLocationId() | Unread counts scoped to a thread / location. |
useUnreadCommentAnnotationCountByLocationId() | Unread annotation count by location. |
Return shapes matter. Several read hooks return wrapper objects, not bare values (…Count* → { count }; useGetCommentAnnotations → a response object). Read the field, don’t render the object. When unsure of a return shape, console.log the hook’s value in your component to see it before rendering.
Mutate: actions
| Hook | Action |
|---|
useAddCommentAnnotation() | Create a new annotation (a new thread). |
useAddComment() | Add a comment/reply to an annotation. |
useUpdateComment() | Edit a comment. |
useDeleteComment() | Delete a single comment. |
useDeleteCommentAnnotation() | Delete a whole thread. |
useResolveCommentAnnotation() | Resolve a thread. |
useApproveCommentAnnotation() / useRejectCommentAnnotation() | Approval flows. |
useUpdateStatus() | Set a thread’s status. |
useUpdatePriority() | Set priority. |
useAssignUser() | Assign a user to a thread. |
useUpdateAccess() | Change a thread’s access/visibility. Returns { updateAccess }; await updateAccess(request: UpdateAccessRequest) → Promise<UpdateAccessEvent | null>. Writes CommentAnnotation.iam.accessMode (public vs private). |
useAddReaction() / useDeleteReaction() / useToggleReaction() | Reactions. |
useAddAttachment() / useDeleteAttachment() / useGetAttachment() | Attachments. |
useGetLink() / useCopyLink() | Deep link to a comment. |
useGetComment() | Returns { getComment }; await getComment(request) → Comment[] (imperative fetch, not reactive). |
useGetRecording() / useDeleteRecording() | Returns { getRecording } / { deleteRecording }; fetch or delete a recording attached to a comment. |
Most return an object with a function, e.g. const { addComment } = useAddComment(); then await addComment({ annotationId, comment }).
Events: callbacks
| Hook | Fires on |
|---|
useCommentEventCallback() | Generic comment events. |
useCommentAddHandler() / useCommentUpdateHandler() | A comment added / updated. |
useCommentSelectionChangeHandler() | Selected thread changes. |
useCommentCopyLinkHandler() | A copy-link action. |
useCommentActionCallback(action) | Typed callback for a specific comment action (CommentEventTypesMap[action]). |
useCommentSidebarActionButtonClick() | A custom sidebar action-button click → CommentSidebarCustomActionEventData | null. |
useCommentSidebarInit() | Fires when the comment sidebar initializes. |
useCommentDialogSidebarClickHandler() | A click on the sidebar from a comment dialog. |
useNotificationEventCallback(action) | Typed notification event callback (NotificationEventTypesMap[action]). |
usePresenceEventCallback(action) | Typed presence event callback (PresenceEventTypesMap[action]). |
useRecorderAddHandler() | Fires when a recording is added → RecordedData | null. |
useServerConnectionStateChangeHandler() | Live-state server connection state changes → ServerConnectionState. |
useVeltEventCallback(eventName) | Custom events (e.g. 'veltButtonClick' from a wireframe button). |
Control: init, scope, imperative
| Hook | Use | |
|---|
useVeltClient() | The Velt client (const { client } = useVeltClient()); imperative API + client.getCommentElement(). (useClient() is a newer alias.) | |
useIdentify() | Returns { identify }; call identify(user). | |
useSetDocuments() / useSetDocument() | Return a setter: const { setDocuments } = useSetDocuments(); then setDocuments(documents, options). Not useSetDocuments([...]). | |
useSetDocumentId(documentId) | Argument-form setter for a single document id (no returned setter; pass the id directly). | |
useUnsetDocuments() / useUnsetDocumentId() | Clear the current document(s) scope. | |
useSetRootDocument() | Returns { setRootDocument }; setRootDocument(document) sets the root document. | |
useSetLocation(location, appendLocation?) | Argument-form location setter. | |
useSetLocations() | Returns { setLocations }; setLocations(locations, options). | |
useSetRootLocation() | Returns { setRootLocation }; setRootLocation(location). | |
useSetPageInfo() / useClearPageInfo() | Return { setPageInfo } / { clearPageInfo }; set or clear page metadata. | |
useHeartbeat(config?) | Reactive GetHeartbeatResponse (presence heartbeat). | |
useSetContextProvider() | Provide custom context to comments. | |
useVeltInitState() | Whether Velt finished initializing (gate rendering on this). | |
useUiState() / useSetLiveStateData() | Shared UI state between users. | |
useSubscribeCommentAnnotation() / useUnsubscribeCommentAnnotation() | Subscribe to a specific annotation. | |
useCommentUtils() | The underlying comment element (`CommentElement | undefined`); the imperative element backing most comment hooks. |
Imperative API via the client
Some controls aren’t hooks: call them on the comment element:
const { client } = useVeltClient();
const commentElement = client.getCommentElement();
commentElement.openCommentSidebar();
commentElement.enableCommentMode();
commentElement.setCommentSidebarFilters({ status: ["open"], priority: ["high"] });
commentElement.setCustomStatus([{ id: "new", title: "New", color: "#FF5733" }]);
(These element APIs come from the typed comment element returned by client.getCommentElement().)
Other features (brief)
| Feature | Representative hooks |
|---|
| Presence | usePresenceUsers, usePresenceData, usePresenceUtils, usePresenceEventCallback, useHeartbeat |
| Cursors | useCursorUsers, useCursorUtils |
| Notifications | useNotificationsData, useUnreadNotificationsCount, useNotificationSettings, useNotificationUtils, useNotificationEventCallback |
| Reactions | useAddReaction, useToggleReaction, useDeleteReaction |
| Recorder | useRecordings, useRecordingDataByRecorderId, useRecorderUtils, useRecorderEventCallback, useRecorderAddHandler |
| Suggestions | useSuggestions, useSuggestionUtils, usePendingSuggestion, useStartSuggestion, useCommitSuggestion, useEnableSuggestionMode / useDisableSuggestionMode, useSuggestionModeState, useSuggestionEventCallback |
| Activity log | useAllActivities, useActivityUtils |
| Autocomplete | useAutocompleteUtils, useAutocompleteChipClick, useContactList, useContactSelected, useContactUtils |
| Tags | useTagAnnotations, useTagUtils |
| Views/Analytics | useUniqueViewsByUser, useUniqueViewsByDate, useViewsUtils |
| Live state sync | useLiveState, useLiveStateData, useSetLiveStateData |
See Other features for how customization applies to these.
Other-feature hook exports (verified return types)
These are exported from @veltdev/react but belong to out-of-scope features. They are listed here only to keep the “a hook not listed doesn’t exist” invariant true: name, category, return type, and one-line purpose. Return types verified against ground truth.
| Hook | Category | Returns | Purpose |
|---|
useLiveStateSyncUtils() | Live state sync | LiveStateSyncElement | undefined | The imperative live-state-sync element backing the live-state hooks. |
useUserEditorState() | Live state sync | UserEditorAccess | null | undefined | Whether the current user is the editor in single-editor mode. |
useEditor() | Live state sync | User | null | The current editor user in single-editor mode. |
useEditorAccessTimer() | Live state sync | EditorAccessTimer (defaults to { state: 'idle' }) | Editor-access countdown/timer state. |
useEditorAccessRequestHandler() | Live state sync | { requestStatus: string; requestedBy: User } | null | The pending editor-access request, if any. |
useLiveStateSyncEventCallback(action) | Live state sync | LiveStateEventTypesMap[action] | Latest live-state-sync event payload (access/editor events). |
useRegisterTarget() | Suggestion targets | { registerTarget(config: RegisterTargetConfig<T>): void } | Register a complex-object getter for a suggestion target. |
useUnregisterTarget() | Suggestion targets | { unregisterTarget(targetId: string): void } | Drop a registered suggestion-target getter. |
useLiveSelectionUtils() | Live selection | SelectionElement | undefined | The imperative live-selection element. |
useLiveSelectionDataHandler() | Live selection | LiveSelectionData | null | Reactive live-selection data. |
useCrdtUtils() | CRDT | CrdtElement | undefined | The imperative CRDT element. |
useCrdtEventCallback(action) | CRDT | CrdtEventTypesMap[action] | Latest CRDT event payload (e.g. updateData). |
useHuddleUtils() | Huddle | HuddleElement | undefined (typed any in source) | The imperative huddle element. |
useAIRewriterUtils() | AI rewriter | RewriterElement | undefined | The imperative rewriter element (subscribe to textSelected; call askAi/replaceText/addComment). |