This repository has no description
README.md

aim #

An AIM-style buddy list for Bluesky. Type your handle and see which of your mutuals are online right now — in real time, with the door chime when someone signs on.

🔗 Live: aim.cee.wtf

No login, no password, no backend. It reads your public follows and followers, then watches the Bluesky firehose for what they do. Pure static HTML + ES modules — open it on any web server and it runs.

What it does #

  • Presence, the honest way. One filtered Jetstream firehose socket streams only your mutuals' events. Presence is behavioral:
    • 🟢 online — posted, replied or reposted within the window
    • 🟡 idle — only liked or followed (lurking)
    • ⚪ offline — quiet A door chime plays when a buddy flips to online.
  • IM windows = your conversation. Click a buddy to open an AIM-style chat log scoped to the two of you — their replies/likes/reposts/quotes/mentions of your stuff, and yours of theirs. Not their global feed; just the relationship.
  • Deep history. That window also pulls both full repos (com.atproto.sync.getRepo) in the background and decodes them, surfacing interactions going back years — including likes, which no public API otherwise exposes (and your own likes, normally auth-gated).
  • "Last seen 3d ago" for dormant buddies, derived from each repo's latest-commit rev (a TID that timestamps their last write of any kind).
  • Door chimes are synthesized in WebAudio — original sounds, not AIM's copyrighted samples.

Run it #

ES modules must be served over HTTP (not file://). Any static server works:

python3 -m http.server 8137
# then open http://localhost:8137

No build step, no dependencies, no API keys.

How it works (atproto notes) #

Everything hits public, CORS-enabled, unauthenticated endpoints:

What Endpoint
Handle → DID, profiles, follows/followers, post text public.api.bsky.app (AppView XRPC)
Live presence + activity jetstream*.bsky.network (firehose websocket)
Full-history interactions incl. likes com.atproto.sync.getRepo (PDS, CARv1 + DAG-CBOR)
"Last seen" for dormant accounts com.atproto.sync.getLatestCommit rev (relay)
DID → PDS resolution plc.directory

Two details worth stealing:

  • wantedDids goes in a hello message, not the URL. Hundreds of DIDs as query params blow past the WebSocket handshake URL-length limit and the server refuses the connection. Connect with ?requireHello=true and send {type:'options_update', payload:{wantedDids:[...]}} on open. See jetstream.js.
  • Likes live only in the repo. They're absent from feeds and getActorLikes is auth-gated, so the only way to see who-liked-what across history is to decode the CAR. See atproto/ + deep-history.js.

Layout #

index.html        markup + Win98/AIM chrome
main.js           orchestrator: state map, firehose connection, DOM wiring
jetstream.js      filtered firehose client (hello-message wantedDids, cursor replay)
status.js         presence taxonomy (online/idle/offline)
buddy-list.js     incremental list rendering (reused rows — no avatar flicker)
chat.js           IM window lifecycle (fast pass + deep pass + live updates)
chat-actions.js   raw event/record -> normalized entry (with interaction targets)
chat-render.js    entry -> IM line HTML
deep-history.js   full-repo download + decode -> interaction entries
last-seen.js      "last seen" backfill via repo rev (TID decode)
sound.js          WebAudio door open/close chimes
about.js          the (?) window
drag.js           draggable windows
util.js           esc / relTime / postUrl / TID helpers
api.js            thin atproto AppView client
typeahead.js      handle autocomplete
atproto/          CARv1 + DAG-CBOR + MST decoder (repo parsing)
style.css         the teal desktop

License #

MIT — see LICENSE.


a cee.wtf thing