SDK guides

Cross-posted articles

When an author publishes an article from the SkyScribe 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.

The bskyPostRef field

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.

Constructing the Bluesky post URL

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>
)}

Note

The cid field in bskyPostRef is the content identifier for the post record. You do not need it to build the URL — it is available if you want to verify post integrity via the AT Protocol.

Creating a cross-post yourself

Everything above covers reading an existing bskyPostRef — the common case for a site that just displays published content. If you're building your own publishing tool against the SDK (rather than using SkyScribe'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.

See also

Settings

Appearance