Liking cljdoc? Tell your friends :D

hive-cljs

ClojureScript development as a hive IAddon: shadow-cljs build status, cljs-eval, Playwright e2e scenarios and build→e2e watching, driven by config in your project root.

One addon. One cljs subdomain on the code tool. Three ports.

Runtime assertions are pinned to the page the scenario drives, and a step that could not be attempted is :incomplete — never a silent pass.

Documentation

Setting up a fresh projectnothing → a green scenario, with the traps that cost real time
Configuration reference.hive-project.edn vs hive-cljs.edn, every key, every default
Step referencethe browser + runtime vocabulary, semantics, adding a kind
Mounting in a hostwiring into hive-mcp, why a subdomain, diagnosing a silent mount
ArchitectureCPPB layers, the ports, extension points
Runnable examplea wired shadow-cljs + re-frame app you can cljs e2e run against

Why not just a build-status tool

A scenario asserts on the DOM and the live re-frame runtime in the same step vector:

[[:goto "/"]
 [:click "#go"]
 [:expect-text "#hi" "Hello, pedro"]      ; browser  → IBrowserDriver
 [:expect-sub [:current-user] "some?"]    ; runtime  → ICljsEval
 [:expect-db  [:user] "some?"]]

:expect-sub / :expect-db / :dispatch / :eval-cljs are evaluated inside the running application over shadow's nREPL. Everything else drives a real browser.

That split is also a debugging instrument: :expect-text red while :expect-sub green localises a bug to rendering rather than state.

For that reading to be trustworthy the runtime assertion has to be about the page the scenario is driving — so hive-cljs stamps the page it opens and pins evaluation to it. Otherwise any other connected runtime (a stray tab, a forgotten headless browser, the shadow UI) answers instead, and the scenario grades the wrong page while reporting green.

Quick start

shadow-cljs.edn supplies the two ports:

{:deps true
 :nrepl {:port 7889}          ; runtime channel
 :dev-http {8280 "public"}    ; what the browser opens
 :builds {:app {:target :browser ...}}}

Config — in your existing .hive-project.edn:

{:project-id "my-app"
 :hive.cljs  {:shadow {:nrepl-port 7889}
              :builds {:app {:http-port 8280}}}}

…or in a standalone hive-cljs.edn. Both work; both together merge, with the dedicated file winning. A single build id is the only required key.

Either file is found by walking up from wherever you invoked, so a subdirectory works. A workspace can hold shared defaults, but a child inherits them only by asking: :hive.cljs/inherit true. Values can come from the environment with #hive/env PORT.

Then, with shadow-cljs watch app running:

code {command: "cljs doctor",  directory: "/path/to/my-app"}
code {command: "cljs e2e run", directory: "/path/to/my-app", scenario: "login"}
code {command: "cljs watch start", directory: "/path/to/my-app"}

Full walkthrough: docs/setup.md. Working code to copy from: example/ — both config sources, both assertion channels, the input vocabulary and the watcher, in one small app.

Tool surface

SubcommandDoes
cljs doctorvalidate config, report per-port connectivity and which runtimes are attached
cljs stalenessis the cached config still current, and does the server serve our builds
cljs status [build]build verdict — one build or all
cljs compile <build>one compile cycle, returns the verdict
cljs eval <build> <code>evaluate cljs in the running runtime
cljs e2e list \| runrun a scenario (scenario) or a tag set (tags)
cljs watch start \| stop \| statuscouple build success to e2e runs
cljs helpsubcommand index

All accept directory (project root; defaults to cwd).

In a test suite

(require '[hive-cljs.test-api :as cljs-e2e])

(deftest login-works
  (let [res (cljs-e2e/run-scenario! project-root :login)]
    (is (cljs-e2e/passed? res) (cljs-e2e/explain res))))

Same execution path as the tool and the watcher. See setup.md.

Installing

One line in the host's local.deps.edn:

io.github.hive-agi/hive-cljs {:mvn/version "0.1.1"}

…or, when hacking on hive-cljs itself, #:local{:root "../hive-cljs"}.

Batteries included — the relay transport, nREPL client and browser driver all ride in on hive-cljs's own :deps. The host declares nothing about our vendors. Details and the reasoning: docs/hosting.md.

Requirements

  • a running shadow-cljs server (shadow-cljs watch <build>) for build status and e2e
  • :nrepl-port in the config for the runtime channel, plus a browser with the app open so a JS runtime is connected — a scenario's :goto handles that itself

Testing

clojure -M:test    # 122 tests, 568 assertions — stubs only, no vendors needed

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