Kindly is a convention from the Clojure ecosystem for annotating values with rendering intent. Babqua supports Kindly metadata, so the same code patterns work in both Babashka+Quarto and Clojure+Clay.
Without an annotation, results display as code output:
One exception: (def x ...) returns the var (#'user/x), which is noise rather than information. Babqua suppresses var results by default, so a setup block like (def magic-number 42) is hidden without needing #| output: hidden. Reference the binding in a later block to display its value.
Add Kindly metadata to control how a value is rendered.
3.1^:kind/hiccup — HTML from data
Converts a hiccup vector to HTML. Hiccup represents HTML as nested Clojure vectors:
The vector [:tag {:attr "value"} content] becomes <tag attr="value">content</tag>. Babashka has hiccup2.core built in, so the HTML rendering happens on the Babashka side, not in the Lua filter.
3.2^:kind/html — raw HTML
Renders a string as raw HTML. Since strings can’t hold metadata in Clojure, wrap the expression in a vector:
^:kind/html["<b>bold</b> and <em>italic</em>"]
bold and italic
The vector is automatically unwrapped — Babqua extracts the first element for rendering.
3.3^:kind/md — markdown
Renders a string as markdown. Same wrapping rule as kind/html:
^:kind/md["| a | b |\n| --- | --- |\n| 1 | 2 |"]
a
b
1
2
3.4^:kind/hidden — suppress output
Evaluates the code but hides the result. The code itself is still shown. Useful for setup like defining helper functions:
^:kind/hidden[(def my-data [123])]
3.5^:kind/mermaid — Mermaid diagrams
Renders a string as a Mermaid diagram. The Mermaid JS library is loaded automatically from a CDN (content delivery network):
^:kind/mermaid["graph LR\n A[Start] --> B{Decision}\n B -->|Yes| C[OK]\n B -->|No| D[Cancel]"]
3.6^:kind/graphviz — Graphviz diagrams
Renders a string as a Graphviz DOT diagram. The viz-js library is loaded from CDN; no local Graphviz install needed:
^:kind/graphviz["digraph { rankdir=LR; A -> B -> C; A -> C; }"]
ECharts refuses to render to a size-less container, so Babqua applies a default of 600 × 400 pixels. Override with width=/height= fence attributes or :kindly/options.
3.12^:kind/cytoscape — Cytoscape graphs
Renders a map as a Cytoscape graph. The spec needs :elements (nodes and edges); Babqua sets the container automatically:
The table is rendered on the Babashka side (via hiccup) and inserted as raw HTML, so styling can target it the same way as any other HTML table.
3.15 Annotating in library functions
The ^:kind/... reader syntax attaches metadata at the call site. But metadata can also be attached programmatically with with-meta or vary-meta, which means library functions can annotate their return values. The caller doesn’t need to know about the rendering — the function handles it.
For example, a function that builds an SVG bar chart and tags it as hiccup:
Now simply calling the function renders the chart — no annotation needed at the call site:
(bar-chart ["a""b""c"] [102015])
This is a key idea behind Kindly: rendering intent lives in the metadata of values, not in the document markup. Libraries can provide visualization functions that render correctly in any Kindly-aware tool — Babqua, Clay, Janqua, or others.
3.16 Why wrap strings in vectors?
In Clojure (and Babashka), metadata can only be attached to collections — vectors, maps, sets — not to primitive types like strings or numbers. So ^:kind/html "hello" won’t work.
The convention is to wrap the value in a vector:
^:kind/html ["<b>hello</b>"]
hello
Babqua automatically unwraps the vector for all string-valued kinds (kind/html, kind/md, kind/mermaid, kind/graphviz, kind/tex, kind/code), extracting the first element for rendering.