A React component library for rendering common AT Protocol records for applications such as Bluesky and Leaflet.
at main 2.2 kB view raw
1import { useBlueskyAppview } from "./useBlueskyAppview"; 2import type { ProfileRecord } from "../types/bluesky"; 3import { extractCidFromBlob } from "../utils/blob"; 4 5/** 6 * Minimal profile fields returned by the Bluesky actor profile endpoint. 7 */ 8export interface BlueskyProfileData { 9 /** Actor DID. */ 10 did: string; 11 /** Actor handle. */ 12 handle: string; 13 /** Display name configured by the actor. */ 14 displayName?: string; 15 /** Profile description/bio. */ 16 description?: string; 17 /** Avatar blob (CID reference). */ 18 avatar?: string; 19 /** Banner image blob (CID reference). */ 20 banner?: string; 21 /** Creation timestamp for the profile. */ 22 createdAt?: string; 23} 24 25/** 26 * Fetches a Bluesky actor profile for a DID and exposes loading/error state. 27 * 28 * Uses a three-tier fallback strategy: 29 * 1. Try Bluesky appview API (app.bsky.actor.getProfile) - CIDs are extracted from CDN URLs 30 * 2. Fall back to Slingshot getRecord 31 * 3. Finally query the PDS directly 32 * 33 * When using the appview, avatar/banner CDN URLs (e.g., https://cdn.bsky.app/img/avatar/plain/did:plc:xxx/bafkreixxx@jpeg) 34 * are automatically parsed to extract CIDs and convert them to standard Blob format for compatibility. 35 * 36 * @param did - Actor DID whose profile should be retrieved. 37 * @returns {{ data: BlueskyProfileData | undefined; loading: boolean; error: Error | undefined }} Object exposing the profile payload, loading flag, and any error. 38 */ 39export function useBlueskyProfile(did: string | undefined) { 40 const { record, loading, error } = useBlueskyAppview<ProfileRecord>({ 41 did, 42 collection: "app.bsky.actor.profile", 43 rkey: "self", 44 }); 45 46 // Convert ProfileRecord to BlueskyProfileData 47 // Note: avatar and banner are Blob objects in the record (from all sources) 48 // The appview response is converted to ProfileRecord format by extracting CIDs from CDN URLs 49 const data: BlueskyProfileData | undefined = record 50 ? { 51 did: did || "", 52 handle: "", 53 displayName: record.displayName, 54 description: record.description, 55 avatar: extractCidFromBlob(record.avatar), 56 banner: extractCidFromBlob(record.banner), 57 createdAt: record.createdAt, 58 } 59 : undefined; 60 61 return { data, loading, error }; 62}