Skip to content

Dev Tools Improvements

Branch: improve-dev-tools (Application-Frontend + Creative-Engine) Issue: #1836 | AF PR: #1858 | CE PR: #733

Completed

DataTracker Rewrite

Replaced flat last-mutation display with a recursive collapsible tree view.

New files:

  • src/components/DevTools/DataTracker.vue — main panel
  • src/components/DevTools/TreeNode.vue — recursive tree component

Features:

  • Recursive collapsible tree showing all block properties
  • Auto-expand and blue highlight on Vuex updateBlockValue mutations
  • Sticky parent headers (VS Code-style scroll context) with correct stacking
  • Sticky block-header bar showing block name, type badge, and expand/collapse toggle
  • Click-to-select with orange highlight and scroll-into-view
  • Color swatches for hex/rgba string values
  • Expand all / Collapse all toggle button
  • Deep-clone block data (JSON.parse(JSON.stringify())) to strip Vue 2 reactivity wrappers
  • blockKey counter forces fresh TreeNodes on block switch (no stale expanded state)
  • i18n keys under devTools section in en.js

Key technical decisions:

  • TreeNode must be a .vue SFC file — Vue 2 runtime-only build (used by Vite) cannot compile inline template strings
  • Block data deep-cloned because Vue 2 reactive objects don't always iterate correctly with v-for
  • changedPath watcher uses immediate: true so newly rendered children (after parent expands) also auto-expand for deeply nested changes
  • Validation auto-expand: FormConfigurationMixin emits entire validation object at path 'validation' (not 'validation.required'), so TreeNode expands on both exact match and prefix match
  • Mutation path uses indexOf instead of startsWith to handle sub-blocks (e.g. formProperties.formSubmitButtonProperties.stateConfig.hover.x)
  • Sticky offset: block-header height (40px) + depth * 22px per level

DevToolPanel — Shared Wrapper

All three dev tool panels (DataTracker, JSON Viewer, JSON Provider) now use a shared DevToolPanel.vue wrapper component.

File: src/components/DevTools/DevToolPanel.vue

Features:

  • Drag via panel header
  • Resize from 8 handles (4 edges + 4 corners) with minimum size constraints (300×200)
  • Pop-out to separate browser window (experimental — styles/reactivity incomplete)
  • Fullscreen toggle (via scoped slot — children can provide custom button)
  • Close button
  • scrollToTop() method exposed via ref
  • left/top CSS positioning for natural drag/resize behavior

Scoped slot: header-actions provides { isFullscreen, toggleFullscreen } to children, so each tool can inject custom buttons (type toggle, validation badges, fullscreen) alongside the shared pop-out and close buttons.

JSON Tools Migration to DevToolPanel

Refactored CreativeJSONViewerV2.vue and CreativeJSONProviderV2.vue to use the shared DevToolPanel wrapper.

Changes:

  • Removed all custom drag, resize, and positioning code from both components
  • Removed fullscreen logic (now handled by DevToolPanel)
  • Moved tool-specific buttons (type toggle, fullscreen, validation badges) to header-actions scoped slot
  • Content (search bar, JSON display/textarea, footer) rendered as default slot with flex layout
  • Consistent dark aesthetic across all three dev tools
  • Updated JSONSearchBar.vue colors to match DevToolPanel theme
  • Added i18n keys for all user-visible strings in JSON tools

Removed code per component: ~250 lines of drag/resize/position/fullscreen logic + CSS

V2 JSON Components

  • CreativeJSONProviderV2.vue — JSON input with validation, bracket auto-close, search
  • CreativeJSONViewerV2.vue — JSON display with syntax highlighting, search, type toggle (Plain/Composed), copy, double-click edit
  • JSONSearchBar.vue — reusable search component with match navigation

Analytics Monitor (new)

Real-time panel showing all analytics events from Creative-Engine via postMessage bridge.

File: src/components/DevTools/AnalyticsMonitor.vue

Features:

  • Event feed with type badges (event / flow / count / metric / init / click)
  • Live counters: elapsed, in view (from CE), actions, bg clicks, flow seq, events
  • Milestone bar: loaded, viewable, 1st click, links, goal, end
  • Click debug capture showing element selector, shortcode, innerText, and full CE handler chain
  • Sub-type filter dropdown
  • Glossary descriptions for headerClick and backgroundClick count metrics
  • Baseline reset on creative rebuild so counters don't show negatives
  • Accurate secondsToActive on preview refresh (CE resets loadTimestamp in devMode)
  • Expandable event details with raw payload
  • Refresh button that reloads creative and starts clean recording

