Audience: AI coding agents (and teams running them). This page is part of the deterministic agent workflow for building and verifying Velt UI customizations. Customizing by hand? Start with the Approaches and Feature Guides.
Use the same standard whether verification is automated or manual: cover every mapped element, every required state, and every behavior contract before marking the surface done.
What you need first (preconditions)
You can’t verify what isn’t rendering. Before anything else:- Velt is initialized. The app boots, the user is identified, documents are set, and the default version of this surface renders. Gate logic on
useVeltInitState()if needed. (SeeDebugging.) - The surface has data. Create a comment / open a thread / trigger a notification through the app’s own UI so the surface has something to show. If you genuinely can’t seed data, verify the empty / loading state only and record that limitation in the report.
- You have the design reference for this surface (the Figma frame / screenshot) and know which states it specifies.
The flow
Step 1: Drive every state the design specifies
For each visual goal, render the surface in each state the design covers and capture it. The states that matter per surface are in the matrix below. Common ones:- default, hover, selected/focused
- empty, loading / skeleton, filtered-to-zero
- unread, resolved (and
OPEN/IN_PROGRESS/RESOLVEDif the design themes by status) - long content (truncation), private (if shown)
["default","resolved"] is only checkable once you’ve driven both.
Step 2: Whole-surface measured check + visual gate (match the design)
For each state, do all four: this is the gate:- Consume or assemble the complete checklist (R26: do not hand-pick samples). Build the checklist from every distinct styled appearance in the design (deduped by its declarations: the teal mention, the placeholder, each filter row), every
mustSupplyslot, every mount-map part, and every required state. Resolve each element’s live selector by inspection: use the manifestcssClassesfor measured leaves and inspect to the leaf for the rest. Add relations + gaps from the manifestlayout. Produce a disposition for every checklist element plus the per-state visual artifact. A report that samples fewer elements than the checklist is INCOMPLETE, not PASS, so the loop cannot end on it. - Gross-mismatch pre-check first: compare total content height / element count / surface extents vs the designSpec. Grossly off ⇒ FAIL immediately (don’t let per-element props “pass” on a broken surface).
- Measure live browser output: read each live node’s
getComputedStyleplus surface-relativegetBoundingClientRect(never the 0-size*-wireframetemplate) and produce a delta table with a verdict covering style (Delta E below 2, ±1px, keywords exact) and layout (box ±2-3px, gaps, relations, missing or extra elements). - Visual side-by-side: a GATE: capture the full-surface screenshot beside the Figma frame and name every visible difference (density/spacing, name placement, filter as a box vs icon, hover actions revealed, unwanted banner). Any nameable difference ⇒ FAIL, then find the property/relation you didn’t measure and add it. A clean table with an obviously-wrong screenshot is still a FAIL.
width===0 ⇒ BLOCKED/FAIL. Every mustSupply slot must be present and carry the design’s content: an icon slot must contain the design’s exported SVG (compare identity), not a Velt default or hand-drawn glyph (R17 FAIL). A popup must be styled on its content slot, never its container/trigger (R23). Horizontal padding must not compound across nested wrappers (R22). No feature/prop whose UI the design doesn’t show (R24). Colours still must trace to a --velt-* token / documented class (an accidentally-matching hard-coded colour breaks in dark mode: fail it even if ΔE passes).
The delta table’s failing rows + the named visual differences ARE the feedback. Mark the goal met only when, for every state, the gross check is clean, the style + layout tables are empty, and the visual side-by-side has no nameable difference; otherwise not met, listing each diff.
Step 3: Behavior check (Velt still works)
Customizing presentation must never break Velt’s behavior: you never disabled it, so it must still work (R0, R7). Perform the surface’s real actions (in the matrix) and confirm each still functions: place a pin, open a dialog, reply, change status, filter, sidebar sync; open a notifications panel, switch tab, mark read, click through. If an action is dead, something was hidden with CSS instead of a prop (R7), interactivity was put in wireframe markup (R4), or a slot was dropped: fix it; it is not a “design gap.”Step 4: Rules-compliance scan (static, on the produced code)
Walk the Quick gate inRules against what you wrote. The checks that catch the most:
- R0: no hacks: no
setTimeout/MutationObserveron Velt internals, no scraped internal markup, no timing/DOM shims. - R1 / R2: exactly one
<VeltWireframe>; the live feature component is mounted. - R4 / R5: no
onClick/useState/ hooks inside wireframe markup; UI-library components wrap around primitives, not inside wireframes. - R6 / R7 / R8 / R9: selector CSS only with shadow off or
injectCustomCss; nodisplay:noneto remove features; one stylesheet; dark values scoped to:root[data-velt-theme="dark"]. - R10: every identifier (slot, prop, variable, class, hook, API) verified against
reference/. If it isn’t there, it doesn’t exist. - R11 / R16: files under
components/velt/ui-customization/; only this one surface touched this step. - Verified gotchas:
ThreadCardnested inBody → Threads; container slots declare their full child tree; correct shadow root-vs-nested handling; pin index/number filled viavelt-data;VeltCommentDialog, never the deprecatedVeltCommentThread. (All inWireframe components.)
Step 5: Verdict
Per-surface state & behavior matrix
The concrete “what to drive” for each v1 surface. Drive the states for the visual check (step 1-2); perform the behaviors for step 3. Verify only the states the design actually specifies, but never skip the behavior column.Comments
Notifications
After an SDK upgrade
Re-run the visual + rules checks. Variable-based theming (--velt-*) is upgrade-safe; class/selector overrides and wireframe slot names are the most drift-prone pieces, so re-verify them first (Cross-cutting concerns).
