Liking cljdoc? Tell your friends :D

re-frame.vertica

re-frame.vertica is a Chrome DevTools inspector that follows one selected UI element through a vertical slice of a re-frame application:

app-db paths → subscriptions → props → Reagent components → DOM element

It shows the data and render dependencies that contributed to the selected element, rather than presenting the entire application as one global graph. The inspector is independent of re-frame-10x and can be used alongside it.

Install

Two matching pieces are required: the preload library runs inside the application, while the unpacked Chrome extension provides the DevTools panel. Keep both on the same released version.

1. Add the preload to the application

With deps.edn, add the released Clojars artifact:

{:deps
 {net.clojars.frknzd/re-frame.vertica {:mvn/version "0.2.0"}}}

For a shadow-cljs configuration that declares Maven dependencies directly:

{:dependencies
 [[net.clojars.frknzd/re-frame.vertica "0.2.0"]]}

Then add the public preload namespace to the development build:

{:builds
 {:app
  {:target :browser
   :devtools
   {:preloads [re-frame.vertica.preload]}}}}

Load the preload only in development. It must start before the application namespaces register their subscriptions, so restart the shadow-cljs build and reload the page after changing this setting. When it starts too late, the panel cannot recover the original subscription computation functions and reports the resulting partial trace.

2. Install the DevTools extension manually

  1. Open the repository's latest GitHub release.
  2. Download re-frame.vertica-devtools-vVERSION.zip. SHA256SUMS in the same release can be used to verify the download.
  3. Extract the ZIP to a permanent local directory. Do not delete that directory while the extension is installed.
  4. Open chrome://extensions in Chrome and enable Developer mode.
  5. Select Load unpacked, then choose the extracted directory containing manifest.json.
  6. Open DevTools on an application with the preload enabled and select the re-frame.vertica tab.

To upgrade, download and extract the new ZIP over the directory (or select a new directory), then click Reload on the extension card in chrome://extensions. Upgrade the application's Clojars dependency to the same version and rebuild it.

3. Inspect a vertical slice

Select an element in Chrome's Elements panel, or use Pick in the re-frame.vertica top bar. The panel locks onto the closest Reagent render owner and shows its app-db paths, subscriptions, live props, component ownership, and selected DOM element.

Opening the panel does not reuse an old Elements selection or draw its blue highlight; inspection begins with the next explicit Elements selection or Pick action. If the inspected page does not expose globalThis.__RE_FRAME_VERTICA__, the panel warns that the development build may be missing the preload and keeps retrying while the page reloads.

When a loaded ClojureScript source map contains the selected component's source, the top bar shows a ↗ file.cljs:line link. It opens the definition at the exact line and column using Chrome DevTools' configured resource handler, falling back to the Sources editor.

The top bar also provides parent, child, and sibling navigation; a refresh action; and a persistent setting for purple Reagent component boxes. Pick mode accepts Reagent roots only and suppresses page clicks while active. The selected element keeps its blue page highlight while the DevTools panel is open.

Value-preview truncation indicators are interactive; click … Show all to reveal the complete value. Subscription levels are collapsible; level 0 starts open and deeper levels start closed for each selection.

What is traced

The selected leaf component's direct subscriptions are render candidates. An ancestor subscription is included only when its output shares an immutable collection identity with a leaf argument or one of its nested collections. Primitive value equality is not treated as provenance.

Relevant layer-2 subscriptions are first replayed against read-tracking wrappers to discover concrete keyword, map, vector, set, record, sequence, reduction, destructuring, get, and get-in candidates. Each candidate is then perturbed independently in a cloned app-db, the affected subscription DAG is replayed, and the selected component's render closure is evaluated without committing React work. A path is confirmed only when the normalized visible Hiccup/React branch corresponding to the selected DOM element changes. Callback and ref identities are ignored, so newly allocated closures do not create false positives.

The APP-DB tree contains contributing paths and only the structural ancestors needed to reach them—no neighboring entries or unrelated context is added automatically. All paths use the same presentation. Scalar vector entries use a compact, wrapping index/value view while nested collections remain expandable. Whole-collection and all-entry traversals are loaded ten entries at a time; collection summaries and … more controls can be used repeatedly to drill into nested values. When a map, vector, or set has more than five entries and every direct entry contributes, it starts collapsed with its contributing entry count and can be expanded normally. The tree has no inspector-imposed depth, path-count, node-count, or edge-count limit. Because counterfactual fuzzing is finite, it establishes evidence for the current execution path rather than a mathematical proof over every possible application state.

Prop names are never shortened. When an inspected script's source map contains ClojureScript sourcesContent, re-frame.vertica recovers the component's original argument names, including destructuring and matching multi-arity signatures. If source text is unavailable, the panel keeps complete fallback labels such as arg 0 instead of guessing.

Subscription and app-db badges show the full leaf Reagent component name responsible for that dependency. Shared dependencies can therefore show more than one leaf badge without conflating their parent chains.

Some paths cannot be fully verified when data is transformed into a new object, was registered before the preload, or passes through unsupported reg-sub-raw, Subscription alpha, opaque custom derefables, disposed reactions, mutations, nondeterministic/throwing renders, unfamiliar fibers, or closed shadow roots. They remain in APP-DB with the same presentation as other contributing paths.

Tested compatibility

The automated suite and production fixtures use these versions:

PartTested version
Clojure1.12.0
ClojureScript1.12.42
shadow-cljs3.1.7
re-frame1.4.7
Reagent1.2.0
React / ReactDOM17.0.2 and 18.3.1
Transit CLJS0.8.280
Chrome build targetChrome 120 or newer
Node.js used by the build20.x
Leiningen used by CI2.12.0
Java used by CITemurin 21

React 17 and React 18 each have a separately compiled fixture. Other dependency versions may work, but are not part of the verified compatibility matrix. React 19, iframes, closed shadow roots, unresolved portals, and Firefox packaging are currently outside scope.

Privacy and protocol

The preload exposes globalThis.__RE_FRAME_VERTICA__ using protocol version 1. Communication stays between the inspected page and the local DevTools extension. No application data is sent to a service by this project.

Snapshots are not quantity-capped, so selecting a component backed by an exceptionally large dependency set can take significant time and memory. Values, reactions, fibers, and DOM objects remain inside the inspected page and are accessed through snapshot-scoped opaque tokens. Counterfactual app-db values never replace the live app-db, and temporarily substituted subscription and argv fields are restored in finally. A protocol mismatch is rejected with an upgrade message, which is why the preload and extension versions should stay aligned.

Develop and verify

Requirements are Node.js 20+, npm, Java, Leiningen, Clojure CLI, and Chrome.

npm ci
npm run verify

npm run verify runs the JVM shared-model tests, ClojureScript tracking tests, extension protocol and parser tests, the production preload and extension build, and both React fixture builds. The unpacked output is written to dist/extension.

For a manual fixture test, serve either dist/fixtures/react17 or dist/fixtures/react18 over HTTP, load dist/extension as an unpacked extension, and open its re-frame.vertica panel. Native Elements selection and cross-panel inspect(element) are not reliably exposed to extension automation, so those interactions remain part of the manual smoke test.

License

MIT

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close