A component library for rendering common AT Protocol records for applications such as Bluesky and Tangled.
Enter a handle to fetch your profile, latest Bluesky post, a Tangled string, and a Leaflet document.
Wrap your app with the provider once and drop the ready-made components wherever you need them.
import { AtProtoProvider, BlueskyPost } from 'atproto-ui';
export function App() {
return (
<AtProtoProvider>
<BlueskyPost did="did:plc:example" rkey="3k2aexample" />
</AtProtoProvider>
);
}Pass prefetched data to components to skip API calls—perfect for SSR or caching.
import { BlueskyPost, useLatestRecord } from 'atproto-ui';
import type { FeedPostRecord } from 'atproto-ui';
const LatestPostWithPrefetch: React.FC<{ did: string }> = ({ did }) => {
// Fetch once with the hook
const { record, rkey, loading } = useLatestRecord<FeedPostRecord>(
did,
'app.bsky.feed.post'
);
if (loading) return <span>Loading…</span>;
if (!record || !rkey) return <span>No posts yet.</span>;
// Pass prefetched record—BlueskyPost won't re-fetch it
return <BlueskyPost did={did} rkey={rkey} record={record} />;
};Use atcute directly to construct records and pass them to components—fully compatible!
import { Client, simpleFetchHandler, ok } from '@atcute/client';
import type { AppBskyFeedPost } from '@atcute/bluesky';
import { BlueskyPost } from 'atproto-ui';
// Create atcute client
const client = new Client({
handler: simpleFetchHandler({ service: 'https://public.api.bsky.app' })
});
// Fetch a record
const data = await ok(
client.get('com.atproto.repo.getRecord', {
params: {
repo: 'did:plc:ttdrpj45ibqunmfhdsb4zdwq',
collection: 'app.bsky.feed.post',
rkey: '3m45rq4sjes2h'
}
})
);
const record = data.value as AppBskyFeedPost.Main;
// Pass atcute record directly to component!
<BlueskyPost
did="did:plc:ttdrpj45ibqunmfhdsb4zdwq"
rkey="3m45rq4sjes2h"
record={record}
/>