932d7a5f0e4b3b873bad2cbef7e6dc320f2140a3
All checks were successful
CI / test (push) Successful in 1m41s
- Add 22 unit tests covering feed parsing, thread rendering, facets, needsRefetch staleness windows, and handleConfigureAction - Add FreshRSS class stubs so tests run without a full FreshRSS install - Add RSS feed fixture (hockeyviz.com snapshot) and thread API fixture for post 3mhtk7awhrp26 (1 root + 2 replies) - Add Gitea Actions workflow (.gitea/workflows/ci.yml) running on PHP 8.2 - Fix POST_URL_PATTERN: using '#' as PCRE delimiter with '#' inside a character class caused PHP to close the pattern early, so no Bluesky URL ever matched; switch delimiter to '~' Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bluesky Threads — FreshRSS Extension
A FreshRSS extension that enriches Bluesky posts in your RSS feeds by fetching the full reply thread and embedded content via the Bluesky public API, collapsing everything into a single article.
Features
- Fetches full reply threads when a post is first saved, so API sync clients (Fever, GReader, etc.) receive enriched content immediately
- Automatically refreshes thread content as it ages, with progressively relaxed refresh intervals
- Renders rich text with working links, mentions, and hashtags
- Renders all embed types: images, external link cards, quoted posts, and videos
- No Bluesky account or API credentials required
Installation
- Download or clone this repository into FreshRSS's
extensions/directory. The folder must be namedxExtension-BlueskyThreads. - In FreshRSS, go to Extensions and enable Bluesky Threads.
Configuration
In the extension settings, you can set Thread depth (default: 10, max: 1000) — how many levels of replies to fetch per post.
How it works
Hooks
Two hooks work in tandem so both the web UI and API sync clients receive enriched content:
EntryBeforeInsert— fires once when a new entry is first saved. Fetches the thread immediately and stores the rendered HTML.EntryBeforeDisplay— fires on every web render. Checks if the cached thread is stale; if so, re-fetches and writes the updated HTML back to the database.
Cache & staleness
Thread HTML is cached as JSON files in DATA_PATH/BlueskyThreads/{md5(url)}.json. Staleness is determined by the post's age:
| Post age | Cache refresh interval |
|---|---|
| < 1 hour | Every 10 minutes |
| < 24 hours | Every 1 hour |
| < 7 days | Every 12 hours |
| 7+ days | Never (frozen) |
On API failure, the stale cache is served as a fallback.
API endpoints used
All requests go to public.api.bsky.app — no authentication required.
- Handle resolution:
com.atproto.identity.resolveHandle - Thread fetch:
app.bsky.feed.getPostThread
Description
A FreshRSS extension that enriches Bluesky posts in your RSS feeds by fetching the full reply thread and emb
edded content via the Bluesky public API, collapsing everything into a single article.
Languages
PHP
98.3%
HTML
1.7%