blavatar#
A caching proxy for Bluesky avatars with real-time cache invalidation.
Overview#
blavatar is an HTTP service that fetches, caches, and serves user avatars from the Bluesky social network. It maintains cache freshness by subscribing to Bluesky's Jetstream for profile update events, automatically invalidating cached avatars when users change their profiles. Currently it observes only the Bluesky profile since there is no single profile lexicon (yet). This may change in the future.
Features#
- File-based avatar caching with automatic invalidation
- Real-time updates via Bluesky Jetstream subscription
- Supports both DIDs and handles as identifiers
- Generates default placeholder avatars for users without avatars
- Scales all avatars to 128x128 JPEG format
- Graceful shutdown handling
Building#
make build # Compile binary
make install # Build and install
make clean # Remove build artifacts
For Docker:
make release-dev # Build and push dev image
make release # Build and push release image
Configuration#
Configuration is done via CLI flags or environment variables:
| Flag | Environment Variable | Default | Description |
|---|---|---|---|
--jetstream-url |
BLAVATAR_JETSTREAM_URL |
wss://jetstream2.us-west.bsky.network/subscribe |
Jetstream WebSocket URL |
--store-path |
BLAVATAR_STORE_PATH |
./avatars |
Directory for cached avatars |
--listen |
BLAVATAR_LISTEN |
:8080 |
HTTP server listen address |
Usage#
Start the server:
blavatar
Or with custom configuration:
blavatar --store-path /var/cache/avatars --listen :3000
Using environment variables:
export BLAVATAR_STORE_PATH=/var/cache/avatars
export BLAVATAR_LISTEN=:3000
blavatar
API#
GET /{identifier}.jpg#
Retrieve an avatar by DID or handle.
Examples:
# By handle
curl http://localhost:8080/alice.bsky.social.jpg -o avatar.jpg
# By DID
curl http://localhost:8080/did:plc:abcdef123456.jpg -o avatar.jpg
Response Headers:
Content-Type: image/jpegCache-Control: public, max-age=7200(for real avatars)Cache-Control: no-cache(for default placeholder avatars)
Response Codes:
200 OK- Avatar returned (real or default)400 Bad Request- Invalid identifier format500 Internal Server Error- Fetch or processing failure
How It Works#
- Request: Client requests an avatar via
/{identifier}.jpg - Resolution: Handle is resolved to DID if needed
- Cache Check: Local file cache is checked
- Fetch: On cache miss, avatar is fetched from the user's PDS
- Processing: Image is scaled to 128x128 and encoded as JPEG
- Caching: Result is stored in the file cache
- Invalidation: Jetstream consumer listens for profile updates and removes stale cache entries
License#
See LICENSE file for details.