@scribe-atp/core
Functions
Section titled “Functions”fetchSite
Section titled “fetchSite”function fetchSite( author: string, siteSlug: string, signal?: AbortSignal): Promise<Site>Fetches a site record from the author’s PDS. Resolves the author handle to a DID, discovers the PDS, and returns the full Site with embedded group and article metadata.
| Parameter | Type | Description |
|---|---|---|
author | string | Author handle (alice.bsky.social) or DID (did:plc:…) |
siteSlug | string | The site’s rkey — derive with toSlug(domain) |
signal | AbortSignal | Optional. Cancel the request when the signal fires |
fetchArticle
Section titled “fetchArticle”function fetchArticle( author: string, articleSlug: string, signal?: AbortSignal): Promise<Article>Fetches a single article record (including full HTML content) from the author’s PDS.
| Parameter | Type | Description |
|---|---|---|
author | string | Author handle or DID |
articleSlug | string | The article’s rkey / slug |
signal | AbortSignal | Optional. Cancel the request when the signal fires |
listSites
Section titled “listSites”function listSites( author: string, signal?: AbortSignal): Promise<SiteRecord[]>Returns all site records for the given author. Calls com.atproto.repo.listRecords for the app.scribe.site collection and follows cursor pagination automatically.
| Parameter | Type | Description |
|---|---|---|
author | string | Author handle (alice.bsky.social) or DID (did:plc:…) |
signal | AbortSignal | Optional. Cancel the request when the signal fires |
Each SiteRecord is a Site with an additional uri field (the full AT URI of the record). Use slugFromUri(record.uri) to extract the rkey when you need to construct URLs.
listArticles
Section titled “listArticles”function listArticles( author: string, signal?: AbortSignal): Promise<ArticleRef[]>Returns all article records for the given author as lightweight ArticleRef objects (no content field). Calls com.atproto.repo.listRecords for the app.scribe.article collection and follows cursor pagination automatically.
| Parameter | Type | Description |
|---|---|---|
author | string | Author handle or DID |
signal | AbortSignal | Optional. Cancel the request when the signal fires |
To determine the publication state of each article, cross-reference with listSites:
const [sites, articles] = await Promise.all([ listSites(author), listArticles(author),]);
const referencedUris = new Set( sites.flatMap((s) => [ ...s.groups.flatMap((g) => g.articles), ...s.ungroupedArticles, ]).map((a) => a.uri));
const drafts = articles.filter((a) => !referencedUris.has(a.uri));Call fetchArticle to retrieve the full content for any article.
toSlug
Section titled “toSlug”function toSlug(domain: string): stringDerives a site slug from a domain name by replacing . with - and removing non-alphanumeric characters.
toSlug('norobots.blog') // → "norobots-blog"toSlug('anthonycregan.co.uk') // → "anthonycregan-co-uk"slugFromUri
Section titled “slugFromUri”function slugFromUri(uri: string): stringExtracts the rkey (slug) from an AT URI.
slugFromUri('at://did:plc:abc/app.scribe.article/my-post') // → "my-post"flattenArticles
Section titled “flattenArticles”function flattenArticles( groups: Array<{ articles: ArticleRef[] }>): ArticleRef[]Flattens all ArticleRef objects from all groups into a single ordered array.
const allArticles = flattenArticles(site.groups);generateFeed
Section titled “generateFeed”function generateFeed(site: Site, options: FeedOptions): stringReturns a complete RSS 2.0 XML string for all published articles in the site.
FeedOptions
| Property | Type | Required | Description |
|---|---|---|---|
baseUrl | string | Yes | Your site’s origin, e.g. "https://alice.example.com" |
feedUrl | string | No | Canonical URL of the feed — used for the <atom:link> self-reference |
language | string | No | RSS <language> tag. Default: "en" |
limit | number | No | Maximum number of items to include |
See the RSS feeds guide for usage examples.
getSitemapEntries
Section titled “getSitemapEntries”function getSitemapEntries( site: Site, options: GetSitemapEntriesOptions): SitemapEntry[]Returns an array of sitemap entries for all published articles (plus the site root and group index pages).
GetSitemapEntriesOptions
| Property | Type | Required | Description |
|---|---|---|---|
baseUrl | string | Yes | Your site’s origin, e.g. "https://alice.example.com" |
SitemapEntry
interface SitemapEntry { url: string; lastmod?: string; // ISO 8601 date, e.g. "2024-03-15"}See the Sitemaps guide for usage examples.
interface Site { title: string; url: string; // Domain without protocol, e.g. "alice.bsky.social" urlPrefix: string; // Path prefix, e.g. "blog" — empty string if content is at root description?: string; splashImageUrl?: string; logoImageUrl?: string; groups: SiteGroup[]; ungroupedArticles: ArticleRef[];}SiteGroup
Section titled “SiteGroup”interface SiteGroup { slug: string; title: string; articles: ArticleRef[];}ArticleRef
Section titled “ArticleRef”A lightweight snapshot of article metadata, embedded in the site record to avoid N+1 fetch patterns. Does not include content.
interface ArticleRef { uri: string; // AT URI, e.g. "at://did:plc:…/app.scribe.article/my-post" title: string; url?: string; // Article slug / rkey splashImageUrl: string | null; synopsis?: string | null; createdAt: string; // ISO 8601 updatedAt?: string; // ISO 8601}Article
Section titled “Article”The full article record, including HTML content. Returned by fetchArticle.
interface Article { title: string; content: string; // Sanitised HTML — safe to render directly url: string; // Article slug / rkey splashImageUrl?: string; synopsis?: string; createdAt: string; // ISO 8601 updatedAt: string; // ISO 8601}SiteRecord
Section titled “SiteRecord”A Site with the AT URI of its underlying record included. Returned by listSites.
interface SiteRecord extends Site { uri: string; // AT URI, e.g. "at://did:plc:…/app.scribe.site/norobots-blog"}Use slugFromUri(record.uri) to extract the rkey when constructing URLs.