Skip to content

Commit feb8d4b

Browse files
ascorbicclaude
andauthored
feat(bluesky): add live bluesky loader for real-time content collections (#91)
- Add liveBlueskyLoader for Astro's experimental Live Content Collections - Support real-time data fetching using AT Protocol's getPosts method - Flexible configuration with identifier in options or collection filter - Comprehensive filtering: limit, date ranges, post types, identifier override - Robust error handling with specific error codes and helpful messages - Full TypeScript support with exported interfaces - Configurable service URLs for custom Bluesky instances - Complete demo site integration with live collection and individual post pages - Comprehensive test suite with 67 tests covering all functionality - Clean code organization with barrel exports separating build-time and live loaders 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude <noreply@anthropic.com>
1 parent 37b1162 commit feb8d4b

11 files changed

Lines changed: 2034 additions & 99 deletions

File tree

.changeset/live-bluesky-loader.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
---
2+
"@ascorbic/bluesky-loader": minor
3+
---
4+
5+
# Add live Bluesky loader
6+
7+
Adds `liveBlueskyLoader` for Astro's experimental Live Content Collections feature. This loader fetches Bluesky posts in real-time, complementing the existing build-time `authorFeedLoader`.
8+
9+
The key difference is that while `authorFeedLoader` fetches data at build time for static generation, `liveBlueskyLoader` retrieves fresh content on-demand during server-side rendering or client-side navigation.
10+
11+
## Getting Started
12+
13+
### Prerequisites
14+
15+
- Astro 5.10.0+ with experimental Live Content Collections enabled
16+
- `@ascorbic/bluesky-loader` package installed
17+
18+
### Basic Usage
19+
20+
Create a live collection in your `live.config.ts`:
21+
22+
```typescript
23+
import { defineLiveCollection } from "astro:content";
24+
import { liveBlueskyLoader } from "@ascorbic/bluesky-loader";
25+
26+
const liveBluesky = defineLiveCollection({
27+
type: "live",
28+
loader: liveBlueskyLoader({
29+
identifier: "your-handle.bsky.social", // Optional: can also be set in filters
30+
service: "https://public.api.bsky.app", // Optional: defaults to public API
31+
}),
32+
});
33+
34+
export const collections = { liveBluesky };
35+
```
36+
37+
### Using in Pages
38+
39+
Fetch posts in your Astro pages:
40+
41+
```astro
42+
---
43+
import { getLiveCollection, getLiveEntry } from 'astro:content';
44+
45+
// Get filtered posts
46+
const posts = await getLiveCollection('liveBluesky', (post) =>
47+
post.data.record.text.includes('astro')
48+
);
49+
50+
// Get a specific post by AT URI
51+
const post = await getLiveEntry('liveBluesky', 'at://did:plc:user/app.bsky.feed.post/id');
52+
---
53+
```
54+
55+
## Features
56+
57+
- Real-time data fetching using AT Protocol's `getPosts` method
58+
- Flexible configuration - set identifier globally or per-request
59+
- Filtering options: limit, date ranges, post types, and more
60+
- Error handling with specific error codes and helpful messages
61+
- Full TypeScript support with exported interfaces
62+
- Configurable service URLs for custom Bluesky instances
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ const spacecraft = defineCollection({
7070
const bluesky = defineCollection({
7171
loader: authorFeedLoader({
7272
identifier: "mk.gg",
73+
limit: 100,
7374
}),
7475
});
7576

demos/loaders/src/live.config.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
1-
import { defineLiveCollection } from 'astro:content';
2-
import { liveFeedLoader } from '@ascorbic/feed-loader';
1+
import { defineLiveCollection } from "astro:content";
2+
import { liveFeedLoader } from "@ascorbic/feed-loader";
3+
import { liveBlueskyLoader } from "@ascorbic/bluesky-loader";
34

45
const news = defineLiveCollection({
5-
type: 'live',
6+
type: "live",
67
loader: liveFeedLoader({
7-
url: 'https://feeds.bbci.co.uk/news/science_and_environment/rss.xml',
8+
url: "https://feeds.bbci.co.uk/news/science_and_environment/rss.xml",
89
}),
910
});
1011

11-
export const collections = { news };
12+
const liveBluesky = defineLiveCollection({
13+
type: "live",
14+
loader: liveBlueskyLoader({
15+
identifier: "mk.gg",
16+
service: "https://public.api.bsky.app",
17+
}),
18+
});
19+
20+
export const collections = { news, liveBluesky };

demos/loaders/src/pages/index.astro

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,16 @@ const formatter = new Intl.DateTimeFormat("en-CA", {
1616
---
1717

1818
<Layout title="Releases">
19-
<h2>Live News Feed</h2>
20-
<p><a href="/news">BBC Science & Environment News (Live Feed Demo)</a></p>
19+
<h2>Live Collections</h2>
20+
<ul>
21+
<li><a href="/news">BBC Science & Environment News (Live Feed Demo)</a></li>
22+
<li><a href="/live-bluesky">Live Bluesky Posts (Real-time)</a></li>
23+
</ul>
24+
25+
<h2>Build-time Collections</h2>
26+
<ul>
27+
<li><a href="/bluesky">Bluesky Posts (Build-time)</a></li>
28+
</ul>
2129

2230
<h2>Spacecraft</h2>
2331
{

0 commit comments

Comments
 (0)