Everything you need to make Velt’s collaboration UI (comments, sidebar, notifications, reactions, presence, and more) match your design: from changing a color to building a 100% custom UI.
shadowDom) that customization depends on.
The one idea to remember
Velt owns the behavior, data, and real-time sync. You own the presentation. Every customization approach in this guide is just a different amount of “you own the presentation”: from recolor it to rebuild it from scratch.The four layers (in 10 seconds)
Ordered by how you should reach for them: CSS → Wireframes → Primitives → Headless:| Layer | What you do | Design control | Effort |
|---|---|---|---|
| CSS | Change colors/spacing/fonts via CSS variables (+ class overrides with !important) | Theme only | Lowest |
| Wireframes | Keep Velt’s behavior/data-wiring but supply your own HTML layout for each slot | High (layout/structure) | Low |
| Primitives | Compose Velt’s building-block components yourself (you do the looping, conditionals, prop-passing): full control + works with any UI library | Highest (short of headless) | Medium-High |
| Headless | Velt gives you data + actions via hooks; you build 100% of the UI | Total | Highest |
VeltCommentDialog primitive and wireframe parts of it; or wireframe the dialog, primitive sidebar, CSS on both). See Combining approaches.
How to use this guide
Read in this order. Don’t skip the first three: they prevent 90% of mistakes.How Velt customization works: the mental model + how the layers relate. (5 min)Decision tree: start here for any new design. Pick the right layer(s) for what you’re building. (the spine of this guide)Setup: prerequisites, theshadowDomrule, and the folder structure to put your code in.Build methodology: HOW to build: the extract → map → build → measure pipeline. Extract the exact numbers + icon SVGs deterministically (Extraction), map each element to a real slot/prop/icon (Velt Code Connect,Manifest: props-first, supply every slot), build in small patches applying the exact numbers, then measure (delta table, not eyeballing). Pair withBuild gotchas(the traps + the fix).- The approach you picked: open the matching approach page from the UI Customization navigation.
- The feature you’re customizing: comments are covered throughout the approach guides; to resolve a specific comment surface (dialog, sidebar V1/V2, sidebar button, pin, bubble, comment tool) to its primitive · root wireframe · key props · flags · variables, use the Surface lookup map in
Component catalog. For any other feature (notifications, reactions, recorder, mentions, presence/cursors, activity log, …) open the matching feature guide, starting withOther features. - Does the design need a component that isn’t showing? Check
Feature flags: many features (reply avatars, priority, minimap, @here, …) are off by default and just need a prop. Reference: the dictionary: look up exact CSS variables, classes, wireframe slots/tokens, props, behaviors (Behaviors), data fields/events (Data models), and hooks while you build. You look things up here: you don’t read it cover to cover.Rules: the non-negotiables. Read once; re-check before you ship.Verifying a customization: after each surface, confirm it matches the design, behavior is intact, and the rules pass. The definition of “done”.
Debugging (symptom → fix), SDK gaps and blockers (fixable problem vs. real SDK gap, and how to record a gap honestly), Patterns and tips (proven recipes), Context (attach/read your own data on comments), Cross-cutting concerns (a11y/i18n/RTL/responsive/testing), and Edge cases and limitations.
Docs map
Use these public routes when you share or link to this guide:Implementation checklist
- Recognize first: map the design to Velt components. Before using the decision tree, identify which Velt component each design element represents, whether it is available, and what needs to be enabled. Use
Component definitionsfor design intent, visual cues, positioning cues, look-alikes, and off-by-default flags. When two components match, confirm the intended component. When nothing matches, treat it as host UI or an SDK gap; do not force a Velt mapping. - Run the decision tree (
Decision tree) against each recognized surface. It returns the right layer, or per-feature mix, with the reason. - Treat
Rulesas hard constraints. They cover the core invariants: one<VeltWireframe>per app,shadowDom={false}when styling with selectors, no interactive React inside a wireframe, and no brittle DOM or timing workarounds. - Use only real identifiers. The
Referencepages are the source of truth for CSS variables, classes, wireframe slots, primitives, variables, props, config, feature flags, hooks, and component definitions. If a name is not documented there, do not use it unless you have verified it against the live SDK and added it back to the reference. - Follow each approach page in order. The CSS, wireframes, primitives, headless, and combining approaches pages are written as step-ordered guides.
- Match the folder structure in
Setup. This keeps Velt setup, customization, assets, and host app UI separated. - Verify each surface before moving on (
Verifying a customization). Drive its states, confirm Velt behavior is intact, run the static rules scan, and record a PASS, PARTIAL, FAIL, or BLOCKED verdict. Work one surface at a time. - When a goal seems impossible, run the gap flow (
SDK gaps and blockers). Rule out fixable causes such as shadow DOM, specificity, wrong layer, off-by-default features, and custom data before recording a real SDK gap.

