Script Examples
Sidecar Records
Create two records with different collection NSIDs but the same rkey, linking them together by key.
Lexicon type: procedure
function handle()
local rkey = TID()
local post = Record("xyz.statusphere.post", {
text = input.text,
createdAt = now(),
})
post:set_rkey(rkey)
local metadata = Record("xyz.statusphere.postMetadata", {
lang = input.lang or "en",
source = input.source or "web",
createdAt = now(),
})
metadata:set_rkey(rkey)
Record.save_all({ post, metadata })
return {
post = { uri = post._uri, cid = post._cid },
metadata = { uri = metadata._uri, cid = metadata._cid },
}
endHow it works
- Generate a single
TID()to use as the rkey for both records. - Create a
Recordfor each collection and callr:set_rkey()with the shared rkey. - Save both records in parallel with
Record.save_all(). - Return both URIs so the client knows the identity of each record.
Usage
const response = await fetch("http://127.0.0.1:3000/xrpc/xyz.statusphere.createPost", {
method: "POST",
headers: {
"X-Client-Key": CLIENT_KEY,
Authorization: `Bearer ${TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
text: "Hello world",
lang: "en",
source: "web",
}),
});
const data = await response.json();The response includes URIs for both the post and its metadata:
{
"post": {
"uri": "at://did:plc:abc/xyz.statusphere.post/3abc123",
"cid": "bafyrei..."
},
"metadata": {
"uri": "at://did:plc:abc/xyz.statusphere.postMetadata/3abc123",
"cid": "bafyrei..."
}
}Use case
Sidecar records are useful when you want to associate related data across collections without embedding everything in a single record. Because they share an rkey, you can derive one URI from the other:
at:// did:plc:abc /xyz.statusphere.post /3abc123
at:// did:plc:abc /xyz.statusphere.postMetadata /3abc123
^^^^^^^ same rkeyThis is a common atproto pattern for keeping a primary record lean while storing auxiliary data (metadata, reactions, settings) in a companion collection.