diff --git a/docs/pages/protocol/cursors.mdx b/docs/pages/protocol/cursors.mdx
index af6884e7..bee4208b 100644
--- a/docs/pages/protocol/cursors.mdx
+++ b/docs/pages/protocol/cursors.mdx
@@ -1,3 +1,5 @@
+import Mermaid from '../../components/Mermaid';
+
# Cursors with XMTP
This document explains the concept of **cursors** as they relate to message synchronization on the XMTP network. Cursors are a fundamental part of how XMTP clients efficiently fetch new messages and maintain state, particularly with the `sync()` family of functions.
@@ -43,6 +45,28 @@ Each `sync()` function corresponds to a different type of cursor:
For example, here is a sequence diagram illustrating how cursors operate with `conversation.sync()`:
-
+
+ (Stores cursor)
+ participant Network as Network
(Stores group topic)
+
+ Note over Client: No cursor for topic yet
+ Client ->> Network: Initial conversation.sync()
+ Network ->> Client: Returns all messages from topic
(Msg1, Msg2, Msg3)
+ Note over Client: Stores new cursor for topic
+ Client ->> Client: Cursor points after Msg3
+ Note over Network: New messages arrive on group topic
+ Network ->> Client: streamAllMessages()
(Msg4, Msg5, Msg6)
+ Note over Client: Cursor unaffected by stream
+ Client ->> Network: Subsequent conversation.sync()
(Sends stored cursor from after Msg3)
+ Network ->> Client: Returns messages that occurred after cursor
(Msg4, Msg5, Msg6)
+ Note over Client: Advances cursor for topic
+ Client ->> Client: Cursor points after Msg6
+ `}
+ />
+
By understanding cursors, you can better reason about the behavior of your app's synchronization logic and the data being transferred from the XMTP network.
diff --git a/docs/styles.css b/docs/styles.css
index e9c122aa..bb701f69 100644
--- a/docs/styles.css
+++ b/docs/styles.css
@@ -603,6 +603,30 @@ li ol ~ p {
text-align: center;
}
+/* Responsive iframe container */
+.responsive-iframe-container {
+ position: relative;
+ padding-bottom: 56.25%; /* 16:9 aspect ratio */
+ height: 0;
+ overflow: hidden;
+}
+
+.responsive-iframe-container iframe {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ border: 0;
+}
+
+/* White background container for diagrams */
+.diagram-white-bg {
+ background-color: #ffffff;
+ padding: 20px;
+ border-radius: 8px;
+}
+
/* styles/global.css or wherever you include global styles */
.mermaid {
max-width: 100%;
diff --git a/package-lock.json b/package-lock.json
index 617ea748..3bd32772 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,7 +14,7 @@
"react-dom": "^19.0.0",
"react-medium-image-zoom": "^5.2.14",
"react-router": "^7.8.2",
- "vocs": "^1.0.13"
+ "vocs": "https://github.com/sashaaldrick/vocs/releases/download/v1.0.13-search-fix-release/vocs-1.0.13-search-fix.tgz"
},
"devDependencies": {
"@types/react": "^19.0.0",
@@ -11253,8 +11253,8 @@
},
"node_modules/vocs": {
"version": "1.0.13",
- "resolved": "https://registry.npmjs.org/vocs/-/vocs-1.0.13.tgz",
- "integrity": "sha512-V/ogXG5xw7jMFXI2Wv0d0ZdCeeT5jzaX0PKdRKcqhnd21UtLZrqa5pKZkStNIZyVpvfsLW0WB7wjB4iBOpueiw==",
+ "resolved": "https://github.com/sashaaldrick/vocs/releases/download/v1.0.13-search-fix-release/vocs-1.0.13-search-fix.tgz",
+ "integrity": "sha512-4t2PawAKR66uH/Ra6sbxbFYb7GOjMKGtqRr1gxfIDJQoywIhuhhLeiwVTFvwZPGIv1tS6Fvi5JLZpTQ74JzY1Q==",
"funding": [
{
"type": "github",
diff --git a/package.json b/package.json
index 01fdfd80..a27a446a 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,7 @@
"react-dom": "^19.0.0",
"react-medium-image-zoom": "^5.2.14",
"react-router": "^7.8.2",
- "vocs": "^1.0.13"
+ "vocs": "https://github.com/sashaaldrick/vocs/releases/download/v1.0.13-search-fix-release/vocs-1.0.13-search-fix.tgz"
},
"devDependencies": {
"@types/react": "^19.0.0",