- Admin: sign-up Open / Invite only / Closed with single-use invite links
- Present mode for scripts (auto-scroll) and outlines (step through, pace vs planned minutes)
- Series: group studies on the dashboard, filter by series, calendar file for a study's sessions
- Lesson handout: printable page per session (passage, outline, questions, writing lines)
- Save a chunk's notes as your own study template (synced)
- Voice dictation for notes and scripts (browser speech recognition)
- Reading progress: map of the 66 books and a calendar of days read, synced and merged across devices
- Export highlights and bookmarks as Markdown or Word, grouped by named colour
- Verse of the day push to the ntfy topic (needs IQBIBLE_API_KEY)
- Sharing: co-teacher editing via single-use invite links; read-only links can expire and take a passcode
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- The search box matches tags as well as title and passage; "#tag" searches
tags only
- Tag chips (with counts) replace the Tag dropdown; several can be on at
once and a study must have all of them
- Tags on each study card are clickable filters
- "No studies match" message with a Clear filters link
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A Grid / List toggle beside the sort and tag filters. List is one compact
row per study (small book cover, title with Rename, passage, tags, date,
Resume and Delete). The choice is remembered on the device.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Selection
- Selected text uses a per-theme colour (it was nearly invisible on Dark)
- The colour picker also appears on touch screens after dragging the selection
handles, and sits below the selection there so the system menu doesn't cover it
Highlights
- Each highlight remembers its translation and whether it covers the whole verse
- In another translation the same words are found again (ignoring case and
punctuation); whole-verse highlights cover the whole verse; when the wording
differs, the verse gets a small colour dot instead of marking the wrong words
- Older highlights are checked against their saved words instead of trusted
- Server keeps the new fields
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Verse of the day: card over a picture (a different one each day, or chosen),
12 drawn scenes plus photos from public/verse-backgrounds, and "Share as
image" (also on the Reader's verse panel) that saves or shares a PNG with the
same background, a theme look, or a photo from the device
- Study cards get a cover banner named for the book, coloured by kind of book
- Outline "Build from my notes": abbreviations like "A.D. 63." no longer end a
sentence
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
New "Build from my notes" on the Outline page: a main point per chunk with
Background, What the text says, What it means and How we respond under it
(a point per note line, long lines become a headline plus a note), with the
chunk's cross-references and words attached. Also builds a single chunk's
sections. Only adds what's missing; Undo offered.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Commentary tab: "More sources" switch with notes for the whole chunk and
"Add to notes" quoting
- Word study: Lexicons button for words with a Strong's number
- New "Study aids" tab (any verse of the chunk; topics add as tags)
- Outline points: "Add from IQ Bible" attaches topics, Gospel parallels,
manuscript notes and places
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
IQ Bible picks the verse; its words come from BSB, NET, ESV, NLT, CSB or
NASB (default: your reading translation, remembered per device), with the
KJV as a fallback if that Bible can't load.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
setup.sh starts the production server without SESSION_SECRET, so the new
"refuse to start" check stopped the app after an update. When the variable
is unset in production the server now makes a random secret once and keeps
it in DATA_DIR/.session-secret (mode 600, git-ignored).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Sync and data safety
- Autosave flushes on leaving a study or the tab; storage-full errors are reported
- Unsynced studies, deletes and ink are queued and retried when back online
- Deletes propagate across devices (with a "Keep it" undo) and no longer resurrect
- Server assigns study versions (no client-clock conflicts); "Combine both"
merges a conflicted study chunk by chunk
- Reading-plan progress made offline is merged, not overwritten; plans, ink and
marks are cleared from the device on sign-out
Security
- Block SSRF through the ntfy reminder URL; failure-only rate limiting per IP and
account; constant-time login; TOTP replay protection; input validation;
SESSION_SECRET required in production; admin user delete fixed
- Forgot password: one-time code sent to the account's ntfy topic
Features
- IQ Bible proxy (route allow-list, text-only caching per its terms): more
commentaries, lexicons, study aids, daily verse and devotional, plan calendar
export, narrations, podcast background
- Study templates, reading-plan catch-up, account export, daily database snapshots
Tests and tooling
- ESLint config; App tests split into src/test; tests for sync queues, library
hook, merge, templates, IQ Bible UI and reset form
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Drag the left edge of the verse side panel to resize it (arrow keys too,
Shift for bigger steps; double-click resets). The text reflows to make room,
and the width is remembered on this device. Reuses the Study page's resize
handle; the hook now takes the CSS variable to drive.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A highlighter button beside Bookmarks opens your highlights (by colour);
Bookmarks now opens the bookmarks. Each shows in the accent colour when you
have some. "H" opens the highlights.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Tooltips on hover and keyboard focus across the app: icon-only buttons show
their label, existing titles show in the app's style without the browser's
delay, and the reader's main buttons show shortcut hints ("Search (/)").
Touch screens are unaffected.
- Reader: cross-references (under verses and in the Cross-refs tab) open the
passage's text in the side panel without leaving the chapter; "Open chapter"
goes there when wanted
- Reader: the verse panel now has a Highlight row of colours for one-tap
whole-verse highlighting (tap again to remove, Clear for all, with Undo);
selecting words still highlights just those
- Fix: a cross-reference preview was cleared when React ran the panel's
effect twice (development builds)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Hero ("Read it. Study it. Teach it.") with small previews of the outline
and the translation comparison
- Four groups of features (Read, Study, Teach, Everywhere), all things the
app really does
- Sign-in / create-account card stays in view beside the tour on wide
screens and comes first on a phone; theme switcher before signing in
- Sign-in, account creation, 2FA and error handling unchanged
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Read-only share page: a calm paper-toned page rendered natively (no
iframe), with outline tabs, Print / PDF, numbered points with accent
numerals, type tags, notes and verse quotes; works on phones
- Printable / PDF page restyled to match (serif, hanging numerals, tidy
spacing, footer)
- Word outline restyled: eyebrow + title block, bold main points, accent
numerals, set-off verse quotes, tidy margins
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Share on the Outline page opens a sheet: create / copy / turn off a
read-only link, share the link with the system share sheet, or send the
outline as text
- The link has its own token (separate from the whole-study share link) and
the public endpoint returns only the outlines, rebuilt field by field:
no observations, interpretations, applications, scripts or word notes
- Opening the link shows the outline(s) with no sign-in, a switcher between
the whole-study and per-chunk outlines, and Print / PDF
- New outline_share_token column (added automatically on start)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A button beside Aa in the reader's top bar opens a Compare translations
sheet (pick the Bible to compare with, show/hide the differing-word
highlights). It shows as active while a comparison is on. The controls
moved out of the Aa sheet; "C" opens it from the keyboard.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Word-level comparison (ignores case and punctuation): differing words are
marked in both columns of the side-by-side view
- Chapter summary ("NET is 18% different from BSB · 37 of 39 verses differ")
with links to the most different verses, and a percentage on each verse
- Compare tab on a verse shows each translation's difference from the one
being read, with the differing words marked
- "Highlight differences" setting; your own highlights and search matches
always win where they overlap a difference mark
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- One outline for the whole study plus one per chunk (picker at the top);
chunk outlines can start from the chunk's verses, each carrying its words
- Points can have a type (illustration, application, quote, question,
transition), minutes (with a running total), a longer note, verse text
fetched from a passage, and cross-references / word studies attached from
the chunk
- Share (system share sheet, or copy), Print / PDF, Copy as text, Word and
Markdown downloads for any one outline
- All of it included in the Markdown, HTML/PDF and Word study exports,
with each chunk's outline under that chunk
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Study
- New Outline stage (hierarchical I./A./1. points, linked to chunks, in all exports);
the chunk stage is now "Chunks"
- Home cards: passages shown as ranges, tags capped with "+N more"
Reader
- Side-by-side translations and a Compare tab per verse
- Typeface, line spacing, verse-number settings; text and column scale with the screen
- Highlights/bookmarks sheet with named colours (synced); BSB footnote spacing fix
- Cmd-K palette (passages, studies, notes, marks), keyboard shortcuts and "?" help
Flow and safety
- Toasts with Undo replace most confirm()/alert()
- Back/Forward move between pages
- Server refuses saves over a newer copy (409); keep-mine / use-other banner;
opening a study no longer re-stamps it
- Latest chapter request wins when flipping quickly
Offline and data
- Save books, plan days or a whole BSB/NET for offline
- Service worker fixes: helloao /api/ URLs were skipped and responses cloned too late
- Settings: download/restore a full backup
Accessibility
- Sheets trap focus and close on Escape, skip link, focus ring, reduced motion,
theme contrast raised to 4.5:1 (with a test)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Drops viewport-fit=cover so the iPad/iPhone status bar is its own area and the system's
top-edge blur no longer covers the app bar. Fixed-height study stages are position:fixed so
they cannot scroll the document, and min-h-screen/100vh become dvh units.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The scroll position of the previous page used to carry over, which on iPad makes the
system blur the app bar when content is scrolled under it.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The app now sets theme-color, color-scheme and the page background from the chosen theme,
so the iPad status-bar area no longer shows a light band over a dark theme. Every top bar
leaves room for the status bar via a safe-top class (replacing a rule that padded every
<header>). Install defaults match the paper theme.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A blank three-column session list (Session #, Title, Passage) with instructions and
example rows, built in the browser on demand. A test imports the generated file back
through the real importer.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The Study stage's right column has a drag handle (mouse, arrow keys, double-click
or Home to reset); the width is remembered per device. The app now starts on the
user's chosen home page from the first render instead of showing My Studies
first. Tests wait on page headings so a lazily loaded page can't be confused
with hidden text from the previous one.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Settings gets a Preferences section: theme, default Bible, the Bible new reading
plans start in, verse layout, commentary, text size, reading width, audio
narrator (the last three stay per device; text size and narrator are now
remembered). A Home page setting (My Studies, Bible Reader or Reading Plans)
decides where the app opens and where every Home button goes; already being
there means My Studies. Back arrows are labelled Home. Tests cover every page
leading back.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Bookmarks and text highlights are saved per user and merged across devices
(union on first contact, newer server copy when this device is clean). Theme,
default translation, verse layout, commentary source and reading position sync
too, each with its own timestamp so the newest change to each setting wins.
The Reader never moves under you while it is open. Signing out clears this
device's marks and forgets sync timestamps.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Plans can no longer have more days than chapters (existing ones heal), and
opening a plan never strands the Reader on an empty day. The Reader shows
Done drawing while inking (Escape also exits). Reminders use the user's own
timezone, send within a 3 hour grace window, and Settings has a Send test
notification button.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
App bar: brand, Studies / Read Bible / Reading Plans, and one account menu
(theme, Settings, Admin, Log out). Study stage: notes get their own box above
the resources in the right column. Settings, Admin and the login page use the
reader themes; add a theme-aware danger colour.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Studies now move through a stage bar in the reader's themes. Outline splits
chunks by clicking between verses (join merges notes) and suggests chunks from
section headings. Study is three panes: outline, passage with an Observe /
Interpret / Apply accordion, and commentary / word study / cross-refs / people
& places for the chunk; original words are added by clicking them in the
interlinear. Script drafts an outline from notes; Export holds files and the
share link. Home, Import and the Pronunciation guide are restyled. Study
projects are BSB only.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Reader: plan strip with a dot per chapter, plan sheet (day picker, chapter
ticks, translation, streak, other plans), end-of-day card that steps through
the day and rolls into the next, and chapter-level auto-marking.
Each plan remembers its own translation (BSB, ESV, NLT, CSB, NASB, NET) and the
Reader follows it while a plan is open. Plans home redesigned in the reader's
themes with a Continue card, in-progress plans, a filterable catalog, and
sheets for details and the custom-plan builder.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
BSB and NET are indexed in the browser; ESV, NLT, CSB and NASB are searched
through a server proxy (keys stay server-side). Results page in 25 at a time
and jump to the verse. Also fixes a stray trailing comma in CSB chapter text.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The Reader's player follows the translation on screen: ESV plays its own
recording via a server route that resolves the ESV API's audio redirect;
other translations keep the BSB narrators.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
New reading surface with paper/sepia/dark themes, slim top and bottom bars,
and sheets for navigation, search, settings, audio and per-verse study tools.
Plan progress is built into the reader. Page-flip mode removed. ESV added via
the server-side proxy (ESV_API_KEY).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Adds a per-verse panel with seven HelloAO commentaries and Theographic
people/places/events, and NET as a fifth Reader translation.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Reader and Reading Plans get a translation picker. Licensed translations are
fetched through a server-side api.bible proxy so the key stays off the client.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The sign-in pull (GET /api/reading-plans -> merge) had the same silent-
failure gap the push side had before the last fix: a failed fetch just
left local state as-is with zero indication anything was wrong. Moved it
into the hook as pullServerReadingProgress(), which reports failures
through the same error banner/retry the push path already uses.
Also found and fixed a real bug while testing this: the "skip syncing on
the very first render" guard used a boolean ref, which React 18 StrictMode
defeats by double-invoking effects in dev — the second invocation saw the
flag already flipped and fired a spurious sync of stale localStorage data
before the app had even confirmed sign-in, occasionally producing a false
"couldn't sync" banner on fresh loads. Replaced it with a reference-equality
check against the state object captured at mount, which both of
StrictMode's synthetic invocations see identically. Caught this in
useReadingPlans.js's own test run, not manual testing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reading plan sync was truly fire-and-forget: a failed PUT to
/api/reading-plans left the change stuck on that device with no
indication anything was wrong, which is exactly what "doesn't sync
across devices" looks like from the outside.
Moved the sync call out of the setState updater and into a proper effect
keyed on state, so success/failure can be tracked. Both Home and Reading
Plans now show a red banner with the actual error (HTTP status or network
error) and a Retry button when a sync fails, mirroring how study project
sync already reports errors. Verified the full cycle locally: normal sync,
a killed-server failure showing the banner, and Retry recovering once the
server's back.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reading plan days now offer "Study this" (seeds a new chunk-builder project
with the day's full passage and jumps straight into the Study editor) and
"Listen" (starts book-mode audio at the right chapter via a new
handlePlayBookAudioFrom, avoiding a stale-closure bug the reader-state
approach would hit). Fixed the "Listen to BSB Audio" player only rendering
when a study project existed, leaving Listen with nowhere to show up.
The service worker now caches audio.bible.helloao.org (the actual host
serving narrator audio, not just the text/cross-ref API) and no longer
tries to cache 206 Partial Content responses, which the Cache API rejects
and was throwing unhandled rejections for every range-requested audio file.
Added a reading journal export (Settings > My reading journal): gathers
bookmarks, text highlights, and completed plans, fetches their verse text,
and offers a .docx download or a print-to-PDF page.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reading plans now track a cross-plan activity log for streaks, surface a
combined "today's reading" view on both Home and the Reading Plans page,
and let custom plans be edited after creation (including narrowing a book
to a specific chapter range). The reader auto-marks a plan's day read after
a dwell period, active plans that fall behind their pace get a "catch me
up" banner, and a new Settings section wires up daily reading reminders
via ntfy.sh, checked once a minute by a small server-side scheduler.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaces the old single-book reading goal with a full Reading Plans page:
9 built-in plans (Whole Bible, OT/NT, topical) with cover photos and
color-themed cards, day-by-day checklists synced to the server per user,
inline "mark today read" in the Bible reader, and user-created plans with
their own book picker and an optional uploaded cover photo.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a shared AudioPlayer component with a seekable progress bar,
big play/pause button, and icon transport controls, replacing the
row of text buttons on both the book and chapter audio players.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Header: navigation buttons grouped; Study Guide, Podcast, and
Pronunciation Guide move into a Tools menu (disabled until a chunk
exists), set apart from Export and Share by a divider.
- Only one header dropdown is open at a time, and it closes on an
outside click or Escape.
- Study page: drop the duplicate Prev/Next and counter at the top; the
fixed bottom bar is the single chunk navigation and now shows a
readable "Chunk N of M".
- Mobile empty-state hint points to Back to Chunks.
- Tests: Tools menu, one-dropdown-at-a-time, Escape/outside click.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With no gloss-map entry, the English gloss falls back to the KJV
definition, so both English Gloss and Short Definition show it. Assert
both instead of failing on the duplicate.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PronunciationPage still read speakOriginalWord from context after it
moved to utils/wordStudy, so Speak would have thrown. Import it directly.
App.jsx: consolidate imports, update comments, list all pages.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The setup form, active chapter tab, verse range selection, typed/bulk/
cross-chapter chunk creation, reorder, and delete move out of App.
- Setup now opens on the chapter holding the chunk last studied (e.g.
after Back to Chunks), and the Add Chapter form suggests the chapter
after the project's last one instead of repeating the current one.
- openNewProject/goHome/resume/import no longer reset setup state by hand;
SetupPage starts fresh each time it opens.
- Tests: add-chapter default, Back to Chunks chapter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- StudyPage owns layout/tabs/collapsed sections, tags, DOCX script
import, chunk navigation, keyboard shortcuts, and the selected-chunk
values derived from the project.
- useStudyResources: commentary + interlinear for the selected chunk's
chapter. These now load only on the study page (they previously also
fetched while on Setup).
- useCrossRefs: typed refs, dataset suggestions, verse text.
- useWordStudy: word entries, Strong's lookups, suggestion picker.
- Fix: study-page messages (word suggestions, DOCX import, lookups) set a
status that only SetupPage displayed, so they were never seen. They
now show as a toast on the study page.
- copyVerse moves into ReaderPage.
- Tests: toast, arrow-key navigation, cross-refs, tags.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ProjectHeader component replaces the headerButtons JSX in context; it
owns the export menu and share panel state.
- useShareLink (share status/enable/revoke/copy) and useSharedView
(?share= read-only view, now used directly by the router).
- utils/projectExport: HTML/Markdown/DOCX download and print-to-PDF.
- AuthStatus component replaces the authStatus JSX in context.
- Pages import wordStudy helpers directly instead of via context.
- Remove dead copyPronunciationGuide (PronunciationPage has its own).
- Tests: Markdown export, enabling a share link, the ?share= view.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only the Reader's canvas uses them now. A module-level lastPen keeps the
chosen tool/color/size when Draw mode is toggled off and on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Search, tag filter, full-text note search, and rename state live in
HomePage. The sort choice is remembered in localStorage.
- useProjectLibrary owns opening/renaming/deleting projects and the
server reconcile (auto-restore + newer-on-server list).
- useReadingPlan owns the reading plan shared by Home and Reader.
- Tests: note search, rename, delete, sort memory, reading plan. Test
setup now resets the storage namespace between tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The session-list import form, preview, and runEpisodeImport now live in
ImportPage. useAvailableTranslations fetches the translation list once per
visit for both Import and Setup. Drops the never-read importFile state.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Strong's dictionary loaders, lexicon lookup, gloss helpers, cross-ref
formatting, and speech move out of App. Dictionaries are now cached at
module level (still one download per visit), and a failed download is no
longer cached forever, so the next lookup retries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All admin state (tab, users, projects, loading/error, preview, reset
result) and the data loader were only used by AdminPage, so they now live
there as local state instead of in App's context. The page loads its data
when it opens (still gated on authUser.isAdmin; the server enforces it too).
Add tests: admin sees users and projects, deleting a user reloads the
list, and non-admins get no Admin button.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- useAuth owns authUser/authServerDown, the startup session check, and
signIn/logout, so every sign-in path runs the same follow-up (switch
local storage to the account, load reader ink). Previously reader ink
only loaded on a page refresh, not right after logging in.
- Login/2FA form state now lives in AuthPage, and 2FA setup, password
change, and podcast name state in SettingsPage (23 fewer context
values; typing in these forms no longer re-renders all of App).
- Add tests for form sign-in, 2FA, session restore + logout, and the
Settings podcast-name prefill.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Home page's whole-book player and the Reader's chapter player share one
<audio> element, so they move together. App now just calls
useAudio(readerBook, readerChapter) and spreads the result into context.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Performance:
- Lazy-load pages, docx, and mammoth (initial JS 1,298 KB -> ~290 KB)
- Gzip responses and cache hashed assets for a year
- Memoize DrawCanvas strokes so ink isn't redrawn on every render
- Precompute whole-Bible search index and defer the query while typing
- Reload once if a lazy chunk is missing after a deploy
Deployment:
- setup.sh builds and runs one production server on APP_PORT (default
5173); --dev keeps the old Vite dev setup
- Session cookie uses secure: 'auto' so login works behind any proxy
Chunk editor:
- Remove the Draw layout, Ink Notes panel, and ink in HTML export
(existing inkStrokes data is left in saved projects)
Refactor:
- Move module-level helpers out of App.jsx into src/utils/*
- Extract Bible reader state and logic into hooks/useBibleReader
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the copy-to-clipboard button with a dedicated page that shows
all collected Greek/Hebrew words as cards grouped by language. Each
card displays the original script large, transliteration, Strong's
number, English gloss, definition, part of speech, and a Speak button.
Includes a search/filter and a "Copy all" fallback for the old behavior.
Move buildPronunciationGuide to bibleUtils.jsx to avoid circular imports.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add server.watch.ignored for .git/** so chokidar doesn't pick up
changes to git object files during git pull/fetch on the server
- Add .dockerignore to exclude .git, node_modules, and dist from
the Docker build context
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extract shared utilities (constants, helpers, components) from App.jsx
into src/utils/bibleUtils.jsx so page components can import from there
instead of from App.jsx. This breaks the App.jsx <-> pages circular
dependency that was triggering vite:import-analysis warnings and causing
the React hook dispatcher to be null at runtime.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
package-lock.json was generated with npm 11; node:20-alpine ships with
npm 10 which can't resolve optional esbuild platform packages from the
newer lockfile format.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
better-sqlite3 is a native C++ addon that requires python3, make, and g++
to compile on Alpine Linux. Added to both builder and production stages.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Passes selectedChunkVerses as headerContent to the inline DrawCanvas so
highlights overlay the actual scripture text, matching annotate mode.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Apple Pencil hover cursor: previews brush size/shape before contact
- Tilt shading: tilted pen strokes widen and reduce thinning via tiltX/Y
- Two-finger undo in draw mode (non-stylus two-finger tap)
- Copy & open Claude buttons: copies study/podcast prompt then opens claude.ai/new
- Inline ink canvas in study notes (DrawCanvas embedded in Notes tab)
- Full-text search across all project notes with 300ms debounce
- Reading plan: set a book + week goal, mark chapters read from the reader
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a "Page" toggle in the reader tool strip. When enabled, the verse
panel becomes a fixed-height container using CSS column-width to create
one column per page-width. Content flows naturally into successive pages;
long chapters simply have more pages. Bottom nav shows ← Back/Prev ch.
and Next/Next ch. → with a page counter (e.g. Genesis 1 · 2/3). Swipe
left/right and arrow keys also navigate pages before crossing chapter
boundaries. Preference persisted to localStorage.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wide mode now enters focus state automatically: the full toolbar collapses
and a slim frosted bar appears at the top showing the current chapter name,
Prev/Next buttons, and a ⚙ Tools button to restore the toolbar. A ✕ Hide
button inside the toolbar lets you re-enter focus mode without toggling wide.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Swipe left/right on mobile to go between chapters (60px threshold,
ignores vertical-dominant gestures so scrolling still works)
- Left/right arrow keys on desktop navigate chapters (skips inputs)
- Fixed side ‹ › buttons at viewport midpoint for one-tap chapter nav;
disappear when at the first/last chapter, hidden in draw mode
- Wide toggle (⊞) switches between narrow reading column (max-w-3xl)
and full-width two-column layout (max-w-7xl, md:columns-2); persisted
to localStorage so the preference survives page reloads
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace non-functional sticky nav with a fixed bottom bar (position: fixed)
that stays visible while scrolling long study notes; hides in draw mode
- Add pb-20 to main so the bar never covers the last study section
- Cache whole-Bible search index (BSB complete.json, ~7MB) in IndexedDB
with a 7-day TTL so repeated searches skip the network fetch entirely
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously reader ink was localStorage-only so it never followed the
user to a different browser or device.
- New reader_ink table (user_id, book_abbrev, chapter, strokes JSON)
- GET /api/reader/ink — loads all pages for the signed-in user
- PUT /api/reader/ink/:book/:chapter — upserts one page
- On startup, client fetches server ink and merges it over localStorage
(server wins so the most-recently saved version always wins)
- updateReaderPageInk debounces a PUT call 1 s after the last stroke,
so rapid Apple Pencil strokes don't flood the server
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
black-translucent status bar overlays page content, pushing the top
nav buttons behind the status bar where they can't be tapped. Switch
to black (status bar takes its own space, content starts below).
Also add env(safe-area-inset-top) padding on <header> elements when
running in standalone/PWA mode so notched iPhones are handled too.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PWA:
- manifest.json with name, icons, theme/background color, standalone display
- PNG icons (192, 512, 180 apple-touch) generated via pure Node.js (no deps)
- index.html: manifest link, theme-color, apple-mobile-web-app-* meta tags,
viewport-fit=cover for iPhone notch/Dynamic Island
- service worker extended to cache app shell (static assets + index.html)
with network-first for navigation, cache-first for hashed assets,
network-first-with-cache-fallback for external Bible APIs
Expandable canvas:
- "Add More Space" button below each draw canvas adds a full notebook page
- Existing ink rescales to preserve visual pixel positions (no stretching)
- Page count embedded as metadata in the strokes array so it survives
navigation without a separate state key
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously draw mode was closed whenever the book or chapter changed.
Now it stays open so the user can flip between chapters while drawing;
each chapter has its own canvas (ink is keyed per bookAbbrev_chapter).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
iPadOS Pointer Events fire pointercancel immediately after pointerdown
for Apple Pencil strokes (triggered by palm detection or canvas-width
resets from React re-renders), forcing the user to tap twice to start
every stroke. The Touch Events API with touchType === 'stylus' bypasses
this issue entirely — Touch Events have no equivalent cancellation
problem and reliably identify Pencil vs finger input. Pointer Events
remain as the fallback for non-iOS platforms.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
React's synthetic event system delegates to the document root, which
on iOS Safari causes pointermove passive:true to block preventDefault
and introduces timing issues that drop every other stroke.
Attaching directly to the canvas element with {passive: false} on
pointermove gives iOS the explicit signal it needs to suppress scroll
and deliver all pen events reliably.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
setPointerCapture/hasPointerCapture is unreliable on iPadOS — Safari
sometimes fires pointercancel which releases capture, causing every other
stroke's pointermove events to be discarded. Replace with a simple
isDrawingRef boolean that is set on pointerdown and cleared on pointerup,
avoiding the capture API entirely.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add user-select: none (with WebKit prefix) to the DrawCanvas wrapper so
the browser does not start a text-selection gesture when the pencil drags
across the component.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
touchAction: 'pan-y pinch-zoom' let the browser intercept vertical
pencil movement as a scroll gesture before JavaScript could prevent it.
Setting 'none' hands all pointer input to our handlers exclusively.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Discards any local package-lock.json drift (cross-platform regeneration)
then pulls latest from GitHub before setup.sh runs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use max-w-full on main when draw mode is active so the layout fills the
viewport. Scripture panel is a fixed 288px column; notebook canvas takes
all remaining space.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace stacked scripture-overlay layout with a side-by-side flex row:
the chapter text panel sits on the left (sticky, scrollable) and the
ruled notebook canvas sits on the right. Stacks vertically on mobile.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DrawCanvas now accepts a headerContent prop — when provided, a transparent
canvas extends over the scripture text so you can draw directly on the
verses, with ruled notebook space below for additional notes.
Study page draw mode shows the full chunk passage this way instead of a
compact unwritable strip. Reader page draw mode replaces the verse list
with the same combined layout (all chapter verses + notebook canvas),
hiding the verse list while active.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Draw mode in the study page replaces all note panels with a full ruled
notebook canvas (no cross-refs, observations, or text boxes) so the user
has a clean writing surface. Ink strokes are saved per chunk and exported
as SVG in the HTML export.
The reader page gets a Draw toggle button that reveals the same notebook
canvas below the verse list, with strokes persisted per book+chapter in
localStorage via readerInkByPage.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a third layout option alongside Stacked and Split. In Draw mode a
canvas overlay covers the scripture panel; the Pointer Events API routes
Apple Pencil input to perfect-freehand strokes while letting finger
touches fall through for normal scrolling. A floating toolbar provides
pen, highlighter, and eraser tools, six color swatches, S/M/L sizes,
undo, clear, and a Done button to return to Stacked view.
Strokes are stored as inkStrokes[] on each chunk and rendered as a
read-only transparent canvas overlay (InkLayer) in Stacked/Split modes.
migrateChunk is updated so all existing chunks get inkStrokes: [] on
first load.
Also adds a simple in-memory rate limiter on auth endpoints (10 attempts
per 15 min per IP).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>