Add study templates, exports, breadcrumb, whole-Bible search, bookmarks UX, and share links

- Study templates: richer multi-line guiding questions in the OIA placeholders
- PDF/print export: reuses buildExportHtml in a new tab + window.print()
- Markdown export: new buildMarkdownExport() with matching tests
- Breadcrumb: current chunk's passage reference shown in the Study page header
- Reader bookmarks: SVG icons instead of ambiguous emoji, always visible
  (not hover-only, so it works on touch devices), plus a Bookmarks panel
  that lists all saved verses across every book and jumps + scrolls to them
- Whole-Bible search: no server-side search endpoint exists, so this fetches
  the full translation once (~7MB) and searches an in-memory flat verse
  index client-side, with results linking back into the reader
- Read-only share links: per-project share token, a public unauthenticated
  /api/share/:token endpoint, and a ?share=TOKEN view that bypasses the auth
  gate entirely and renders the export HTML in a script-sandboxed iframe

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
nmemmert
2026-07-06 10:12:00 -04:00
parent 2735ef216c
commit 37cfcd55a0
6 changed files with 632 additions and 36 deletions
+12 -22
View File
@@ -1,21 +1,17 @@
# Study App Improvement Suggestions
_Refreshed 2026-07-06 — the previous version of this file predated ~40 commits of feature work (OT support, tagging, DOCX import/export, split-view, commentary, cross-ref suggestions, and the full Bible Reader with audio/bookmarks/interlinear/search). Items already shipped have been removed; this reflects what's actually still open._
_Refreshed 2026-07-06 (multiple passes) — items already shipped have been removed; this reflects what's actually still open. Recent additions: multi-user auth with per-account data scoping, TOTP 2FA with backup codes, podcast terminology generalized to "Session" for study-only users (with a configurable podcast/show name), auto-restore on new devices, study templates (richer OIA guiding prompts), PDF/print export, Markdown export, a passage breadcrumb, whole-Bible search, better bookmark UX (always-visible SVG icons + a jump-to panel), and read-only share links._
## Features
### Study Tools
- **Bible comparison mode** — show two translations side-by-side. `availableTranslations` is already fetched and a translation is already selectable per project (`App.jsx:904`), but only one renders at a time — no split/parallel view
- **Bible comparison mode** — show two translations side-by-side. `availableTranslations` is already fetched and a translation is already selectable per project, but only one renders at a time — no split/parallel view
- **Verse-level notes** — annotations are still chunk-level only (OIA fields); no way to attach a note to a single verse within a chunk
- **Progress tracking** — no "in progress"/"complete" marker per chunk and no progress bar on the home project card
- **Study templates** — no guiding prompts pre-filled for new users starting their first OIA entry
- **Word/character count** on the OIA and Final Script textareas — encourages note depth, useful for episode-length planning
### Export / Sharing
- **PDF export** / print stylesheet — still no `window.print()` CSS or PDF button anywhere in the app
- **Share link** — no read-only shareable URL for a project (useful for co-teachers reviewing an episode)
- **Markdown export** — HTML/DOCX/Claude-prompt exports exist; no plain Markdown output for Obsidian-style tools
- **Episode length estimate** — Final Script field exists per chunk; a word-count-based "~X minutes read aloud" estimate would help podcast planning
- **Share link is single-use-case** — one share token per project, all-or-nothing (whole project, all chunks). A per-chunk or per-chapter share might be worth it for someone who only wants to share one episode's notes rather than the whole series
### Chunk Builder (Setup Page)
- **Drag-to-select verses** — still click-then-shift-click; no click-and-drag range selection
@@ -25,13 +21,13 @@ _Refreshed 2026-07-06 — the previous version of this file predated ~40 commits
## UX / UI
### Navigation
- **Breadcrumb in header** — study page header only shows the project title (`App.jsx:4172`); no persistent "Genesis 1:15" reference next to it so users can tell at a glance where they are without checking the scripture panel
### Study Page
- **Word/char counters** — see above
- **Sticky bottom nav** — top Prev/Next chunk nav shipped (commit `103e20c`); a matching sticky bottom bar for long chunks would avoid scroll-back
### Reader
- **Whole-Bible search index isn't persisted** — the ~7MB `complete.json` fetch is cached in-memory only for the session; a page reload re-downloads it. Worth persisting to IndexedDB (not localStorage — too small) if this gets used often
- **Bookmark color picker is still an emoji button** (🎨) — the bookmark/copy icons became proper SVGs, but color-cycling didn't get the same treatment
### Home Page
- Search/filter/sort/rename are all implemented — nothing open here currently
@@ -40,36 +36,30 @@ _Refreshed 2026-07-06 — the previous version of this file predated ~40 commits
## Code Architecture
### State Management
- **`App.jsx` is now ~5,100 lines** (up from ~2,250 when this doc was last written) — still one component from line 9035044. Splitting into `pages/HomePage.jsx`, `pages/SetupPage.jsx`, `pages/StudyPage.jsx`, `pages/BibleReaderPage.jsx`, plus extracted hooks (`useProject`, `useGreekLookup`, `useAutosave`) is more valuable now than it was before, given the size increase
- **`commentarySource` doesn't persist** — resets to `'matthew-henry'` every session (`App.jsx:1107`), unlike `studyLayout`/`activeStudyTab` which do persist to localStorage via the same pattern
- **`App.jsx` is now ~5,700+ lines** — still one component. Splitting into `pages/HomePage.jsx`, `pages/SetupPage.jsx`, `pages/StudyPage.jsx`, `pages/BibleReaderPage.jsx`, plus extracted hooks (`useProject`, `useGreekLookup`, `useAutosave`) is more valuable now than ever given the continued size growth
### Sync / Persistence
- ~~No auth on the backend~~ — fixed; email/password accounts with httpOnly cookie sessions (`server/auth.js`, `server/sessionStore.js`), projects scoped per-user in both SQLite (`server/db.js`) and localStorage (`App.jsx` `switchStorageUser`/namespaced keys), and pre-existing local projects auto-claimed by the first registered account
- No rate-limiting on `/api/auth/*` — a determined attacker could brute-force a weak password; worth adding if this is ever reachable beyond a small trusted group
- No rate-limiting on `/api/auth/*` — a determined attacker could brute-force a weak password or 2FA code; worth adding if this is ever reachable beyond a small trusted group
- **Conflict resolution is still last-write-wins** — only `lastEdited` timestamps are compared; no "which version do you want to keep?" UI
- **"Restore"/"Pull latest from server" don't open the project** (`App.jsx:2997-3017`) — they refresh the local index but leave the user on the Home page instead of jumping into the study
- **Offline-first** — still no service worker; app requires a live connection to `bible.helloao.org` for chapter/audio/commentary loads with no cached fallback if that API is down
### Security (OWASP)
- ~~XSS via `dangerouslySetInnerHTML`~~ — fixed; `DOMPurify.sanitize()` now wraps both render paths (`App.jsx:4784`, `App.jsx:5020`)
- **No input validation on server** — still no max-length/character validation on `id`/`title` in `server/index.js`
- **CORS** — still no CORS headers configured
- **Shared HTML view is sandboxed but not escaped** — `buildExportHtml` interpolates OIA notes into HTML without escaping `<`/`>`/`&`; the public share view mitigates this by rendering in a `sandbox="allow-popups"` iframe (no `allow-scripts`, so injected `<script>`/event handlers can't execute), but the underlying string-building still isn't defense-in-depth. Worth properly HTML-escaping user text in `buildExportHtml` itself
---
## Performance
- **Verse data stored in project JSON** — still true; full verse text is saved per chapter in both localStorage and SQLite
- **Reader bookmark icon is unclear** — shows a 🏷️ tag emoji before bookmarking and only switches to 🔖 after (`App.jsx:3641`), but the help text says "bookmark icon to save" — a plain outline bookmark icon would read more clearly from the start
- **No audio playback speed control** — chapter/reader audio only has play/pause/stop (`App.jsx:1037`); a 0.75x/1x/1.5x toggle would help slow, careful study listening
- **Hardcoded external API, no fallback** — audio and commentary both call `bible.helloao.org` directly (`App.jsx:985`, `App.jsx:1129`) with no retry UI if the free API is briefly down
- **Hardcoded external API, no fallback** — audio and commentary both call `bible.helloao.org` directly with no retry UI if the free API is briefly down; whole-Bible search now adds a third hard dependency on this API (`/complete.json`)
---
## Testing
- Migration and prompt-building tests now exist (`migrateChunk`, `migrateProject`, `buildClaudePrompt`, `parseBibleChapter` are all covered in `src/utils.test.js`) — this section is essentially done
- Still missing: autosave debounce behavior, and coverage for the newer features (DOCX episode import, cross-ref auto-suggest, commentary loading)
- Missing: autosave debounce behavior, DOCX session-list import, cross-ref auto-suggest, commentary loading, and no coverage yet for the newer share-link/2FA/whole-Bible-search flows (all verified manually in-browser instead)
---