diff --git a/crates/geormerge-demo/README.md b/crates/geormerge-demo/README.md
index 91e2125..d57ee6b 100644
--- a/crates/geormerge-demo/README.md
+++ b/crates/geormerge-demo/README.md
@@ -1,6 +1,6 @@
## Geomerge Demo
-This crate demonstrates storing and reading data with the `geomerge` submodule.
+This demo show how to store and read data from Geomerge.
The demo
1. loads the compiled `paths.json` schema
@@ -10,6 +10,8 @@ The demo
5. persists the store to bytes
6. reloads it and checks that the restored store matches the original.
+
+
### Run
```sh
diff --git a/crates/geormerge-demo/docs/diagrams/make_figures.sh b/crates/geormerge-demo/docs/diagrams/make_figures.sh
new file mode 100644
index 0000000..c688dcc
--- /dev/null
+++ b/crates/geormerge-demo/docs/diagrams/make_figures.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# You need to have Graphviz installed to run this script
+# On Debian-based OSes, you can install it using: sudo apt-get install graphviz
+
+# Directory containing .dot files (with default value)
+ASSET_DIR=${1:-"."}
+
+# Make figures from .dot files
+for f in "${ASSET_DIR}"/*.dot; do
+ dot -Tsvg "$f" -o "${f%.dot}.svg"
+done
diff --git a/crates/geormerge-demo/docs/diagrams/workflow.dot b/crates/geormerge-demo/docs/diagrams/workflow.dot
new file mode 100644
index 0000000..addc8af
--- /dev/null
+++ b/crates/geormerge-demo/docs/diagrams/workflow.dot
@@ -0,0 +1,133 @@
+digraph GeomergeDemoWorkflow {
+fontname = "Helvetica,Arial,sans-serif"
+layout = dot
+rankdir = LR
+ranksep = 0.9;
+nodesep = 0.7;
+splines = true;
+compound = true;
+bgcolor = "white"
+
+node [
+fontname = "Helvetica,Arial,sans-serif",
+shape = box,
+style = "filled,rounded",
+color = "#555555",
+fillcolor = "white",
+penwidth = 1.5
+]
+edge [
+fontname = "Helvetica,Arial,sans-serif",
+color = "#333333",
+fontsize = 9,
+fontcolor = "#555555",
+labeldistance = 2.0,
+penwidth = 1.2
+]
+
+subgraph cluster_inputs {
+label = "Inputs"
+style = "dashed"
+color = "#888888"
+fontcolor = "#555555"
+margin = 18
+paths_schema [label = "paths.json\n(compiled schema)", fillcolor = "#E8F4FD", color = "#2196F3"]
+fixture_rows [label = "Fixture Rows\n(graphs, vertices, edge)", fillcolor = "#E8F4FD", color = "#2196F3"]
+}
+
+subgraph cluster_demo {
+label = "geormerge-demo (run_demo)"
+style = "rounded"
+color = "#666666"
+fontcolor = "#333333"
+bgcolor = "#FAFAFA"
+margin = 20
+
+subgraph cluster_loading {
+label = "Theory Loading"
+style = "dashed"
+color = "#9C27B0"
+fontcolor = "#7B1FA2"
+margin = 14
+load_theory [label = "load_paths_theory\n(serde_json)", fillcolor = "#F3E5F5", color = "#9C27B0"]
+flat_theory [label = <
+| FlatTheory |
+| • 10 tables |
+| • 12 laws |
+
>, fillcolor = "#F3E5F5", color = "#9C27B0", shape = box]
+}
+
+subgraph cluster_store {
+label = "Store and Transaction"
+style = "dashed"
+color = "#4CAF50"
+fontcolor = "#388E3C"
+margin = 14
+build_store [label = "Store::try_from_theory", fillcolor = "#E8F5E9", color = "#4CAF50"]
+transact [label = <
+| add_paths_data (transact) |
+| • append Graphs rows |
+| • append G0, G1 rows |
+| • append G.V vertices |
+| • append G.E edge |
+
>, fillcolor = "#E8F5E9", color = "#4CAF50", shape = box]
+validate [label = "Law Validation\n(append_row_validated)", fillcolor = "#E8F5E9", color = "#4CAF50"]
+assert_edge [label = "assert_edge_was_stored\n(row count, cells)", fillcolor = "#E8F5E9", color = "#4CAF50"]
+}
+
+subgraph cluster_persist {
+label = "Persistence Round Trip"
+style = "dashed"
+color = "#FF9800"
+fontcolor = "#F57C00"
+margin = 14
+dump_before [label = "store.dump()\n(before persist)", fillcolor = "#FFF3E0", color = "#FF9800"]
+encode [label = "pst::encode_store\n-> bytes", fillcolor = "#FFF3E0", color = "#FF9800"]
+decode [label = "pst::decode_store\n-> restored Store", fillcolor = "#FFF3E0", color = "#FF9800"]
+compare [label = "dump equality check", fillcolor = "#FFF3E0", color = "#FF9800"]
+}
+}
+
+subgraph cluster_report {
+label = "Report"
+style = "dashed"
+color = "#888888"
+fontcolor = "#555555"
+margin = 18
+demo_report [label = <
+| DemoReport |
+| • table_count, law_count |
+| • graph, vertex, edge counts |
+| • edge endpoints |
+| • persisted_bytes |
+
>, fillcolor = "#ECEFF1", color = "#607D8B", shape = box]
+stdout [label = "stdout\n(println! lines)", fillcolor = "#ECEFF1", color = "#607D8B"]
+}
+
+// Inputs into loading
+paths_schema -> load_theory [label = "include_str!", color = "#2196F3"]
+load_theory -> flat_theory [color = "#9C27B0"]
+
+// Loading into store
+flat_theory -> build_store [color = "#9C27B0"]
+build_store -> transact [color = "#4CAF50"]
+fixture_rows -> transact [style = "dashed", color = "#2196F3"]
+
+// Transaction internals
+transact -> validate [color = "#4CAF50"]
+validate -> transact [style = "dashed", label = "row ids", color = "#4CAF50"]
+transact -> assert_edge [color = "#4CAF50"]
+
+// Into persistence
+assert_edge -> dump_before [color = "#FF9800"]
+dump_before -> encode [color = "#FF9800"]
+encode -> decode [label = "bytes", color = "#FF9800"]
+decode -> compare [color = "#FF9800"]
+dump_before -> compare [style = "dashed", label = "expected", color = "#FF9800"]
+
+// Out to report
+compare -> demo_report [color = "#607D8B"]
+flat_theory -> demo_report [style = "dashed", label = "counts", color = "#607D8B"]
+demo_report -> stdout [color = "#607D8B"]
+
+}
diff --git a/crates/geormerge-demo/docs/diagrams/workflow.svg b/crates/geormerge-demo/docs/diagrams/workflow.svg
new file mode 100644
index 0000000..3c497a4
--- /dev/null
+++ b/crates/geormerge-demo/docs/diagrams/workflow.svg
@@ -0,0 +1,247 @@
+
+
+
+
+