Something went wrong. Try again.
React blog kit backed by AT Protocol. Provides filtering UI, pagination, Bluesky comments/embeds, subscribe widget, and markdown rendering.
Something went wrong. Try again.
4.9 kB · 147 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148import { createBlogConfig, createAtprotoFeed, consoleTelemetry, type BlogConfig, type Post, type Category, type Author, type AtprotoFeedAdapter,} from "@blog";import { withStandardSiteFix } from "./standard-site-fix";
interface PubSpec { slug: "scb" | "standard" | "stevedylan"; name: string; did: string; publicationRkey: string; canonicalUrl: string; defaultAuthor: Author; categories: Record<string, Category>; tagToCategoryMap: Record<string, string>; // Temporary flag — see standard-site-fix.ts fixPostUrls?: true;}
const SPECS: PubSpec[] = [ { slug: "scb", name: "Serious Computer Business", did: "did:plc:txurc6ueald5d7462bpvzdby", publicationRkey: "3mbnlfyowxg2v", canonicalUrl: "https://octet-stream.net/b/scb", defaultAuthor: { name: "Serious Computer Business", role: "Author", href: "https://bsky.app/profile/did:plc:txurc6ueald5d7462bpvzdby", did: "did:plc:txurc6ueald5d7462bpvzdby", }, categories: { ai: { title: "AI", href: "/?categories=ai" }, security: { title: "Security", href: "/?categories=security" }, }, tagToCategoryMap: { ai: "ai", security: "security" }, }, { slug: "standard", name: "Standard.site", did: "did:plc:re3ebnp5v7ffagz6rb6xfei4", publicationRkey: "3me5vykp6lf2y", canonicalUrl: "https://standard.site", defaultAuthor: { name: "Standard.site", role: "Author", href: "https://bsky.app/profile/did:plc:re3ebnp5v7ffagz6rb6xfei4", did: "did:plc:re3ebnp5v7ffagz6rb6xfei4", }, categories: {}, tagToCategoryMap: {}, fixPostUrls: true, }, { slug: "stevedylan", name: "Steve Simkins", did: "did:plc:ia2zdnhjaokf5lazhxrmj6eu", publicationRkey: "3mbykzswhqc2x", canonicalUrl: "https://stevedylan.dev", defaultAuthor: { name: "Steve Simkins", role: "Author", href: "https://bsky.app/profile/did:plc:ia2zdnhjaokf5lazhxrmj6eu", did: "did:plc:ia2zdnhjaokf5lazhxrmj6eu", }, categories: { "open-web": { title: "Open Web", href: "/?categories=open-web" }, personal: { title: "Personal", href: "/?categories=personal" }, rss: { title: "RSS", href: "/?categories=rss" }, blogging: { title: "Blogging", href: "/?categories=blogging" }, philosophy: { title: "Philosophy", href: "/?categories=philosophy" }, programming: { title: "Programming", href: "/?categories=programming" }, neovim: { title: "Neovim", href: "/?categories=neovim" }, "developer-tools": { title: "Developer Tools", href: "/?categories=developer-tools" }, ai: { title: "AI", href: "/?categories=ai" }, atproto: { title: "ATProto", href: "/?categories=atproto" }, "web-development": { title: "Web Development", href: "/?categories=web-development" }, blockchain: { title: "Blockchain", href: "/?categories=blockchain" }, developer: { title: "Developer", href: "/?categories=developer" }, }, tagToCategoryMap: { "open web": "open-web", personal: "personal", rss: "rss", blogging: "blogging", philosophy: "philosophy", programming: "programming", neovim: "neovim", "developer tools": "developer-tools", ai: "ai", atproto: "atproto", "web development": "web-development", blockchain: "blockchain", developer: "developer", }, },];
function withOutboundHref(feed: AtprotoFeedAdapter, canonicalUrl: string): AtprotoFeedAdapter { const rewrite = (p: Post): Post => ({ ...p, href: `${canonicalUrl}${p.href.startsWith("/") ? p.href : `/${p.href}`}`, }); return { tagsToCategories: feed.tagsToCategories.bind(feed), fetchAllDocuments: async () => (await feed.fetchAllDocuments()).map(rewrite), fetchDocument: async (slug: string) => { const doc = await feed.fetchDocument(slug); return doc ? rewrite(doc) : undefined; }, };}
export const publications: Record<string, BlogConfig> = Object.fromEntries( SPECS.map((spec) => { const rawFeed = createAtprotoFeed({ did: spec.did, basePath: "", defaultAuthor: spec.defaultAuthor, categories: spec.categories, tagToCategoryMap: spec.tagToCategoryMap, }); const outbound = withOutboundHref(rawFeed, spec.canonicalUrl); const config = createBlogConfig({ basePath: "", postsPerPage: 5, feed: spec.fixPostUrls ? withStandardSiteFix(outbound) : outbound, categories: spec.categories, defaultAuthor: spec.defaultAuthor, sequoia: { publicationUri: `at://${spec.did}/site.standard.publication/${spec.publicationRkey}`, }, telemetry: consoleTelemetry, }); return [spec.slug, config]; }),);
export const publicationOrder = SPECS.map((s) => ({ slug: s.slug, name: s.name }));export const defaultPublication = "scb";