Edge cases and limitations; this page is the action-first version.)
First, always
- Turn on debug logs. Set
forceDebugModeinsessionStorage(sessionStorage.setItem('forceDebugMode','true')) and reload: Velt logs verbosely. - Confirm Velt is initialized. Gate on
useVeltInitState(). If it’s nevertrue, fix setup (API key,identify,setDocuments) before debugging UI: you can’t style what isn’t rendering. - Compare against default. Temporarily remove your customization. If the default works and yours doesn’t, it’s your customization; if the default is also broken, it’s setup/data.
- Inspect the element. With
shadowDom={false}, open DevTools on the element: read its realvelt-*classes/attributes and where it sits in the DOM.
Symptom → cause → fix
”My CSS does nothing”
- Shadow DOM is on. Variables cross it, but class/selector CSS doesn’t → either set
shadowDom={false}, or keep it on and push your CSS into the shadow root withclient.injectCustomCss({ type:'styles', value:'…' })(R6). - Specificity. Velt injects high-specificity styles → add
!important(R9b). Inspect → target thevelt-*class →!important. - Wrong class. You guessed a class name → inspect and use the actual
velt-*class (CSS classes).
”My wireframe renders nothing”
- Feature component not mounted. A
Velt…Wireframeonly registers a template: you must also mount the live feature (VeltComments/VeltCommentsSidebar/VeltCommentDialog). (R2) - Two
<VeltWireframe>roots. Merge is first-with-content-wins → your template may be ignored. Use one (R1). - Wrong slot name. Verify against
Wireframe components. - List/repeater slot. Custom layout around a list slot is ignored: customize the item wireframe instead (
Wireframes).
”My wireframe markup shows up inline on the page (not inside the Velt component), and the component still uses defaults”
- No
<VeltWireframe>registry root wrapping your slot templates. Verified in-browser: a slot element placed directly in the page (without the<VeltWireframe>root) renders its children inline where it sits and the live component falls back to its default UI because the template was never registered. Wrap all slot templates in exactly one<VeltWireframe>root (in plain HTML: one<velt-wireframe>). (R1)
“My wireframe’s empty state (or one piece) works, but the header/search/list vanished”
- You declared a container/root slot and omitted its structural children. Verified in-browser: declaring
velt-comments-sidebar-v2-wireframewith only a custom empty-placeholder rendered the empty state but dropped the search/filter/list. Container slots replace their layout: re-declare every structural child you want (panel → header(search,filter) → list → empty-placeholder). Leaf slots fall back to default; containers do not (Wireframes).
”My wireframe applies in the wrong places (or not where I want)”
- Scoping. Nested child wireframe = scoped to that parent’s render; root-level child = global. Move it accordingly (
Wireframes). - First-with-content-wins. If the same component is registered both nested and at root, the first one with content wins: don’t register it both ways.
”A button/onClick/hook inside my wireframe does nothing”
- Expected: wireframe markup is cloned; React interactivity is stripped (R4). Use the Velt slot for built-in actions, or
VeltButtonWireframe+useVeltEventCallback('veltButtonClick')for custom actions (Patterns and tips). For real interactive components, use primitives.
”velt-data shows blank / velt-if never matches”
- Wrong/undefined variable. Names are case-sensitive and finite: check
Wireframe variables. A wrong name →undefined. - Wrong context. Some variables exist only in certain slots (
{comment}/{commentIndex}only inside a thread card;{notification}only in the notifications panel;{focusedAnnotation}only in the sidebar). - Nested access not supported. Only the roots in the nested-access list allow
{root.nested}; others resolve to root only. - Flat-config feature. Try the explicit
{componentConfig.<name>}form (cursor/presence/huddle/recording/reactions/area/arrow/tag/autocomplete).
”My sidebar/list won’t scroll, or overflows / won’t take the available height”
- Broken flex/height chain: including Velt’s internal elements. Every element from your wrapper down to the scroll container needs
min-height:0(plusflex:1/height:100%): including Velt’s own internal containers (e.g.app-comment-sidebar-panel) that sit between your layout and the list. Inspect to find the hidden link and force it (often with!important). One missing link kills the scroll. (R14; full recipe inPatterns and tips.) Re-test that scrolling actually works: it’s easy to get 90% right and still have a dead scroll.
”Default styling is still there even though I wireframed it”
- Expected: a wireframe replaces a slot’s content, not all the surrounding default styling (borders, padding, backgrounds, fixed widths, popover chrome). Inspect → find the
velt-*class → override with!important(R9b). Treat this as part of every wireframe pass.
”My dialog/pin/primitive renders in the wrong place (top-left, escaping its box)”
- Absolute positioning needs a positioned ancestor. Some Velt pieces use
position: absolute. Give the parent you mount them inposition: relativeso they anchor correctly. (Recipe inPatterns and tips.)
”Dark mode colors are wrong”
- Hard-coded colors. Move dark values under
:root[data-velt-theme="dark"]using--velt-dark-mode-*(R9).
”A primitive layout won’t compose / a child won’t restructure”
- Leaf component. Leaf primitives have no sub-components → restructure via that leaf’s wireframe instead (
Primitives). - You forgot the composition. Primitives don’t auto-loop: fetch the data,
.map(), passannotationId/commentyourself.
”Headless mutation does nothing / errors”
- Object shape. Hand-built
Comment/CommentAnnotationis missing required fields → fill every field the action needs (R13); read the type in@veltdev/types. - Wrong hook usage. Most hooks return an object:
const { addComment } = useAddComment(). Read-hook returns are often wrappers (e.g.…Count→{ count }): read the field (Hooks).
”SSR / hydration error (Next.js)”
- Mark customization + hook components
'use client'; gate onuseVeltInitState(); don’t expect Velt UI during SSR.
When you’re still stuck
- Re-check the reference pages:
Wireframe components(slots/props),Wireframe variables(tokens),CSS classes(stateful classes),Component config(props). - Inspect the running UI in DevTools (
shadowDom={false}) to see the real elements, classes, and structure Velt rendered. - Isolate: reproduce the one surface in a minimal setup with default everything, then add your customization back piece by piece.
- Still nothing fixes it? Decide whether it’s even fixable:
SDK gaps and blockersrules out the fixable causes and, if none apply, shows how to record a real SDK gap honestly rather than hacking around it (R0).

