learn and share notes on atproto (wip) 🦉 malfestio.stormlightlabs.org/
readability solid axum atproto srs

docs: establish initial project roadmap, define core architecture, and document public vs private data rules

+508
+36
README.md
··· 4 4 5 5 Social layer: publish/share/remix learning artifacts; follow curators; discuss. 6 6 7 + ## Personas 8 + 9 + - **Learner**: studies daily; imports content; wants fast "review queue". 10 + - **Creator**: makes decks/notes; publishes updates; wants feedback + forks. 11 + - **Curator/Teacher**: bundles content into learning paths; annotates lectures/articles. 12 + - **Moderator/Community admin**: handles reports, takedowns, spam. 13 + 7 14 ## Principles 8 15 9 16 - Local-first study experience; offline study must not feel "second-class". ··· 20 27 - Article: URL + extracted text (readability style heuristics) + highlights + 21 28 linked notes/cards. 22 29 - Collection/Path: curated bundle of decks + notes + sources. 30 + 31 + ## System Architecture 32 + 33 + ### Frontend (SolidJS) 34 + 35 + - App shell + router-driven workspaces (Library / Study / Create / Social). 36 + - Signals as primary state primitive; keep study session state in signals/store. 37 + 38 + ### Backend (Rust) 39 + 40 + - Axum API gateway: REST/XRPC-ish endpoints, tower middleware, typed extractors. 41 + - Services (logical, not necessarily microservices): 42 + - Identity/Auth service (local + optional ATProto OAuth integration) 43 + - Content service (notes/cards/decks/sources) 44 + - Study service (queue generation + grading + scheduling) 45 + - Social service (follows, feeds, comments, notifications) 46 + - Search service (indexing + query) 47 + - Moderation service (reports, takedowns, rules) 48 + 49 + ### Storage 50 + 51 + - Postgres: canonical app DB (users, private study state, cache of published records). 52 + - Object storage: images/audio, extracted article snapshots (if you store them). 53 + - Search index: separate system (Meilisearch/Typesense/ZincSearch-pick one later). 54 + 55 + ### Eventing 56 + 57 + - Internal outbox pattern (DB table) for: 58 + - reindex jobs, notification fanout, federation publish steps
+71
docs/core-user-journeys.md
··· 1 + # Core User Journeys 2 + 3 + This document outlines the five core user journeys for the initial product version. 4 + 5 + ## 1. Import Source & Publish Deck 6 + 7 + **Goal**: A creator builds a study deck from an external resource and shares it. 8 + 9 + 1. **Import**: User inputs a URL (Article) or pastes text. 10 + 2. **Generate**: System extracts metadata (and optionally snapshots content). 11 + 3. **Authoring**: 12 + * User highlights key sections in the source. 13 + * User creates **Notes** linked to highlights. 14 + * User generates **Cards** (Flashcards) from Notes or directly from source. 15 + 4. **Assembly**: User organizes Cards into a **Deck**. 16 + 5. **Publish**: User sets visibility (e.g., Public) and publishes the Deck. 17 + 6. **Result**: The Deck is now a shareable Artifact (ATProto record). 18 + 19 + ## 2. Daily Study Loop 20 + 21 + **Goal**: A learner maintains their knowledge using Spaced Repetition (SRS). 22 + 23 + 1. **Session Start**: User opens the app/daily study mode. 24 + 2. **Review Queue**: System presents cards due for review based on SRS algorithm (e.g., SM-2). 25 + 3. **Interaction**: 26 + * User sees **Front** of card. 27 + * User attempts recall. 28 + * User reveals **Back**. 29 + 4. **Grading**: User self-grades (e.g., 0-5). 30 + 5. **Update**: System schedules next review interval. 31 + 6. **Progress**: User sees feedback (cards done, streak incremented). 32 + * *Note: All grading/progress data is strictly private.* 33 + 34 + ## 3. Social Collaboration (Follow/Fork) 35 + 36 + **Goal**: A learner discovers content and improves it. 37 + 38 + 1. **Discovery**: 39 + * User follows a Curator. 40 + * User sees a new Deck in their "New from Follows" feed. 41 + 2. **Acquisition**: User saves/pins the Deck to their library. 42 + 3. **Contribution (Forking)**: 43 + * User identifies a gap or error in the Deck. 44 + * User **Forks** the Deck. 45 + * User edits cards or adds new ones. 46 + * User republishes the modified Deck (referencing the original). 47 + 4. **Loop**: Original author (or others) can see the fork and potentially merge changes (future scope) or users can switch to the better fork. 48 + 49 + ## 4. Discussion & Moderation 50 + 51 + **Goal**: Community interaction while maintaining safety. 52 + 53 + 1. **Context**: A User is viewing a public Card or Deck. 54 + 2. **Discuss**: User adds a **Comment** (threaded) asking for clarification. 55 + 3. **Report** (Unhappy Path): 56 + * User encounters abusive content/spam. 57 + * User triggers **Report** flow. 58 + * Moderation system receives report. 59 + * Content may be hidden/labeled based on moderation actions. 60 + 61 + ## 5. Lecture Study Workflow 62 + 63 + **Goal**: Deep study of long-form audio/video content. 64 + 65 + 1. **Import**: User provides a Lecture URL (e.g., YouTube/Video). 66 + 2. **Structure**: 67 + * User creates an **Outline** of the lecture. 68 + * User adds **Timestamps** to segment the content. 69 + 3. **Link**: 70 + * User creates Cards specific to timestamped segments. 71 + * Clicking context on a Card jumps video to the specific timestamp.
+65
docs/information-architecture.md
··· 1 + # Information Architecture 2 + 3 + This document defines the application structure, navigation, and data model mapping for Milestone A. 4 + 5 + ## Site Map (Navigation) 6 + 7 + ### Global Navigation 8 + 9 + - **Home/Feed**: Discover content (Following, Trending). 10 + - **Library**: User's saved Decks, curated Collections, and private progress. 11 + - **Create**: Entry point for Authoring tools. 12 + - **Search**: Global search for Decks, Curators, and Tags. 13 + - **Profile**: User identity and settings. 14 + 15 + ### Logical View Hierarchy 16 + 17 + - **/** (Home) 18 + - Feed of followed curators 19 + - **/library** 20 + - Study Queue (What to review today) 21 + - My Decks (Created & Forked) 22 + - Saved Collections 23 + - **/deck/:did/:slug** (Deck View) 24 + - Overview (Description, Stats) 25 + - Browser/Cards List 26 + - Study Mode (Launch Session) 27 + - **/note/:rkey** (Note View) 28 + - Note Content (Markdown) 29 + - Backlinks / Linked Cards 30 + - **/source/:rkey** (Article/Lecture View) 31 + - Source Metadata (Title, URL) 32 + - Snapshot/Content View (if saved) 33 + - Highlights List 34 + - **/study/:session_id** (Study Session) 35 + - Active Recall Interface (Front/Back) 36 + - **/editor** 37 + - New Deck / Edit Deck 38 + - Import Source (URL/Text) 39 + - **/profile/:handle** 40 + - Public Decks 41 + - Followers/Following 42 + 43 + ## Data Model Mapping 44 + 45 + Mapping screens to underlying data entities (Lexicon Records + Private State). 46 + 47 + | Screen / Component | Primary Data Entity | Secondary Entities | Private/Public | 48 + | :----------------- | :----------------------------- | :---------------------------------------- | :---------------------------- | 49 + | **Deck Overview** | `app.malfestio.deck` | `app.malfestio.card` (refs), User Profile | **Public** | 50 + | **Study Session** | N/A (Ephemeral) | `app.malfestio.card`, Private Review Log | **Private** | 51 + | **Card View** | `app.malfestio.card` | `app.malfestio.note`, Media Blobs | **Public** | 52 + | **Editor** | Draft State (Local) | Source (`article`), `note` | **Private (Draft) -> Public** | 53 + | **Source View** | `app.malfestio.source.article` | `app.malfestio.note` (linked) | **Public** | 54 + | **Note View** | `app.malfestio.note` | Backlinks (`card`/`deck`) | **Public** | 55 + | **Library** | `app.malfestio.collection` | Bookmarks, User Prefs | **Mixed** | 56 + | **Comments** | `app.malfestio.thread.comment` | User Profile | **Public** | 57 + 58 + ## URL Structure 59 + 60 + - `https://app.example.com/` - Home 61 + - `https://app.example.com/profile/<handle>` - User Profile 62 + - `https://app.example.com/profile/<handle>/deck/<slug>` - Deck Permalink 63 + - `https://app.example.com/profile/<handle>/deck/<slug>/card/<rkey>` - Card Permalink 64 + - `https://app.example.com/profile/<handle>/note/<rkey>` - Note Permalink 65 + - `https://app.example.com/profile/<handle>/source/<rkey>` - Source Permalink
+49
docs/share-vs-private-rules.md
··· 1 + # Share vs Private Rules 2 + 3 + This document defines the strict separation between public "Artifacts" and private "Learning State". 4 + This distinction is critical for the application's architecture and user privacy. 5 + 6 + ## The Separation Principle 7 + 8 + - **Public Layer ("Artifacts")**: Content that is created to be shared. 9 + These are immutable (or append-only) records published to the AT Protocol. 10 + - **Private Layer ("Learning State")**: Personal study data. 11 + This includes grades, schedules, and progress. 12 + This data **NEVER** leaks into the public record automatically. 13 + 14 + ## Public Record Types (The Lexicon) 15 + 16 + These entities are visible to anyone with access to the PDS (essentially public). 17 + 18 + - Deck (`app.malfestio.deck`): The collection of cards/notes. 19 + - Card (`app.malfestio.card`): The flashcard content (Front/Back). 20 + - Note (`app.malfestio.note`): The source knowledge note. 21 + - Article (`app.malfestio.source.article`): Metadata/snapshot of an external article. 22 + - Lecture (`app.malfestio.source.lecture`): Metadata/outline of an external video/audio. 23 + - Collection (`app.malfestio.collection`): Curated lists of decks. 24 + - Comment (`app.malfestio.thread.comment`): Public discussion. 25 + 26 + > **Rule**: If a user puts sensitive information in a Card, they must be warned that 27 + > publishing the Deck makes it public. 28 + 29 + ## Private Data Types (Local/Private Sync) 30 + 31 + These entities are stored in the user's private database (Local -> Private User Sync). 32 + 33 + - **Scheduling Data**: 34 + - Next due date 35 + - Ease Factor (EF) 36 + - Interval history 37 + - Retrievability estimates 38 + - **Performance Metrics**: 39 + - Grades (Forget, Hard, Good, Easy) 40 + - Session duration 41 + - Response times 42 + - **Drafts**: 43 + - Decks/Cards currently being written but not yet published. 44 + 45 + ## Interaction Rules 46 + 47 + 1. **Forking**: When a user forks a public deck, they create a *new* public record (referencing the original). Their *private* study data for the original deck does NOT transfer to the new fork (or is reset). 48 + 2. **Study Session**: A study session is a purely private event. It reads Public Artifacts but writes only to the Private Layer. 49 + 3. **Sync**: Public records sync via ATProto (Relay/PDS). Private data syncs via a separate, private channel (e.g., encrypted backup or private PDS blob).
+287
docs/todo.md
··· 1 + # Product + Technical Roadmap 2 + 3 + ## Protocol + Lexicon Strategy 4 + 5 + - "Artifacts" are publishable records (ATProto Lexicon). 6 + - "Learning state" is private (local DB + your backend sync; not public records). 7 + - Records are distributed and hard to migrate globally; keep mutable/private state out. 8 + - Lexicon evolution rules strongly encourage forward-compatible extensibility. 9 + 10 + ### Namespace + NSID conventions 11 + 12 + - `app.malfestio.note` 13 + - `app.malfestio.card` 14 + - `app.malfestio.deck` 15 + - `app.malfestio.source.article` 16 + - `app.malfestio.source.lecture` 17 + - `app.malfestio.collection` 18 + - `app.malfestio.thread.comment` 19 + 20 + ### Lexicon basics 21 + 22 + - Lexicon defines record types + XRPC endpoints; JSON-schema-like constraints. 23 + - Use "optional fields" heavily; avoid enums that will calcify the product too early. 24 + - Versioning: add fields, don’t rename; never rely on being able to rewrite history. 25 + 26 + ### Schema boundaries (important) 27 + 28 + - **Public share layer**: 29 + - decks, cards, notes, collections, comments 30 + - **Private layer**: 31 + - review schedule, lapses, grades, per-card performance, streaks 32 + 33 + ### Auth direction 34 + 35 + - ATProto is moving toward OAuth for client↔PDS authorization. 36 + - Plan for OAuth support even if MVP starts centralized. 37 + 38 + ## Roadmap Milestones 39 + 40 + ### Milestone A - Product Spec + IA + UX Flows 41 + 42 + #### Deliverables 43 + 44 + - Core user journeys (5): 45 + - Import source -> generate notes/cards -> publish deck 46 + - Daily study -> review queue -> grade -> progress view 47 + - Follow curator -> discover deck -> fork -> contribute improvements 48 + - Discuss a card/deck -> moderation/report flow 49 + - Lecture workflow -> outline -> timestamps -> linked cards 50 + - Information architecture + navigation map 51 + - "Share vs private" rules doc (what becomes public records; what never does) 52 + 53 + #### Acceptance 54 + 55 + - Every screen maps to a backend capability + a data model entity. 56 + 57 + ### Milestone B - Lexicon Design Kit + Data Model Mapping 58 + 59 + #### Deliverables 60 + 61 + - Lexicon repo folder with: 62 + - record schemas for note/card/deck/article/lecture/collection/comment 63 + - schema evolution notes (what can change, what cannot) 64 + - Mapping doc: 65 + - Public record (lexicon) <-> internal DB row(s) 66 + - Minimal "publish pipeline" spec (draft->published->deprecated) 67 + 68 + #### Acceptance 69 + 70 + - You can create a deck and serialize it into a stable record shape. 71 + - Follow Lexicon rules; prefer additive evolution. 72 + - Review Bluesky "custom schemas" patterns for compatibility expectations. 73 + 74 + ### Milestone C - Foundations: Repo, CI, Axum API Skeleton, Solid Shell 75 + 76 + #### Deliverables 77 + 78 + - Monorepo layout (crates/server/, web/, lexicons/, crates/cli/, crates/core/) 79 + - core: domain logic, data models 80 + - server: axum, postgres, search, eventing, auth 81 + - cli: entry point for local dev, PDS sync 82 + - web: solidjs app 83 + - CI: format/lint/test + schema validation + typegen 84 + - Axum: 85 + - health, auth stub, error model, request IDs, structured logging 86 + - Solid: 87 + - tailwind, router shell, auth gate, initial pages + layout system 88 + 89 + #### Acceptance 90 + 91 + - End-to-end "hello world" for create/read deck locally. 92 + 93 + ### Milestone D - Identity + Permissions + Publishing Model 94 + 95 + #### Deliverables 96 + 97 + - Auth MVP: 98 + - BlueSky App Passwords 99 + - ATProto OAuth 100 + - Permission model: 101 + - private / unlisted / public / shared-with 102 + - Publishing: 103 + - draft editing, publish, update, deprecate, fork 104 + 105 + #### Acceptance 106 + 107 + - A user can publish a deck and another user can view it. 108 + 109 + ### Milestone E - Content Authoring (Notes + Cards + Deck Builder) 110 + 111 + #### Deliverables 112 + 113 + - Note editor (markdown + attachments + backlinks) 114 + - Card editor: 115 + - basic front/back + cloze v1 116 + - images/audio attachments (optional) 117 + - Deck builder: 118 + - tags, ordering, sections 119 + - Importers v1: 120 + - article URL -> extracted snapshot + highlights 121 + - lecture URL -> outline + timestamps (manual entry initially) 122 + 123 + #### Acceptance 124 + 125 + - A creator can build a deck from an article and publish it. 126 + 127 + ### Milestone F - Study Engine (SRS) + Daily Review UX 128 + 129 + #### Deliverables 130 + 131 + - SRS scheduler v1 (SM-2 baseline) 132 + - grade 0–5, EF, interval, repetition count 133 + - Review queue generation rules 134 + - Study session UI: 135 + - keyboard-first review loop 136 + - quick edit card during review 137 + - Progress views (private): 138 + - due count, retention proxy, streaks 139 + 140 + #### Acceptance 141 + 142 + - 30-day simulated study test produces stable, believable intervals. 143 + 144 + #### Notes 145 + 146 + - SM-2 reference behavior is well documented; start there and iterate. 147 + 148 + ### Milestone G - Social Layer v1 (Follow, Feed, Fork, Comments) 149 + 150 + #### Deliverables 151 + 152 + - Follow graph + notifications 153 + - Feeds: 154 + - "New decks from follows" 155 + - "Trending this week" (simple scoring) 156 + - Forking workflow: 157 + - fork deck -> edit -> republish 158 + - Threaded comments on decks/cards 159 + 160 + #### Acceptance 161 + 162 + - A user can follow a curator and see new published decks in a feed. 163 + 164 + ### Milestone H - Search + Discovery + Taxonomy 165 + 166 + #### Deliverables 167 + 168 + - Full-text search over: 169 + - deck title/description, card text, note text, source metadata 170 + - Tag taxonomy: 171 + - user tags + curator tags + system tags 172 + - Discovery pages: 173 + - top tags, featured paths, editor picks 174 + 175 + #### Acceptance 176 + 177 + - Search is fast (<200ms typical) and results feel relevant. 178 + 179 + ### Milestone I - Moderation + Abuse Resistance 180 + 181 + #### Deliverables 182 + 183 + - Reporting pipeline + review queue 184 + - Rate limits + spam heuristics 185 + - Takedown/visibility states (shadowed, removed, quarantined) 186 + - Audit logging for moderation actions 187 + 188 + #### Acceptance 189 + 190 + - You can safely operate an open publishing surface. 191 + 192 + ### Milestone J - Federation / ATProto Integration Pass 193 + 194 + #### Deliverables 195 + 196 + - Phase 1 (minimum): 197 + - export Lexicon records 198 + - ingest remote records into a read-only "federated library" 199 + - Phase 2: 200 + - OAuth login to PDS + publish records directly (client or server mediated) 201 + - reconcile local drafts with remote published state 202 + 203 + #### Acceptance 204 + 205 + - A published artifact is portable beyond your app. 206 + 207 + #### Notes 208 + 209 + - ATProto OAuth is the forward path; plan on it. 210 + - XRPC endpoint patterns and legacy session behavior exist, but treat them as transitional. 211 + 212 + ### Milestone K - Reliability, Observability, Launch 213 + 214 + #### Deliverables 215 + 216 + - Metrics + tracing + structured logs 217 + - Backups + restore drills 218 + - Load test targets (study session + feed + search) 219 + - Beta program + feedback loop + roadmap iteration 220 + 221 + #### Acceptance 222 + 223 + - You can run this as a real product with confidence. 224 + 225 + ## "First Cut" Lexicon Fields (Draft) 226 + 227 + ### Note (app.malfestio.note) 228 + 229 + - title: string 230 + - body: richtext/markdown string 231 + - tags: string[] 232 + - links: { uri, title?, type? }[] 233 + - createdAt, updatedAt 234 + - visibility: "private|unlisted|public" (consider leaving as string + documented values) 235 + 236 + ### Card (app.malfestio.card) 237 + 238 + - deckRef: at-uri / stable ref 239 + - front: string (markdown) 240 + - back: string (markdown) 241 + - cardType: "basic|cloze" (optional) 242 + - hints?: string[] 243 + - media?: { kind, uri, alt? }[] 244 + 245 + ### Deck (app.malfestio.deck) 246 + 247 + - title, description 248 + - tags 249 + - cardRefs: at-uri[] 250 + - sourceRefs: at-uri[] (articles/lectures) 251 + - license?: string (strongly recommended) 252 + 253 + ### Article (app.malfestio.source.article) 254 + 255 + - url 256 + - title 257 + - author? 258 + - publishedAt? 259 + - extractedTextRef? (only if you store it) 260 + - highlights?: { quote, start?, end? }[] 261 + 262 + ### Lecture (app.malfestio.source.lecture) 263 + 264 + - url 265 + - title 266 + - creator? 267 + - timestamps?: { t, label, noteRef? }[] 268 + 269 + ### Collection/Path (app.malfestio.collection) 270 + 271 + - title, description 272 + - items: { type, ref, note? }[] 273 + - tags 274 + 275 + ### Comment (app.malfestio.thread.comment) 276 + 277 + - subjectRef (deck/card/note ref) 278 + - body 279 + - replyTo? 280 + 281 + (Keep everything extensible; avoid hard commitments early.) 282 + 283 + ## Open Questions (Parked Decisions) 284 + 285 + - Local-first mechanics: full offline authoring + later publish, or online-only creation? 286 + - Federation depth: read-only ingest first, or publish-to-PDS in the first public beta? 287 + - Content extraction: store extracted article snapshots (legal/ops implications), or store only metadata + highlights?