The Rust HTTP core always returns application/json content-type
regardless of the content_type field in the response dict. This is a
fundamental limitation of turboAPI's current Rust server - it was
designed for JSON APIs, not template-rendered HTML sites.
HTML content is correctly generated but served with wrong content-type,
causing browsers to download instead of render pages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turboAPI passes query string params as kwargs to handlers. Add **kwargs
to static file handlers so cache-bust params like ?v=30f664df don't
cause 500 errors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
turboAPI's Rust server doesn't serve mounted StaticFiles, so add
explicit routes for /static/{file} and /static/{subdir}/{file}.
Also patch ResponseHandler to properly extract body/content-type
from Response objects instead of JSON-serializing them.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Monkey-patch turboAPI's route registration to wrap handlers that expect
a Request parameter with a Starlette-compatible Request object built
from the Rust server's raw HTTP data. Also skip unsupported middleware
during Rust server initialization instead of failing.
This enables all HTML template routes to work alongside the JSON API
routes under turboAPI's Zig/Rust HTTP core.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace FastAPI with turboAPI across the entire codebase:
- Swap all imports from fastapi to turboapi (TurboAPI, APIRouter, HTTPException, etc.)
- Keep starlette imports for Jinja2Templates and StaticFiles (not yet in turboapi)
- Remove unsupported `example=` params from Query/Path declarations
- Update entry point to use turboapi's native server (app.run())
- Update test clients to use turboapi.testclient.TestClient
The app loads successfully with all 200+ routes registered. turboAPI's
Zig HTTP core provides significant throughput improvements over uvicorn.
Note: turboAPI's TestClient has limited support for Request injection
and Query defaults, causing some test failures. The actual server
runtime handles these correctly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pre-render ~1,277 high-traffic HTML pages (homepage, books, chapters)
at build time and serve them directly via nginx. All other routes
(verses, search, API, PDFs, Strong's) fall through to a FastAPI
sidecar. If the sidecar crashes, nginx continues serving static
pages and health checks.
Also harden the FastAPI app against the memory/crash issues:
- Switch from bare uvicorn to gunicorn with uvicorn workers
- Add --max-requests worker recycling to prevent memory leaks
- Add --timeout to kill hung workers
- Add per-IP rate limiting middleware (10 req/s, burst of 50)
- Add request timeout middleware (30s max per request)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use file modification time hash for base.js and tufte.css to
automatically bust browser cache when files are updated.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add "Your Reading Plans" section showing plans with saved progress
- Display progress bars and percentage on plan cards
- Show "Up next: Day X" for in-progress plans
- Include full Scripture text in all PDFs (including 365-day plans)
- Show Scripture references in collapsed day headers
- Arrow points right when collapsed, down when expanded
- Use green (#4a7c59) for completed days instead of dark color
- Enhanced keyboard navigation for chapter sections when expanded
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add API endpoint /api/reading-plans/{plan_id}/day/{day_num} for fetching
Scripture text on demand
- Update template to load text via API when days are expanded (not upfront)
- Implement cascading progress: checking a day marks all previous days
as complete, unchecking removes all subsequent days
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Features:
- Full Scripture text now available for ALL plans (including 365-day)
- Collapsible day sections - click to expand/collapse
- "Mark as Read" checkboxes with localStorage persistence
- Progress bar showing completion percentage
- Day navigation with completed days highlighted
- Expand All / Collapse All / Reset Progress buttons
- Keyboard shortcuts: j/k navigate, Enter/Space expand, x mark complete
- PDF verses now display one per line
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
New reading plans:
- Books of Moses in 40 Days (pentateuch_40)
- Major Prophets in 60 Days (prophets_60)
- Minor Prophets in 14 Days (minor_prophets_14)
- Wisdom Literature in 30 Days (wisdom_30)
- Historical Books in 45 Days (historical_45)
- General Epistles in 14 Days (general_epistles_14)
Features:
- Reading plan pages now show full Scripture text for plans 90 days or less
- Day navigation bar for quick jumping between days
- PDF exports include full Bible text for shorter plans
- Refactored Jinja filters into separate jinja_filters.py module
- Added parse_reading_reference() and get_reading_text() helpers
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated link_verse_references_in_text() and verse_reference_to_url()
to link to chapter view with anchors instead of dedicated verse pages.
This keeps users in the reading flow when clicking cross-references.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Same chapter refs: use anchor (#verse-X)
- Different chapter/book refs: link to chapter view with anchor
- Keeps users in reading flow instead of jumping to dedicated verse page
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add KJVNav.initSimpleNav() for DRY keyboard navigation across site
- Fix broken keyboard nav on 10+ resource pages (orphaned JS code)
- Left arrow on chapters now does browser back
- Add non-writing prophets: Moses, Samuel, Nathan, Elijah, Elisha
- Redesign chapter PDFs with glossary, cross-refs, book intro
- Style sidenotes as inline notes in all PDFs (fix checkbox squares)
- More liberal word studies in PDF output (for_pdf parameter)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added About link at bottom of sidebar navigation
- Added breadcrumbs to /about, /about/stats, /about/commentary, /about/cross-references
- Removed emoji from "Open Source & Free" heading on about page
All about-related pages now have proper navigation structure.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed URLs from:
- /commentary → /indexes/commentary
- /cross-references → /indexes/cross-references
Updated stats page links to use new URLs. Old routes removed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed both index pages to display books in biblical order (OT then NT)
instead of alphabetical order. Now starts with Genesis and ends with
Revelation, matching the order readers expect.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
New browseable index showing all 24,900 verses with cross-references:
Features:
- Organized by book and chapter
- Shows reference count per verse (blue badge)
- Links to individual verse pages
- Coverage statistics (80% of Bible)
- 120,858 total cross-references
- Clean, scannable interface
Route: GET /cross-references
Template: cross_references_index.html
Updates to stats page:
- Link to /commentary index
- Link to /cross-references index
- Link to /strongs concordance
This completes the major indexes for discovering
content - users can now browse all commentary,
cross-references, and Strong's entries systematically.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Detailed information about KJV Study including:
- What KJV Study is and key statistics
- Open source section (prominent) with GitHub link
- Creator information
- Theological approach and convictions
- Data sources and attributions
- Technical architecture details
- Contributing guidelines
- Privacy policy and analytics opt-out
- Resource links including /stats page
Highlights:
- Emphasizes free and open source nature
- Links to GitHub repository
- Explains conservative evangelical theological stance
- Credits all data sources (TSK, Strong's, etc.)
- Clear privacy commitments
- Encourages community contributions
🤖 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>
- Add no-cache headers to sw.js endpoint to prevent aggressive caching
- Move system status grid to top of offline page for debugging
- Show connection status, SW version, cache storage, bible data, pages cached
- Add SW version check that reads from actual sw.js file
- Keep download progress indicator in download section
- Move cached pages list to collapsible details
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Service workers can only control URLs within their scope. A service worker
at /static/sw.js couldn't control the root scope (/) without special headers.
- Add /sw.js route that serves the service worker with Service-Worker-Allowed: /
- Update registration to use /sw.js instead of /static/sw.js
🤖 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>
- Create chapter_interlinear_pdf.html template for PDF export
- Add /book/{book}/chapter/{chapter}/interlinear/pdf route
- Add PDF download button to interlinear page alongside print
- Include Hebrew/Greek text, English translations, and Strong's numbers
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Interactive family tree improvements:
- Add hamburger menu toggle for sidebar with localStorage persistence
- Smooth tween animation when navigating between people
- Preserve zoom level during navigation
- Narrower node cards (120px) with adjusted font sizes
- Remove minus indicators, keep only + for expandable nodes
- Add info button (i) on each node to open sidebar
- Enhanced info panel with more fields: title, Kekulé number,
siblings, children links, scripture references
- Add View Ancestors/Descendants links in sidebar
- Make ancestor nodes semi-transparent (60% opacity)
- Fix search input width with box-sizing
Strong's Concordance:
- Embed related Strong's entries in derivation section
- Show preview cards for referenced entries (e.g., H1 on H2 page)
- Display word, transliteration, and definition excerpt
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add get_all_strongs() function for paginated entry listing
- Create /strongs/hebrew and /strongs/greek routes with pagination
- Add strongs_language_index.html template with entry cards
- Update main Strong's page with browse cards for each language
- Hebrew: 8,674 entries across 87 pages
- Greek: 5,523 entries across 56 pages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Show all verses containing a Strong's number from interlinear data
- Display each verse as a card with reference, original word, and full text
- Highlight the translated English word in yellow
- Add dark mode support for highlighted text
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update sidebar link to point to /strongs
- Remove old /concordance route and template
- Update cache control settings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace naive string replace with regex-based filter
- Only linkify actual Strong's references (G/H followed by digits)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Hebrew (8674 entries) and Greek (5523 entries) dictionaries from openscriptures/strongs
- Create strongs.py module for lookups and search
- Add /strongs web page for search and browsing
- Add /strongs/{number} page for individual entries
- Add /api/strongs and /api/strongs/{number} API endpoints
- Update interlinear templates to link to our Strong's pages instead of BibleHub
Data source: https://github.com/openscriptures/strongs (CC-BY-SA)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Increase font sizes for Hebrew (2.2rem) and Greek (2rem) text
- Add proper RTL direction and font families for Hebrew
- Tighten word spacing for more natural reading flow
- Remove hover tooltips, keep click-to-expand details
- Increase English verse text size in chapter interlinear view
- Add is_old_testament to verse template context
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
New route: /book/{book}/chapter/{chapter}/interlinear
Shows all verses with word-by-word Hebrew/Greek analysis:
- Hebrew badge for OT, Greek badge for NT
- Same polished UI as verse page interlinear
- Click words for details, hover for definition preview
- Chapter navigation links
- Dark mode support
- Mobile bottom sheet for word details
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix interactive tree deep linking via query parameter
- Redesign /family-tree main page with card-based layout
- Add feature cards, stats card, generation cards, notable figures
- Highlight Family Tree on /resources with Interactive badge
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add DISABLE_ANALYTICS=true to docker-compose.yml for local dev
- Pass disable_analytics to Jinja2 templates as global
- Wrap Gauges analytics in conditional block
- Add blue/pink gender-based coloring to generation cards
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
PDF Script:
- Added --limit N parameter to process only first N books (for testing)
- Added --output FILE parameter for custom output filename
- Updated help text and examples
- Example: --limit 1 --output genesis.pdf to test with just Genesis
Name Linking:
- Fixed compound names like "Sarai or Sarah" not linking properly
- Now splits names on " or " and creates separate mappings for each variant
- Both "Sarai" and "Sarah" in Bible text will link to same person entry
- Preserves full compound name as well for exact matches
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The random verse endpoint was being cached by browsers, causing it to
always redirect to the same verse instead of selecting a new random
verse each time.
Changes:
- Added /random-verse to the no-cache path list in CacheControlMiddleware
- Set explicit cache control headers on the redirect response
- Changed status code to 302 (Found) for temporary redirect
- Added Pragma and Expires headers for better cache prevention
Tested with 5 consecutive requests, all returned unique verses.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Use negative lookahead to prevent matching words followed by 's
- Fixes issue where "LORD'S" was being split into "LORD" + "'S"
- Sidenotes now appear after complete words only
Removed the /bible/pdf endpoint (too resource-intensive for live requests)
and created a standalone script for offline PDF generation.
New script: scripts/generate_bible_pdf.py
- Generates complete KJV Bible PDF with all footnotes
- ~1000 pages with cross-references and word studies
- Progress tracking during generation
- Saves to kjv-complete-bible.pdf
Usage:
uv run python scripts/generate_bible_pdf.py
This is more efficient - generate once, serve as static file if needed,
rather than regenerating on every request.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>