diff --git a/docs/Project.toml b/docs/Project.toml
index e79e44aba..f725f467a 100644
--- a/docs/Project.toml
+++ b/docs/Project.toml
@@ -3,6 +3,7 @@ Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
+DocumenterMermaid = "a078cd44-4d9c-4618-b545-3ab9d77f9177"
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
LogDensityProblems = "6fdf6af0-433a-55f7-b3ed-c6c6e0b8df7c"
diff --git a/docs/make.jl b/docs/make.jl
index ebf15df06..b0168076d 100644
--- a/docs/make.jl
+++ b/docs/make.jl
@@ -8,6 +8,7 @@ using DynamicPPL: AbstractPPL
# in the doctest as run in `test/runtests.jl`, and so we need to stay
# consistent with that.
using Distributions
+using DocumenterMermaid
# Doctest setup
DocMeta.setdocmeta!(DynamicPPL, :DocTestSetup, :(using DynamicPPL); recursive=true)
diff --git a/docs/src/assets/images/transformations-assume-without-istrans.dot b/docs/src/assets/images/transformations-assume-without-istrans.dot
deleted file mode 100644
index 6eb6865c3..000000000
--- a/docs/src/assets/images/transformations-assume-without-istrans.dot
+++ /dev/null
@@ -1,17 +0,0 @@
-digraph {
- # `assume` block
- subgraph cluster_assume {
- label = "assume";
- fontname = "Courier";
-
- assume [shape=box, label=< assume(varinfo, @varname(x), Normal())>, fontname="Courier"];
- without_linking_assume [shape=box, label="f = from_internal_transform(varinfo, varname, dist)", fontname="Courier"];
- with_logabsdetjac [shape=box, label="x, logjac = with_logabsdet_jacobian(f, assume_internal(varinfo, varname, dist))", fontname="Courier"];
- return_assume [shape=box, label=< return x, logpdf(dist, x) - logjac, varinfo >, style=dashed, fontname="Courier"];
-
- assume -> without_linking_assume;
- without_linking_assume -> with_logabsdetjac;
- with_logabsdetjac -> return_assume;
- }
-}
-
diff --git a/docs/src/assets/images/transformations-assume-without-istrans.dot.png b/docs/src/assets/images/transformations-assume-without-istrans.dot.png
deleted file mode 100644
index f58727ad2..000000000
Binary files a/docs/src/assets/images/transformations-assume-without-istrans.dot.png and /dev/null differ
diff --git a/docs/src/assets/images/transformations-assume-without-istrans.dot.svg b/docs/src/assets/images/transformations-assume-without-istrans.dot.svg
deleted file mode 100644
index be91de2ad..000000000
--- a/docs/src/assets/images/transformations-assume-without-istrans.dot.svg
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
-
-
diff --git a/docs/src/assets/images/transformations-assume.dot b/docs/src/assets/images/transformations-assume.dot
deleted file mode 100644
index f1952b63f..000000000
--- a/docs/src/assets/images/transformations-assume.dot
+++ /dev/null
@@ -1,22 +0,0 @@
-digraph {
- # `assume` block
- subgraph cluster_assume {
- label = "assume";
- fontname = "Courier";
-
- assume [shape=box, label=< assume(varinfo, @varname(x), Normal())>, fontname="Courier"];
- iflinked_assume [label=< if istrans(varinfo, varname) >, fontname="Courier"];
- without_linking_assume [shape=box, label="f = from_internal_transform(varinfo, varname, dist)", fontname="Courier"];
- with_linking_assume [shape=box, label="f = from_linked_internal_transform(varinfo, varname, dist)", fontname="Courier"];
- with_logabsdetjac [shape=box, label="x, logjac = with_logabsdet_jacobian(f, assume_internal(varinfo, varname, dist))", fontname="Courier"];
- return_assume [shape=box, label=< return x, logpdf(dist, x) - logjac, varinfo >, style=dashed, fontname="Courier"];
-
- assume -> iflinked_assume;
- iflinked_assume -> without_linking_assume [label=< false>, fontname="Courier"];
- iflinked_assume -> with_linking_assume [label=< true>, fontname="Courier"];
- without_linking_assume -> with_logabsdetjac;
- with_linking_assume -> with_logabsdetjac;
- with_logabsdetjac -> return_assume;
- }
-}
-
diff --git a/docs/src/assets/images/transformations-assume.dot.png b/docs/src/assets/images/transformations-assume.dot.png
deleted file mode 100644
index b8b0ec734..000000000
Binary files a/docs/src/assets/images/transformations-assume.dot.png and /dev/null differ
diff --git a/docs/src/assets/images/transformations-getindex-with-dist.dot b/docs/src/assets/images/transformations-getindex-with-dist.dot
deleted file mode 100644
index e44fc0ce6..000000000
--- a/docs/src/assets/images/transformations-getindex-with-dist.dot
+++ /dev/null
@@ -1,20 +0,0 @@
-digraph {
- # `getindex` block
- subgraph cluster_getindex {
- label = "getindex";
- fontname = "Courier";
-
- getindex [shape=box, label=< x = getindex(varinfo, @varname(x), Normal()) >, fontname="Courier"];
- iflinked_getindex [label=< if istrans(varinfo, varname) >, fontname="Courier"];
- without_linking_getindex [shape=box, label="f = from_internal_transform(varinfo, varname, dist)", fontname="Courier"];
- with_linking_getindex [shape=box, label="f = from_linked_internal_transform(varinfo, varname, dist)", fontname="Courier"];
- return_getindex [shape=box, label=< return f(getindex_internal(varinfo, varname)) >, style=dashed, fontname="Courier"];
-
- getindex -> iflinked_getindex;
- iflinked_getindex -> without_linking_getindex [label=< false>, fontname="Courier"];
- iflinked_getindex -> with_linking_getindex [label=< true>, fontname="Courier"];
- without_linking_getindex -> return_getindex;
- with_linking_getindex -> return_getindex;
- }
-}
-
diff --git a/docs/src/assets/images/transformations-getindex-with-dist.dot.png b/docs/src/assets/images/transformations-getindex-with-dist.dot.png
deleted file mode 100644
index 381ba45a2..000000000
Binary files a/docs/src/assets/images/transformations-getindex-with-dist.dot.png and /dev/null differ
diff --git a/docs/src/assets/images/transformations-getindex-without-dist.dot b/docs/src/assets/images/transformations-getindex-without-dist.dot
deleted file mode 100644
index 38dd296e1..000000000
--- a/docs/src/assets/images/transformations-getindex-without-dist.dot
+++ /dev/null
@@ -1,20 +0,0 @@
-digraph {
- # `getindex` block
- subgraph cluster_getindex {
- label = "getindex";
- fontname = "Courier";
-
- getindex [shape=box, label=< x = getindex(varinfo, @varname(x)) >, fontname="Courier"];
- iflinked_getindex [label=< if istrans(varinfo, varname) >, fontname="Courier"];
- without_linking_getindex [shape=box, label="f = from_internal_transform(varinfo, varname)", fontname="Courier"];
- with_linking_getindex [shape=box, label="f = from_linked_internal_transform(varinfo, varname)", fontname="Courier"];
- return_getindex [shape=box, label=< return f(getindex_internal(varinfo, varname)) >, style=dashed, fontname="Courier"];
-
- getindex -> iflinked_getindex;
- iflinked_getindex -> without_linking_getindex [label=< false>, fontname="Courier"];
- iflinked_getindex -> with_linking_getindex [label=< true>, fontname="Courier"];
- without_linking_getindex -> return_getindex;
- with_linking_getindex -> return_getindex;
- }
-}
-
diff --git a/docs/src/assets/images/transformations-getindex-without-dist.dot.png b/docs/src/assets/images/transformations-getindex-without-dist.dot.png
deleted file mode 100644
index a869326d3..000000000
Binary files a/docs/src/assets/images/transformations-getindex-without-dist.dot.png and /dev/null differ
diff --git a/docs/src/assets/images/transformations.dot b/docs/src/assets/images/transformations.dot
deleted file mode 100644
index 2ca40ddd0..000000000
--- a/docs/src/assets/images/transformations.dot
+++ /dev/null
@@ -1,28 +0,0 @@
-digraph {
- # Nodes.
- tilde_node [shape=box, label="x ~ Normal()", fontname="Courier"];
- base_node [shape=box, label=< vn = @varname(x)
dist = Normal()
x, vi = ... >, fontname="Courier"];
- assume [shape=box, label="assume(vn, dist, vi)", fontname="Courier"];
-
- iflinked [label=< if istrans(vi, vn) >, fontname="Courier"];
-
- without_linking [shape=box, label="f = from_internal_transform(vi, vn, dist)", styled=dashed, fontname="Courier"];
- with_linking [shape=box, label="f = from_linked_internal_transform(vi, vn, dist)", styled=dashed, fontname="Courier"];
-
- with_logabsdetjac [shape=box, label="x, logjac = with_logabsdet_jacobian(f, getindex_internal(vi, vn, dist))", styled=dashed, fontname="Courier"];
- return [shape=box, label=< return x, logpdf(dist, x) - logjac, vi >, styled=dashed, fontname="Courier"];
-
- # Edges.
- tilde_node -> base_node [style=dashed, label=< @model>, fontname="Courier"]
- base_node -> assume [style=dashed, label=" tilde-pipeline", fontname="Courier"];
-
- assume -> iflinked;
-
- iflinked -> without_linking [label=< false>, fontname="Courier"];
- iflinked -> with_linking [label=< true>, fontname="Courier"];
-
- without_linking -> with_logabsdetjac;
- with_linking -> with_logabsdetjac;
-
- with_logabsdetjac -> return;
-}
diff --git a/docs/src/assets/images/transformations.dot.png b/docs/src/assets/images/transformations.dot.png
deleted file mode 100644
index 1343a81e7..000000000
Binary files a/docs/src/assets/images/transformations.dot.png and /dev/null differ
diff --git a/docs/src/assets/images/transformations.dot.svg b/docs/src/assets/images/transformations.dot.svg
deleted file mode 100644
index 1e98f612d..000000000
--- a/docs/src/assets/images/transformations.dot.svg
+++ /dev/null
@@ -1,124 +0,0 @@
-
-
-
-
-
diff --git a/docs/src/internals/transformations.md b/docs/src/internals/transformations.md
index d948290ec..ae629dbd6 100644
--- a/docs/src/internals/transformations.md
+++ b/docs/src/internals/transformations.md
@@ -41,10 +41,35 @@ But to ensure that we stay consistent with what the user expects, DynamicPPL.jl
In the end, we'll end up with something that looks like this:
-```@raw html
-