# 015 — EPUB bookmarks and notes (physical-book UX) **Status:** Implemented **Created:** 2026-06-04 ## Objective Let users select passage text while reading an EPUB, save a bookmark (with optional thought), list markers in chapter order, and jump back to the exact location. Global view groups markers by book in a Reddit-style thread layout. ## Fix: AnnotationsProvider `AnnotationsProvider` wraps all routes in [`App.tsx`](frontend/src/App.tsx) so `/bookmarks-notes` and the reader can use `useAnnotations()`. ## Data model `Bookmark` (annotations app) references **`books.EBook`**, not catalog `Book`: | Field | Purpose | |-------|---------| | `ebook` | FK to uploaded ebook | | `epub_cfi` | EPUB CFI anchor | | `chapter_index` | Spine index for sort order | | `chapter_title` | Display label | | `location_text` | Selected passage quote | | `content` | Optional user thought (empty = bookmark only) | | `page` | Legacy display field (`chapter_index + 1`) | Unique: `(user, ebook, epub_cfi)`. Default API ordering: `chapter_index`, `epub_cfi`. Legacy `Note` model remains for old API; new UX uses `Bookmark.content` only. ## Reader flow ```mermaid sequenceDiagram participant User participant EpubView participant Popover participant API User->>EpubView: Select text EpubView->>Popover: Show near selection User->>Popover: Save optional thought Popover->>API: POST /annotations/bookmarks/ ``` 1. Text selection via epub.js `selected` event and content `mouseup` hook. 2. [`SelectionPopover`](frontend/src/components/reader/SelectionPopover.tsx) — floating UI, optional textarea. 3. Toolbar bookmark icon opens [`BookMarkersPanel`](frontend/src/components/reader/BookMarkersPanel.tsx) (current ebook only). 4. “Go to passage” sets reader `location` to stored CFI (`/read/:id` with router state). ## Global page (`/bookmarks-notes`) [`MarkerThreadsView`](frontend/src/components/annotations/MarkerThreadsView.tsx): - Groups markers by ebook (collapsible book rows). - Within each book: chapter order, passage as blockquote, thought indented below (Reddit-style). - Optional filter: `/bookmarks-notes/:ebookId`. ## API - `GET /api/annotations/bookmarks/?ebook={id}` - `POST /api/annotations/bookmarks/` — body: `ebook`, `epub_cfi`, `chapter_index`, `chapter_title`, `location_text`, `content` ## i18n New keys under `annotations.*` (EN/ES): `saveMarker`, `thoughtPlaceholder`, `bookmarkOnly`, `selectTextHint`, `goToPassage`, `inBookPanel`, `markerCount`, etc. ## Verification 1. `/bookmarks-notes` loads without provider error. 2. Select text in reader → popover → save with/without thought. 3. Markers appear in reader panel and global page under correct book, in chapter order. 4. “Go to passage” opens the correct location. See also [016 — Bookmark reading anchor](016-bookmark-reading-anchor.md) for preserving reading position while peeking at bookmarks. ## Out of scope - PDF selection - Multiple replies per passage - Migrating legacy `Note` rows into `Bookmark`