CE integration (Creative-Engine PR #733)

  • Analytics event bridge — forwards all analytics events to parent via postMessage in devMode
  • Flow event enrichment with component name/text
  • Click debug capture with full handler chain analysis and innerText fallback
  • Live visibility postMessage (cavai-devtools-visibility) with generation counter for accurate viewable tracking across rebuilds
  • Reset loadTimestamp and creativeClickedOnce on rebuild in devMode for accurate metrics

Tool switching

  • Dropdown in panel title to switch between all dev tools
  • Position, size, and fullscreen state persist across switches
  • Pop-out reuses existing popup when switching tools
  • Click-outside closes the dropdown

DevTools.vue

  • Updated to use V2 components, DataTracker, and Analytics Monitor
  • Rounded corner styling
  • Tool switching dropdown

Planned

Extract CE devtools code into its own module (from PR #733 review)

McSneaky flagged that the analytics bridge, click debug capture, and visibility tracking code in Creative.vue is a lot of inline code. Should be extracted to a separate module.

Goal: Move all devtools-related logic out of Creative.vue into a dedicated module (e.g. src/utils/devtools.ts or src/composables/useDevtools.ts).

Bonus: Dynamic import so the code is only loaded when devMode is active — keeps the production bundle clean. Could use import() to lazy-load the module when devMode is detected:

js
if (this.devMode) {
  const { setupDevtools } = await import('./devtools')
  setupDevtools(this)
}

Scope:

  • Click debug capture (click handler → structured debug info → postMessage)
  • Analytics event bridge (all analytics events → postMessage with enrichment)
  • Live visibility tracking (secondsInView / viewable state → postMessage with generation counter)

Operator/flow data inspection

  • Extend DataTracker to inspect operator data, not just blocks
  • Need to investigate how operators are stored in Vuex (getters, selection state)
  • Would make DataTracker useful for debugging flow logic, not just visual block properties

Pop-out improvements

  • Current approach re-mounts a new Vue instance in the popup — styles and reactivity break
  • Better approach: DOM adoption (appendChild to move real DOM node into popup window), preserving Vue reactivity and scoped styles
  • Would allow fullscreen dev tools on a second monitor

Performance profiling tool

  • Show render times for blocks, reflow counts
  • Monitor postMessage frequency between AF and CE
  • Help identify performance bottlenecks in complex creatives

Console/log panel (started - see DOM Inspector below)

In Progress

DOM Inspector + Console (branch: dom-inspector)

Branch: dom-inspector (AF + CE)

Built-in iframe DOM inspector solving the browser DevTools focus-loss problem on iframe refresh. Three tabs:

Elements tab:

  • Recursive DOM tree with Chrome DevTools-style attribute display (id, class, src, href, type)
  • Click-to-inspect with pointer-blocking overlay (prevents creative interaction during inspect)
  • Auto-expand ancestors and scroll-into-view on selection
  • Layout badges: FLEX, GRID, ABS, FIXED, REL, STICKY, CLIP
  • Shortcode badges mapping DOM classes to Cavai block names (t1 -> textProperties-1)
  • Breadcrumb ancestor chain (clickable, hover-to-highlight)
  • Element info: size, position, position context ("relative to ..."), flex/grid child info, stacking context detection
  • MutationObserver auto-refresh (filters inspector overlay mutations to prevent tree collapse)

Console tab:

  • Captured console.log/warn/error from CE via postMessage (consoleInterceptor.ts)
  • Eval expressions in iframe scope
  • Command history (up to 50), color-coded output, max 500 entries with auto-scroll

Styles tab:

  • Box model diagram (margin/border/padding/content)
  • Context insights: position info with offsets, z-index + stacking context, overflow clipping
  • Flex/Grid parent context (direction, justify, align, self flex/order)
  • Computed style groups filtered by non-default values

CE side: src/devtools/consoleInterceptor.ts - monkey-patches window.console in devMode, safe serialization (circular refs, DOM nodes, max depth 5)

Status: Functional, needs more testing and polish. Known areas to improve:

  • Indent guide lines in tree (attempted, reverted due to recursive component CSS complexity)
  • Pop-out support not yet tested with this tool

Ideas to explore

Search/filter in Elements tree

  • Filter DOM tree by tag, class, attribute, or text content
  • Use case: find all <img> elements in the creative, or track a specific video element's class changes live as it transitions between states
  • Live filtering: tree updates in real-time as the creative DOM mutates, so you can watch attributes/classes change on filtered elements without manually navigating

Flow stepping from DOM Inspector

  • Step forward/backward through flow steps directly from the inspector panel
  • Navigate the creative's flow without clicking inside the iframe -- control flow progression purely from dev tools
  • Watch the DOM tree update live as each step renders, see which elements appear/disappear/change
  • Would need to send flow navigation commands to CE (postMessage or direct iframe access)
  • Combines well with search/filter: filter to a specific element, then step through flow and watch it change

These need investigation -- not sure how CE exposes flow navigation, or whether we can trigger step transitions from AF side.

Internal documentation