sports / bsfeeds
BS Feeds is a Bluesky feed generator providing curated sports feeds.
Available feeds:
Architecture
I wrote the server as a single Go binary that connects to the Bluesky firehose and a Postgres database.
It contains a few services:
- Web: HTTP handlers for Bluesky's feed generator protocol
- Stream: subscribes to the Bluesky firehose via WebSocket, receiving every public post in real-time
- Builder: matches incoming posts against feed definitions, writes matches to Postgres
- Maintenance: prunes feed items older than one week to keep the database small
It has no message queues or worker processes. Goroutines handle concurrency within the binary.
Feed definitions
Each feed is defined in Go code with:
- Text terms: team names, player names, playoff terms
- Account DIDs: official team accounts, beat reporters
- Game patterns: regex for matchups like "Bills vs Cowboys"
For example, the NFL feed includes all 32 team names,
hundreds of player names, and DIDs for accounts like
@detroitlions.bsky.social.
Terms are chosen carefully to avoid false positives. Ambiguous names are excluded. Substring conflicts are tested (e.g., "Josh Allen" shouldn't match posts about a different Josh Allen).
I use Warp to help me update content periodically as rosters change.
Matching
When a post arrives from the firehose, the matcher checks:
- Does the post contain any text term (case-insensitive)?
- Does it match a game pattern like "Cowboys-Bills"?
- Is the author a listed account DID?
Matches are written to Postgres with the feed ID and post URI. When Bluesky clients request a feed, the web handler queries recent matches and returns them in AT Protocol format.