Skip to content

Cross-posted articles

When an author publishes an article from the Scribe CMS to Bluesky, the Article object returned by @scribe-atp/core includes a bskyPostRef field. You can use this field to render a link to the Bluesky post — letting readers continue the conversation there.

interface Article {
// ...other fields
bskyPostRef?: {
uri: string; // AT URI of the Bluesky post — e.g. at://did:plc:.../app.bsky.feed.post/3mp...
cid: string; // Content identifier of the post record
};
}

bskyPostRef is only present on articles that the author has explicitly cross-posted to Bluesky from the CMS. Always check for its presence before using it.

Bluesky post URLs follow a predictable pattern derived from the AT URI. An AT URI has the form:

at://{did}/{collection}/{rkey}

The web URL for the same post is:

https://bsky.app/profile/{did}/post/{rkey}
function bskyPostUrl(atUri: string): string {
const parts = atUri.split('/');
const did = parts[2];
const rkey = parts[4];
return `https://bsky.app/profile/${did}/post/${rkey}`;
}

Check for bskyPostRef before rendering. If the field is absent, the article was not cross-posted and there is no Bluesky post to link to.

function bskyPostUrl(atUri: string): string {
const parts = atUri.split('/');
const did = parts[2];
const rkey = parts[4];
return `https://bsky.app/profile/${did}/post/${rkey}`;
}
// In your article component:
{article.bskyPostRef && (
<a href={bskyPostUrl(article.bskyPostRef.uri)} target="_blank" rel="noopener noreferrer">
View discussion on Bluesky
</a>
)}

Everything above covers reading an existing bskyPostRef — the common case for a site that just displays Scribe content. If you’re building your own publishing tool against the SDK (rather than using Scribe CMS’s own “Share to Bluesky” action), @scribe-atp/core exports crossPostToBluesky for creating the post in the first place.

This needs an authenticated AT Protocol agent for the author’s own account — it’s the one write operation in an otherwise read-only SDK.

import { crossPostToBluesky, buildCanonicalUrl } from '@scribe-atp/core';
const ref = await crossPostToBluesky(agent, {
did: authorDid,
documentUri: article.uri,
documentCid: article.cid,
publicationUri: site.uri,
publicationCid: site.cid,
canonicalUrl: buildCanonicalUrl(article, site),
title: article.title,
text: `New post: ${article.title}`,
description: article.description,
});
// ref → { uri: "at://did:plc:.../app.bsky.feed.post/3mp...", cid: "..." }
// Write ref to the article's bskyPostRef field yourself if your tool
// should be able to render the "View discussion" link afterward.

See the API reference for the full CrossPostParams shape.