interactive intro to open social at-me.zzstoatzz.io

chore: remove outdated docs from Rust era

Project migrated to pure JS/Vite in 6a5c766. These docs are no longer relevant.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

-277
-107
docs/_artifacts/COPY_IMPROVEMENTS.md
··· 1 - # copy improvements 2 - 3 - ## the problem 4 - 5 - the original copy throughout @me was too technical and jargon-heavy for people unfamiliar with atproto. terms like "silos," "atproto identity," "repository," and "Personal Data Server" appeared without context or explanation. this created barriers for the primary audience: regular social media users who might be curious about decentralized social but don't yet understand the tech. 6 - 7 - more importantly, the copy focused on **how the technology works** rather than **why it matters** to users. people don't care about protocols - they care about not losing their followers when platforms change. 8 - 9 - ## the philosophy 10 - 11 - drawing from [overreacted.io/open-social](https://overreacted.io/open-social/), we adopted these principles: 12 - 13 - 1. **lead with relatable problems** - "built 10k followers? if you leave, you lose them all" 14 - 2. **use familiar analogies** - "what if social media worked like email?" 15 - 3. **focus on benefits, not technology** - "switch apps anytime, take everything with you" 16 - 4. **provide breadcrumbs** - link every technical term to official docs so curious users can learn more 17 - 18 - the key insight: if you can't leave without losing something important, the platform has no incentive to respect you. that's the message that resonates with regular users, not "merkle search trees" or "decentralized identity." 19 - 20 - ## what we changed 21 - 22 - ### logged-out experience (login page "what is this?") 23 - 24 - **before:** 25 - - "visualize your atproto identity" 26 - - "the problem with silos" 27 - - "the atproto solution" 28 - - heavy use of jargon, abstract concepts 29 - 30 - **after:** 31 - - "your posts should be yours" - opens with the actual problem people face 32 - - "what if social media worked like email?" - uses an analogy everyone understands 33 - - "see it in action" - simple call to action 34 - - every technical term links to [atproto.com](https://atproto.com) documentation 35 - 36 - **why:** logged-out users know nothing about atproto. this is our chance to make them care before introducing any technical concepts. 37 - 38 - ### logged-in experience (? button modal) 39 - 40 - **before:** 41 - - "@me - your repository" 42 - - focused on platform switching 43 - - generic language about ownership 44 - 45 - **after:** 46 - - "this is your data" - personal and direct 47 - - explains what they're looking at: "you're looking at your Personal Data Server - where your social data actually lives" 48 - - concrete examples: "bluesky for microblogging. whitewind for long-form posts" 49 - - defines "open social" in plain terms: "if you don't like an app, switch" 50 - - ends with clear instructions on how to use the tool 51 - 52 - **why:** once someone is logged in, they're ready for slightly deeper concepts. but we still prioritize clarity over accuracy, using the visualization to teach what a PDS does. 53 - 54 - ### identity/PDS panel (clicking @ in center) 55 - 56 - **before:** 57 - - title: "your repository" 58 - - subtitle: "what you've built" 59 - - comparison boxes about traditional vs atproto platforms 60 - - technical details at bottom 61 - 62 - **after:** 63 - - title: "your personal data server" 64 - - subtitle: "where your social data lives" 65 - - **"your pds location"** box - explicitly states where the PDS is hosted and what's stored there 66 - - **"explore your data"** box - links to `pdsls.dev/{pds-domain}` as a next step 67 - - removed redundant platform comparison (already covered in modals) 68 - - kept technical details (DID, handle) at bottom 69 - 70 - **why:** this panel should immediately answer "what is this thing in the center?" and "where is my data actually stored?" the pdsls.dev link gives power users an immediate action item. 71 - 72 - ## the pattern 73 - 74 - every piece of copy now follows this structure: 75 - 76 - 1. **hook** - relatable problem or question 77 - 2. **explain** - use familiar analogies 78 - 3. **breadcrumb** - link technical terms to docs 79 - 4. **action** - give them something to do or explore 80 - 81 - examples: 82 - - login page: problem → email analogy → linked "Personal Data Server" → "explore demo" 83 - - info modal: "this is your data" → concrete examples → linked "open social" → "how to explore" 84 - - pds panel: "where your social data lives" → linked PDS location → pdsls.dev tool → technical details 85 - 86 - ## success metrics 87 - 88 - we'll know this worked if: 89 - 90 - 1. **bounce rate decreases** on login page 91 - 2. **demo mode usage increases** (people want to see it work) 92 - 3. **pdsls.dev referrals** show users are exploring further 93 - 4. **fewer confused questions** from new users 94 - 95 - more importantly: can you explain this to your non-technical friend and have them understand why they should care? that's the test. 96 - 97 - ## files modified 98 - 99 - - `src/templates.rs` - login page info section, logged-in info modal 100 - - `static/app.js` - identity/PDS panel on @ click 101 - 102 - ## resources 103 - 104 - - [overreacted.io/open-social](https://overreacted.io/open-social/) - the philosophical foundation 105 - - [atproto.com/guides/data-repos](https://atproto.com/guides/data-repos) - what is a PDS 106 - - [atproto.com](https://atproto.com) - protocol overview 107 - - [pdsls.dev](https://pdsls.dev) - tool for exploring PDS contents
-92
docs/firehose.md
··· 1 - # real-time updates via firehose 2 - 3 - at-me visualizes your atproto activity in real-time using the jetstream firehose. 4 - 5 - ## what is the firehose? 6 - 7 - the [atproto firehose](https://docs.bsky.app/docs/advanced-guides/firehose) is a WebSocket stream of all repository events across the network. when you create, update, or delete records in your PDS, these events flow through the firehose. 8 - 9 - we use [jetstream](https://github.com/ericvolp12/jetstream), a more efficient firehose consumer that filters and transforms events. 10 - 11 - ## architecture 12 - 13 - ### backend: rust + server-sent events 14 - 15 - **firehose manager** (`src/firehose.rs`) 16 - - maintains WebSocket connections to jetstream 17 - - one broadcaster per DID being watched 18 - - smart reconnection with exponential backoff 19 - - thread-safe using `tokio` and `Arc<Mutex>` 20 - 21 - **dynamic collection registration** 22 - - when you click "watch live", we fetch your repo's collections via `com.atproto.repo.describeRepo` 23 - - registers event ingesters for ALL collections (not just bluesky) 24 - - this means whitewind, tangled, guestbook, and any future app automatically work 25 - 26 - **event broadcasting** (`src/routes.rs:firehose_watch`) 27 - - server-sent events (SSE) endpoint at `/api/firehose/watch?did=<your-did>` 28 - - filters jetstream events to only those matching your DID and collections 29 - - broadcasts as JSON: `{action, collection, namespace, did, rkey}` 30 - 31 - ### frontend: particles + circles 32 - 33 - **WebSocket to SSE bridge** (`static/app.js`) 34 - - `EventSource` connects to SSE endpoint 35 - - parses incoming events 36 - - creates particle animations 37 - - shows toast notifications 38 - 39 - **particle system** 40 - - creates colored particles (green=create, blue=update, red=delete) 41 - - animates from app circle → identity (your PDS) 42 - - uses `requestAnimationFrame` for smooth 60fps 43 - - easing with cubic bezier for natural motion 44 - 45 - **dynamic circle management** 46 - - new app? → `addAppCircle()` creates it on the fly 47 - - delete event? → `removeAppCircle()` cleans up when particle completes 48 - - circles automatically reposition to maintain even spacing 49 - 50 - ## event flow 51 - 52 - ``` 53 - 1. you create a post in bluesky 54 - 2. bluesky writes to your PDS 55 - 3. your PDS emits event to firehose 56 - 4. jetstream filters and forwards to our backend 57 - 5. backend matches your DID + collection 58 - 6. SSE pushes event to your browser 59 - 7. particle animates from bluesky circle to center 60 - 8. identity pulses when particle arrives 61 - 9. toast shows "created post: hello world..." 62 - ``` 63 - 64 - ## why it works for any app 65 - 66 - traditional approaches hardcode collections like `app.bsky.feed.post`. we don't. 67 - 68 - instead, we: 69 - 1. call `describeRepo` to get YOUR actual collections 70 - 2. register ingesters for everything you have 71 - 3. dynamically create/remove app circles as events flow 72 - 73 - this means if you use: 74 - - whitewind → see blog posts flow in 75 - - tangled → see commits flow in 76 - - at-me guestbook → see signatures flow in 77 - - future apps → automatically supported 78 - 79 - ## performance notes 80 - 81 - - **caching**: DID resolution cached for 1 hour (`constants::CACHE_TTL`) 82 - - **buffer**: broadcast channel with 100-event buffer 83 - - **reconnection**: 5-second delay between retries 84 - - **cleanup**: connections close when SSE client disconnects 85 - 86 - ## code references 87 - 88 - - firehose manager: `src/firehose.rs` 89 - - SSE endpoint: `src/routes.rs:951` (`firehose_watch`) 90 - - dynamic registration: `src/routes.rs:985` (fetch collections via `describeRepo`) 91 - - particle animation: `static/app.js:1037` (`animateFirehoseParticles`) 92 - - circle lifecycle: `static/app.js:1419` (`addAppCircle`), `static/app.js:1646` (`removeAppCircle`)
-51
docs/lexicon.md
··· 1 - # lexicon 2 - 3 - ## `app.at-me.visit` 4 - 5 - **status**: unofficial, experimental 6 - 7 - this is the record type created when users opt-in to "sign the guestbook" on at-me. 8 - 9 - ### namespace rationale 10 - 11 - we use `app.at-me.visit` rather than a domain-based namespace (like `io.zzstoatzz.*`) because: 12 - 13 - 1. the app is hosted at `at-me.fly.dev`, not under a domain we control 14 - 2. using a personal domain namespace would incorrectly suggest this is an official/owned lexicon 15 - 3. `app.at-me.*` clearly associates records with this specific application 16 - 17 - this is an **unofficial lexicon** - there is no formal schema definition served at a URL. it's a simple, unvalidated record type for analytics/engagement tracking. 18 - 19 - ### record structure 20 - 21 - ```json 22 - { 23 - "$type": "app.at-me.visit", 24 - "timestamp": "2025-10-25T22:30:00Z", 25 - "createdAt": "2025-10-25T22:30:00Z", 26 - "text": "optional message from the visitor" 27 - } 28 - ``` 29 - 30 - **fields:** 31 - - `timestamp` (required): ISO 8601 timestamp of when the signature was created 32 - - `createdAt` (required): ISO 8601 timestamp of when the record was created (typically same as timestamp) 33 - - `text` (optional): a message left by the visitor, max 280 characters 34 - 35 - ### privacy 36 - 37 - - users must explicitly authenticate and click "sign guestbook" to create these records 38 - - records are written to the user's own PDS, which they control 39 - - the app does not store or aggregate this data 40 - - users can delete these records at any time through their PDS 41 - 42 - ### philosophy 43 - 44 - this approach aligns with atproto's principles: 45 - - user data sovereignty (records live in user's PDS) 46 - - transparency (users see exactly what's being written) 47 - - opt-in participation (no tracking without explicit consent) 48 - 49 - ### acknowledgments 50 - 51 - thanks to [@thisismissem.social](https://bsky.app/profile/thisismissem.social) for putting [lexicon-guestbook](https://github.com/FujoWebDev/lexicon-guestbook) on our radar! [@essentialrandom.bsky.social](https://bsky.app/profile/essentialrandom.bsky.social)'s work on that project - a more fully-featured implementation with per-user guestbooks, moderation, and an appview - helped inform the addition of optional text messages to our simpler global guestbook.
-27
docs/oauth.md
··· 1 - # oauth 2 - 3 - at-me uses atproto oauth for authentication. 4 - 5 - ## flow 6 - 7 - 1. user enters handle on landing page 8 - 2. app resolves handle → DID → authorization server via did document 9 - 3. authorization server redirects to user's pds for consent 10 - 4. user approves, receives redirect back with auth code 11 - 5. app exchanges code for access token 12 - 6. token stored in session, used for authenticated api calls 13 - 14 - ## scopes 15 - 16 - ```rust 17 - Scope::Known(KnownScope::Atproto), 18 - Scope::Unknown("repo:app.at-me.visit".to_string()), 19 - ``` 20 - 21 - the granular scope `repo:app.at-me.visit` limits write access to only guestbook records. 22 - 23 - ## session management 24 - 25 - sessions use actix-web's cookie-based session middleware. authenticated agents cached in-memory by DID for performance (`AGENT_CACHE`). 26 - 27 - see `src/oauth.rs` for implementation.