This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

Go 97.7%
Nix 2.3%
7 1 0

Clone this repository

https://tangled.org/karitham.dev/skeets-that-you-misunderstood https://tangled.org/did:plc:5wmoyu6szqufeyelajg5xcgb
git@tangled.org:karitham.dev/skeets-that-you-misunderstood git@tangled.org:did:plc:5wmoyu6szqufeyelajg5xcgb

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



README.md

Skeets That You Misunderstood#

AT Protocol feed generator ranking posts by controversy using Wilson score intervals.

This is an experiment and not made to be used for real. It's only posts that make you go huh.

I can tell it works because it's all posts from The Onion, about US politics and gay p*rn.

What It Does#

Subscribes to the Bluesky firehose, tracks likes/unlikes, and serves ranked feeds via AT Protocol.

Feeds:

  • controversial — Daily controversy rankings
  • controversial-weekly — Weekly controversy rankings

Quickstart#

1. Prerequisites#

  • Bluesky account
  • Go 1.26+
  • Domain you control (for DID) (for dev, https://srv.us suffices)

2. Create Feed Records#

Create records in your Bluesky repo:

# Publish feeds (requires BSKY_HANDLE and BSKY_PASSWORD)
BSKY_HANDLE=your.handle BSKY_PASSWORD=your-pass go run ./cmd/tools/publish

This creates app.bsky.feed.generator/controversial and controversial-weekly records.

3. Configure#

cp .env.example .env
# Edit .env with:
# FEEDGEN_HOSTNAME=feeds.yourdomain.com
# FEEDGEN_SERVICE_DID=did:web:feeds.yourdomain.com
# FEEDGEN_PUBLISHER_DID=your-did

4. Run#

go run ./cmd/feed

5. Test#

# Get feed
curl "http://localhost:3000/xrpc/app.bsky.feed.getFeedSkeleton?feed=at://did:plc:you/app.bsky.feed.generator/controversial&limit=10" | jq .

# Health check
curl http://localhost:3000/xrpc/_health

# Metrics
curl http://localhost:3000/debug/metrics | jq .

Architecture#

All state is held in memory. A periodic checkpoint (every 10s, plus on shutdown) atomically persists to disk for crash recovery.

graph LR
    B[Bluesky Firehose] -->|events| S[Subscriber]
    S -->|inc| L[In-Memory Counters]
    S -->|update scores| SC[ScoreStore]
    L -->|checkpoint| CK[checkpoint.gob]
    D[Deleted Set] -->|checkpoint| CK
    P[Post Index] -->|checkpoint| CK
    SC -->|rank| F[Feed Handler]
    F -->|serve| B2[Bluesky PDS]
    CK -.->|restart: load| L
    CK -.->|restart: load| SC

Data Flow#

sequenceDiagram
    participant B as Bluesky Firehose
    participant S as Subscriber
    participant L as Memory Counters
    participant SC as ScoreStore
    participant CK as Checkpoint (every 10s)
    participant FH as Feed Handler
    participant PDS as Bluesky PDS

    B->>S: Like/Unlike/Post events
    S->>L: IncLikes(uri) — atomic map increment
    S->>SC: UpdateScoreWithCounts(uri, likes, unlikes)
    L-->>CK: Snapshot maps → persist.go
    CK->>CK: tempfile + rename (atomic commit)
    PDS->>FH: GET /xrpc/app.bsky.feed.getFeedSkeleton
    FH->>SC: Top(limit, window)
    SC-->>FH: []ScoredPost sorted
    FH-->>PDS: Feed skeleton (URIs only)
    PDS-->>User: Hydrated feed

Configuration#

Variable Description Default
FEEDGEN_PORT HTTP port 3000
FEEDGEN_HOSTNAME Public hostname example.com
FEEDGEN_SERVICE_DID Service DID did:web:$HOSTNAME
FEEDGEN_PUBLISHER_DID Your Bluesky DID did:example:alice
FEEDGEN_DATA_DIR Checkpoint storage dir ./data
FEEDGEN_SUBSCRIPTION_ENDPOINT Firehose URL wss://relay1...
FEEDGEN_LOGGER_LEVEL Log level (0=INFO) 0

Project Structure#

cmd/
  feed/          # Main feed generator
  tools/
    publish/     # Publish feed records
    unpublish/   # Unpublish feed records
cursorstore/     # Firehose cursor tracking (in-memory)
likesstore/      # Like/unlike counters (in-memory)
deletestore/     # Deleted post tracking (in-memory)
scorestore/      # Wilson score + in-memory sorted indexes
persist/         # Atomic checkpoint save/load
subscriber/      # Firehose consumer
xrpc/            # AT Protocol XRPC handlers

Commands#

# Run feed generator
go run ./cmd/feed

# Publish feeds to Bluesky
BSKY_HANDLE=your.handle BSKY_PASSWORD=pass go run ./cmd/tools/publish

# Unpublish feeds
BSKY_HANDLE=your.handle BSKY_PASSWORD=pass go run ./cmd/tools/unpublish

# Run tests
go test ./...

# Build binary
go build -o feedgen ./cmd/feed