1. Sticky header on scroll
- Shows current page title and breadcrumb navigation
- Appears when scrolling past the main breadcrumb
- Smooth slide-down animation
2. Font size controls (A/A buttons)
- Small, normal, large, x-large sizes
- Persisted to localStorage
- Positioned next to dark mode toggle
3. Prefetch next/prev pages
- Uses requestIdleCallback for non-blocking prefetch
- Prefetches chapter/verse/book navigation links
- Makes page-to-page navigation feel instant
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove sidebar toggle button on desktop (>1200px)
- Sidebar now always visible on desktop for better navigation
- Keep hamburger menu toggle on mobile/tablet (<1200px)
- Remove backtick keyboard shortcut for sidebar toggle
- Update accessibility page to remove backtick reference
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add manifest.json for PWA support (stops 404 requests)
- Add [ and ] keys to navigate between Strong's numbers
- Add info-card selection styles for keyboard nav
- Update accessibility page with Strong's shortcuts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added ` key to Global Shortcuts table and keyboard help modal.
Also added 'n' key to help modal for sidebar navigation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add stopPropagation() and return statements to sidebar keyboard
handlers to prevent events from reaching content navigation handlers.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Opens the sidebar (on mobile/collapsed) when pressing 'n'
- Closes sidebar when exiting nav mode with Escape
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add KJVNav.initGridNav for standardized 2D grid navigation
- Migrate books.html, topics.html, resources.html to use initGridNav
- Add sidebarActive check to all templates with custom keyboard handlers
- Add [ and ] shortcuts for prev/next chapter on chapter pages
- Add [ and ] shortcuts for prev/next book on book pages
- Update accessibility page with comprehensive keyboard shortcut docs
- Add honest note about keyboard navigation complexity
- Fix sidebar nav conflicting with main content selection
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix verse tooltip getting stuck after browser back (Safari bfcache)
- Remove kekule number badges from ancestors/descendants pages
- Keep gold border lines for Christ's lineage highlighting
- Fix Interactive Tree button text color in light mode
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added sidenote selection styles to style.css instead of
tufte.css to keep third-party CSS unmodified.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Moved sidenote user-select styles to tufte.css so they apply
across all pages, not just chapter pages.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Press 0 from anywhere on the site to return to the homepage.
Also updated the keyboard help modal to show this shortcut.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Increase --text-secondary from #a3a3a3 to #c4c4c4 for better readability
- Update verse text to use text-primary with 0.85 opacity for clearer Scripture
- Change verse item border to accent-color for better visual hierarchy
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Shortened nav help to "Tip: ↑/↓ to select verses • ? for more shortcuts"
- Changed 'p' keyboard shortcut from Reading Plans to PDF download
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Extracted ~1250 lines of JavaScript from base.html to static/base.js
- Reduced base.html from ~2700 lines to ~1440 lines
- Updated tests to expect 404 (not 500) for invalid resources
- Updated CLAUDE.md to reflect proper error handling
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Wrap prefers-color-scheme dark styles with html:not([data-theme="light"])
- Fixes interlinear text being white on yellowish background
- Updated verse.html, chapter_interlinear.html, tufte.css, base.html,
and family-tree-expansions.css
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed service worker, PWA manifest, offline page, and all related UI components to simplify the application and reduce bloat.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Collapsible category sections for cached pages
- Categories: Main Pages, Bible Chapters, Verse Commentary,
Interlinear, Stories, Topics, Study Guides, etc.
- Clean URL display: %20 replaced with spaces, paths cleaned up
- Keyboard navigation: j/k to navigate, Enter/Space to expand,
h/l for left/right, Esc to back out, u to enter URL nav mode
- Increased download concurrency from 50 to 100 workers
- Progress notifications every 250 completions (was 100)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace sequential batch downloads with a concurrent pool pattern
using 50 simultaneous workers. This dramatically speeds up the
caching of ~48,000 pages for offline use.
- Each worker pulls URLs from a shared queue
- Progress notifications sent every 100 pages
- Workers run in parallel using Promise.all()
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Service worker now responds to GET_CACHE_STATUS message
- /offline page queries caching status when it loads
- If download is in progress, shows progress bar immediately without requiring click
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major improvements to offline caching:
- Service worker now parses sitemaps dynamically instead of hardcoded URL lists
- Fetches /sitemap.xml and any child sitemaps (sitemap-main.xml, sitemap-verses.xml)
- Caches ALL pages found in sitemaps including 31,102 individual verse pages
- Much cleaner, smaller service worker (~300 lines vs ~1800 lines)
- Added status messages during sitemap parsing
- Better error handling with retry option
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Interlinear pages now redirect to offline reader with book/chapter params
- All uncached HTML pages now go to /offline instead of homepage
- Bumped cache version to v5
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- Caching now only starts when user clicks "Download for Offline Use" on /offline page
- Added all 186 Bible stories (including kids mode) to cache list
- Added progress bar and status indicators on /offline page
- Bumped cache version to v4
- Total cacheable pages: ~1,500 (1189 chapters + 186 stories + 66 books + resources)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated service worker to pre-cache:
- All 1189 chapter pages (Genesis 1 through Revelation 22)
- All 66 book overview pages
- All resource/reference pages (topics, stories, study guides, etc.)
- Total: ~1300+ pages for complete offline access
Also bumped cache version to v3 and increased batch size for faster caching.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Verified all URLs actually return 200 status
- Fixed topic URLs (need capital letters: /topics/Faith not /topics/faith)
- Fixed story URLs (use slugs like /stories/god-creates-the-world)
- Fixed resource URLs (e.g. /fruits-of-the-spirit not /fruits-of-spirit)
- Added all parables, reading plans, study guides
- Total: 388 pages now pre-cached in background
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Service worker now pre-caches ~160 pages in background after install
- Includes all resource pages, topics, study guides, stories, book pages
- Caches in batches of 5 with 1-second delays to avoid overwhelming server
- Progress indicator shows "Caching for offline: X%" in bottom-left
- Shows "Ready for offline! (X pages)" when complete, then fades out
- Bumped cache version to v2 to trigger re-cache
Combined with the Bible JSON (~4.7MB), the entire site is now
available offline after first visit.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Created /offline route with client-side Bible renderer
- Loads verses from cached JSON (verses-1769.json)
- Full book/chapter navigation with dropdowns
- Keyboard navigation (← → for chapters)
- Service worker redirects to offline reader when Bible pages fail
- Pre-caches offline reader page on install
- Auto-parses URL params (?book=Genesis&chapter=1)
When offline, users can read any chapter of the Bible using
the cached JSON data - no need to have visited the page before.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Created sw.js with caching strategies:
- Static assets (CSS, JS, fonts) - cache first
- Bible pages - network first, cache fallback
- API requests - network first with offline cache
- Pre-caches verses-1769.json (~4.7MB) on install
- Added service worker registration to base.html
- Added offline indicator (red badge in bottom-right)
- Linked manifest.json for PWA support
Users can now read the Bible offline after first visit.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Created a clean, Tufte-style og-image.png (1200x630) featuring "KJV Study" branding. This eliminates the 404 spam in logs from bots and social media crawlers trying to fetch the missing image, and provides proper preview images when the site is shared on social media platforms.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The sitemap-verses.xml file was contaminated with WeasyPrint import
warnings, causing "Document is empty" errors in Google Search Console.
Fixes:
- Suppress stdout/stderr during imports to prevent warnings in output
- Add error handling to sitemap-verses endpoint
- Regenerate clean sitemap-verses.xml (6.3MB, 31,102 verses)
The file now starts with proper XML declaration instead of error messages.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, verse URLs (31,102 pages) were excluded from the sitemap
to improve generation speed. This left SEO value on the table - Google
prioritizes URLs in sitemaps for crawling, and verse pages are 3-4
clicks deep, making discovery slow.
Solution: Static sitemap + sitemap index
-----------------------------------------
- Created generate_verse_sitemap.py to generate verse sitemap once
- Generated sitemap-verses.xml (6 MB, 31,102 verse URLs)
- Converted /sitemap.xml to a sitemap index
- Split into sitemap-main.xml (dynamic) and sitemap-verses.xml (static)
Benefits:
---------
- Zero runtime cost for verse sitemap (served as static file)
- Full SEO coverage of all 31k verse pages
- Google gets complete URL list immediately
- Main sitemap stays fast (no verse URL generation)
- CDN can cache verse sitemap indefinitely
Why this works:
---------------
Verse URLs are completely static - Genesis 1:1 will always be at the
same URL. The Bible hasn't changed in 2000+ years, so these URLs
never change. Generate once, commit to repo, infinite caching.
This trades "optimize build speed" for "optimize discoverability."
Build speed is a one-time cost; search rankings compound over time.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Convert all PDF generation endpoints from synchronous to async to
prevent blocking FastAPI's event loop during CPU-intensive operations.
Changes:
- Add render_html_to_pdf_async() using ThreadPoolExecutor (2 workers)
- Convert all PDF endpoints to async def
- Use await render_html_to_pdf_async() instead of blocking calls
- Keep render_html_to_pdf() for backward compatibility
Performance impact:
- Prevents event loop blocking during PDF generation
- Allows other requests to be processed while PDFs are rendering
- Limits concurrent PDF generation to 2 workers to control CPU usage
Files updated:
- kjvstudy_org/utils/pdf.py (new async implementation)
- kjvstudy_org/server.py (5 PDF endpoints)
- kjvstudy_org/routes/api.py (4 PDF endpoints)
- kjvstudy_org/routes/resources.py (7 PDF endpoints)
- kjvstudy_org/routes/stories.py (2 PDF endpoints)
- kjvstudy_org/routes/study_guides.py (1 PDF endpoint)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Allow sidenote numbers to display at their natural height instead
of being constrained to 2rem.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fix dark mode for both system preference and manual toggle:
- Support both @media (prefers-color-scheme: dark) and [data-theme="dark"]
- Fix interlinear word cards showing white in dark mode
- Fix sidenotes/marginnotes showing white boxes in dark mode
This ensures dark mode works whether users have system dark mode
enabled OR use the manual dark mode toggle button.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive dark mode support for:
- Sidenotes and marginnotes (fixing white box issue)
- Interlinear word cards and all text elements
- Links, headings, and borders in dark mode
- Buttons, inputs, and navigation elements
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Updated to latest version from tufte-css repository
- Kept existing font paths (/static/fonts/)
- Adds dark mode support via prefers-color-scheme
- Minor improvements and updates from upstream
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The commit removes the Scofield commentary feature and sidebar navigation, switching to a cleaner mobile-first layout. The main content is now centered with a max-width, and navigation is handled through a bottom bar.
The changes add a custom scrollbar and enhanced scroll functionality to
the sidebar, with cross-browser support, accessibility features, and
device-specific optimizations.
The changes remove several documentation files and simplify the iPad sidebar behavior to always show on non-mobile devices.
Key changes:
- Remove unused documentation markdown files
- Remove keyboard shortcut to toggle sidebar
- Make sidebar always visible on non-mobile devices
- Fix CSS and JavaScript to prevent sidebar from hiding
- Simplify sidebar positioning and transitions