SDK guides
Building URLs
A Site record carries two URL-related fields that together define the root of the site's content:
| Field | Example | Meaning |
|---|---|---|
site.url | "anthonycregan.co.uk" | The site's domain (no protocol) |
site.urlPrefix | "blog" | Path prefix for content — empty string if content is at the root |
An article's own slug lives in article.slug on an ArticleRef.
Article URL pattern
The canonical URL for a published article is:
https://{site.url}/{site.urlPrefix}/{group.slug}/{article.slug}
When urlPrefix is empty, the pattern is:
https://{site.url}/{group.slug}/{article.slug}
Helper function
Write a small utility function once and reuse it across your app:
import type { Site } from '@scribe-atp/core';
function articleUrl(site: Site, groupSlug: string, articleSlug: string): string {
const base = site.urlPrefix
? `https://${site.url}/${site.urlPrefix}`
: `https://${site.url}`;
return `${base}/${groupSlug}/${articleSlug}`;
}
Usage:
const url = articleUrl(site, group.slug, article.slug);
// e.g. "https://anthonycregan.co.uk/blog/2024/my-first-post"
// or "https://norobots.blog/2024/my-first-post"
Tip
When building internal links within your own site, use relative paths (/blog/2024/my-first-post) rather than absolute URLs. The absolute form is for canonical <link> tags, RSS items, and sitemap entries.
Looking up a site by URL
Pass the site's canonical HTTPS URL directly to fetchSite — no slug derivation needed:
import { fetchSite } from '@scribe-atp/core';
await fetchSite('alice.bsky.social', 'https://alice.bsky.social');
await fetchSite('anthonycregan.dev', 'https://anthonycregan.co.uk');
await fetchSite('anthonycregan.dev', 'https://norobots.blog');
The toSlug utility is still exported from @scribe-atp/core for other uses, but it is no longer needed for site lookups.
Article slugs
An article's human-readable slug is available directly on the ArticleRef object returned by fetchSite. Use article.slug — do not try to derive it from the AT URI.
const site = await fetchSite('alice.bsky.social', 'https://alice.bsky.social');
for (const group of site.groups) {
for (const article of group.articles) {
const url = articleUrl(site, group.slug, article.slug);
}
}
Article rkeys are opaque TIDs (e.g. 3mp47vvkh342n) assigned by the PDS. slugFromUri returns this TID, which is not the same as the human-readable slug. Prefer article.slug over slugFromUri when building URLs.