- Examples
Sidecar records
Create two records with different collection NSIDs but the same rkey, linking them together by key.
Trigger: xrpc.procedure:<nsid>. Needs: happyview-record.
local time = require("internal.time")local tids = require("internal.tids")local record = require("happyview.record")
function handle(input, ctx) local rkey = tids.create() local ts = time.to_iso8601(time.now())
local post = record.create("xyz.statusphere.post", { text = input.text, createdAt = ts, }, { rkey = rkey })
local metadata = record.create("xyz.statusphere.postMetadata", { lang = input.lang or "en", source = input.source or "web", createdAt = ts, }, { rkey = rkey })
return { post = post, metadata = metadata }endimport time from "internal.time";import tids from "internal.tids";import record from "happyview.record";
export default async function handle(input, ctx) { const rkey = tids.create(); const ts = time.to_iso8601(time.now());
const post = await record.create("xyz.statusphere.post", { text: input.text, createdAt: ts, }, { rkey });
const metadata = await record.create("xyz.statusphere.postMetadata", { lang: input.lang ?? "en", source: input.source ?? "web", createdAt: ts, }, { rkey });
return { post, metadata };}import time from "internal.time";import tids from "internal.tids";import record from "happyview.record";
interface Input { text: string; lang?: string; source?: string;}
export default async function handle(input: Input) { const rkey = tids.create(); const ts = time.to_iso8601(time.now());
const post = await record.create("xyz.statusphere.post", { text: input.text, createdAt: ts, }, { rkey });
const metadata = await record.create("xyz.statusphere.postMetadata", { lang: input.lang ?? "en", source: input.source ?? "web", createdAt: ts, }, { rkey });
return { post, metadata };}How it works
Section titled “How it works”- Mint a single TID with
tids.create()to use as the rkey for both records. - Create a record in each collection with
record.create, passing the shared rkey inopts. - Return both
{ uri, cid }results so the app knows the identity of each record.
The DPoP proof is signed per request; an app built on the HappyView SDK gets this from its session.
const response = await fetch("http://127.0.0.1:3000/xrpc/xyz.statusphere.createPost", { method: "POST", headers: { "X-Client-Key": CLIENT_KEY, Authorization: `DPoP ${ACCESS_TOKEN}`, DPoP: DPOP_PROOF, "Content-Type": "application/json", }, body: JSON.stringify({ text: "Hello world", lang: "en", source: "web", }),});const data = await response.json();const response = await fetch("http://127.0.0.1:3000/xrpc/xyz.statusphere.createPost", { method: "POST", headers: { "X-Client-Key": CLIENT_KEY, Authorization: `DPoP ${ACCESS_TOKEN}`, DPoP: DPOP_PROOF, "Content-Type": "application/json", }, body: JSON.stringify({ text: "Hello world", lang: "en", source: "web", }),});const data = await response.json();let response = client .post("http://127.0.0.1:3000/xrpc/xyz.statusphere.createPost") .header("X-Client-Key", client_key) .header("Authorization", format!("DPoP {access_token}")) .header("DPoP", dpop_proof) .json(&serde_json::json!({ "text": "Hello world", "lang": "en", "source": "web" })) .send() .await?;clientKey := "hvc_..." // your API client keyaccessToken := "..." // DPoP access tokendpopProof := "..." // DPoP proof JWT
body := `{ "text": "Hello world", "lang": "en", "source": "web" }`req, err := http.NewRequest("POST", "http://127.0.0.1:3000/xrpc/xyz.statusphere.createPost", bytes.NewBufferString(body))if err != nil { log.Fatal(err)}req.Header.Set("X-Client-Key", clientKey)req.Header.Set("Authorization", "DPoP "+accessToken)req.Header.Set("DPoP", dpopProof)req.Header.Set("Content-Type", "application/json")resp, err := http.DefaultClient.Do(req)if err != nil { log.Fatal(err)}defer resp.Body.Close()curl -X POST http://127.0.0.1:3000/xrpc/xyz.statusphere.createPost \ -H "X-Client-Key: $CLIENT_KEY" \ -H "Authorization: DPoP $ACCESS_TOKEN" \ -H "DPoP: $DPOP_PROOF" \ -H "Content-Type: application/json" \ -d '{ "text": "Hello world", "lang": "en", "source": "web" }'
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
Section titled “Use case”Use sidecar records to keep a primary record small and store related data, such as metadata, reactions or settings, in another collection under the same rkey. Because they share an rkey, you can derive one URI from the other:
at:// did:plc:abc /xyz.statusphere.post /3abc123at:// did:plc:abc /xyz.statusphere.postMetadata /3abc123 ^^^^^^^ same rkey© HappyProto

