Bluesky avatar proxy thing
Go 92.1%
Makefile 4.5%
Dockerfile 3.4%
14 1 3

Clone this repository

https://tangled.org/angrydutchman.peedee.es/blavatar
git@tangled.org:angrydutchman.peedee.es/blavatar

For self-hosted knots, clone URLs may differ based on your setup.

README.md

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/jpeg
  • Cache-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 format
  • 500 Internal Server Error - Fetch or processing failure

How It Works#

  1. Request: Client requests an avatar via /{identifier}.jpg
  2. Resolution: Handle is resolved to DID if needed
  3. Cache Check: Local file cache is checked
  4. Fetch: On cache miss, avatar is fetched from the user's PDS
  5. Processing: Image is scaled to 128x128 and encoded as JPEG
  6. Caching: Result is stored in the file cache
  7. Invalidation: Jetstream consumer listens for profile updates and removes stale cache entries

License#

See LICENSE file for details.