(did, 'app.bsky.feed.post');
if (loading) return Fetching latest post…
;
if (error) return Could not load: {error.message}
;
if (empty || !rkey) return No posts yet.
;
return (
);
};
```
The same pattern works for other components: swap the collection NSID and the component you render once you have an `rkey`.
```tsx
const LatestLeafletDocument: React.FC<{ did: string }> = ({ did }) => {
const { rkey } = useLatestRecord(did, 'pub.leaflet.document');
return rkey ? : null;
};
```
## Compose your own component
The helpers let you stitch together custom experiences without reimplementing protocol plumbing. The example below pulls a creator’s latest post and renders a minimal summary:
```tsx
import { useLatestRecord, useColorScheme, AtProtoRecord } from 'atproto-ui';
import type { FeedPostRecord } from 'atproto-ui';
const LatestPostSummary: React.FC<{ did: string }> = ({ did }) => {
const scheme = useColorScheme('system');
const { rkey, loading, error } = useLatestRecord(did, 'app.bsky.feed.post');
if (loading) return Loading…;
if (error || !rkey) return No post yet.;
return (
did={did}
collection="app.bsky.feed.post"
rkey={rkey}
renderer={({ record }) => (
{record?.text ?? 'Empty post'}
)}
/>
);
};
```
There is a [demo](https://wisp.place/s/ana.pds.nkp.pet/ATComponents) where you can see the components in live action.
## Running the demo locally
```bash
npm install
npm run dev
```
Then open the printed Vite URL and try entering a Bluesky handle to see the components in action.
## Next steps
- Expand renderer coverage (e.g., Grain.social photos).
- Expand documentation with TypeScript API references and theming guidelines.
Contributions and ideas are welcome—feel free to open an issue or PR!