This repository has no description
Something went wrong. Try again.
JavaScript 80%
CSS 16%
HTML 4%
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:
wantedDidsgoes 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=trueand send{type:'options_update', payload:{wantedDids:[...]}}on open. Seejetstream.js.- Likes live only in the repo. They're absent from feeds and
getActorLikesis auth-gated, so the only way to see who-liked-what across history is to decode the CAR. Seeatproto/+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