What Velt is
Velt is a set of collaboration features that you drop into your app: comments, a comments sidebar, notifications, reactions, presence, live cursors, huddles, and recordings. Velt handles the hard parts, including storing comments, real-time sync between users, mentions, permissions, and threading. You decide how it looks.The mental model: behavior vs. presentation
Velt owns behavior + data + real-time sync. You own presentation.
- Behavior / data / sync (Velt’s job): saving a comment, syncing it to other users live, resolving a thread, @mentions, reactions, who’s online, unread counts. You never re-implement these.
- Presentation (your job, to whatever degree you want): colors, spacing, fonts, layout, which pieces show, the surrounding HTML, icons.
The four layers
Reach for them in this order: CSS → Wireframes → Primitives → Headless: escalating only when the cheaper layer can’t express your design.Why wireframes are less effort than primitives: with wireframes, Velt fetches the data, loops the threads, and wires each slot’s behavior; you just supply layout markup. With primitives, you write that code yourself, and in exchange get full control and your own UI library.
One more wireframe superpower: variants let you register several looks for the same component and switch between them (e.g. a compact card in the sidebar, a full card in the dialog); see Variants.
Detailed walkthroughs:
CSS · Wireframes · Primitives · Headless.
Mix layers per feature
The layers are not an app-wide setting. You pick one per feature/surface, and you can even combine them on the same surface: wireframe the comment dialog while the sidebar stays a plain primitive, or drop in aVeltCommentDialog primitive and wireframe parts of that same dialog.
How to combine them safely: Combining approaches.
Wireframes are copies; primitives are components
This is the most important non-obvious fact in the whole guide.- Primitives are real components.
VeltCommentDialogis a normal React component that renders a<velt-…>element. Wrap it in a MUI<Dialog>, a shadcn<Card>, anything: your library’s components keep working normally next to it. - Wireframes are cloned markup. Velt copies your slot markup into its own render tree. Any interactivity you attached (a React
onClick,useState, a stateful library component) does not run in the copy. Inside a wireframe, behavior comes only from Velt’s own slot components; your markup is the visual shell, and CSS classes are fine.
Edge cases and limitations.
Shadow DOM
Velt can render its UI inside a shadow DOM: an isolated bubble your global stylesheets cannot reach. It keeps Velt’s styles from clashing with your app, and it decides whether your CSS lands:- ✅ CSS variables (
--velt-*) cross the boundary, so theming always works. - ❌ Class and element selectors do not: those need
shadowDom={false}(orinjectCustomCss).
Setup; full detail in CSS.
Where to go next
Start with theDecision tree to pick the right layer or layer mix for your specific design. This is the spine of the guide; start every new design there.
Working from a Figma file? The UI Customization Plugin can run the decision for you and build a verified result (comments + notifications).
