All notable changes to BookShelf will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Docker Build Failure - Updated Vite build target to ES2022 for compatibility with esbuild 0.28.1
- Series Dropdown on Edit Page - Fixed "create new series" option not appearing when typing a new series name on book edit page
- Audible Results Crash - Fixed TypeError when displaying Audible search results
- Rating field from Audible API was not always a number, causing
.toFixed()to fail - Added proper type checking before formatting rating values
- Rating field from Audible API was not always a number, causing
- Deprecated Meta Tag - Replaced
apple-mobile-web-app-capablewithmobile-web-app-capable
- esbuild - Updated to 0.28.1 (fixes remote code execution via NPM_CONFIG_REGISTRY - High)
- Metadata Search Results Not Displaying - Fixed UI not showing search results
- Component was not correctly parsing nested API response structure
- Added Audible to provider names and colors in search modal
- Updated footer text to reflect current providers
- Goodreads Provider - Removed (blocked by AWS WAF bot detection)
- Amazon Provider - Removed (blocked by robot mitigation)
- These providers cannot work from server environments without a headless browser
- Open Library User-Agent - Now identifies as BookShelf app for 3x rate limit (3 req/sec)
- Google Books (with optional API key for higher quota)
- Open Library
- Audible (audiobooks with narrators)
- Hardcover (requires free API key)
- ComicVine (requires free API key)
- Google Books API Key Support - Add optional API key for higher quota
- New setting
metadata.googlebooks_api_keyin admin settings - Without API key: uses shared quota (often exhausted)
- With API key: 1000 requests/day free tier from Google Cloud
- New setting
- Goodreads Disabled by Default - Blocked by AWS WAF bot detection
- Amazon Disabled by Default - Blocked by robot mitigation
- Both providers can still be enabled in settings but may not work from server environments
- Audible Provider Missing from Search - Audible wasn't being configured in metadata search
- Added Audible settings to settingsService (enabled by default)
- Added Audible domain setting for regional support
- Added Audible to the search API's provider configuration
- Audible Search - Fixed Audible provider returning 0 results
- Changed from using separate
titleandauthorparams to combinedkeywordsparam - Audible API requires the
keywordsparameter for general search
- Changed from using separate
- Metadata Provider User Agents - All metadata providers now use browser-like user agents
- Prevents blocking by APIs that reject non-browser requests
- Updated: Audible, Google Books, Open Library, ComicVine, Hardcover
- Amazon and Goodreads already had browser user agents
- Audible Metadata Provider - New provider for audiobook metadata
- Searches Audible's public API for audiobook information
- Returns narrator information (unique to Audible)
- Includes series information with sequence numbers
- High-quality cover images (up to 1024px)
- Runtime in minutes, publisher, release date, ratings
- Category/genre information from Audible's category ladders
- Enabled by default as the 7th metadata provider
- Cover Image Download - Cover images from URLs are now automatically downloaded when adding/editing books
- Added
coverService.tsfor centralized cover download logic - Books API now auto-downloads cover from
originalCoverUrlif nocoverImageUrlis provided - Works for both creating new books and updating existing ones
- Added
- Series Dropdown - Fixed "Add new series" option not appearing when no series exist
- Dropdown now always shows when focused, with helpful prompts
- Shows "Type to search or create a new series" when empty
- Narrator Dropdown - Same fix applied to narrator selection
- Dropdown now always shows when focused
- Shows "Type to search or create a new narrator" when empty
- Metadata Search Error Handling - Improved error reporting for book metadata providers
- Google Books now properly reports quota exceeded errors (429/RESOURCE_EXHAUSTED)
- Amazon provider now detects blocking/CAPTCHA and reports meaningful errors
- Goodreads provider now handles rate limiting and blocking gracefully
- Open Library provider improved error handling for network issues
- Search API now returns error details per provider so UI can show what went wrong
- All providers return
erroranderrorCodefields when searches fail
- CI/CD Cleanup - Removed HookFlow deployment webhook from GitHub Actions (server no longer in use)
- Dependency Updates - Fixed all 25 Dependabot security alerts
- Updated
drizzle-ormto 0.45.2 (fixes SQL injection via improperly escaped identifiers - High x2) - Updated
viteto 6.3.5 (fixes path traversal and WebSocket vulnerabilities - High + Medium) - Updated
nodemailerto 8.0.9 (fixes SMTP command injection via CRLF - Medium x2, Low x2) - Updated
svelteto 5.55.9 (fixes XSS via DOM clobbering, SSR, promises, ReDoS - Medium x4) - Updated
@sveltejs/kitto 2.61.1 (fixes query.batch cross-talk - Medium) - Added override for
@xmldom/xmldom0.9.10 (fixes XML injection and DoS - High x5) - Added override for
fast-xml-builder1.2.0 (fixes attribute value bypass - High) - Updated override for
devalueto 5.8.1 (fixes DoS via sparse array - High) - Added override for
lodash4.18.1 (fixes prototype pollution and code injection - High + Medium) - Added override for
picomatch4.0.4 (fixes method injection - Medium x2) - Resolved all npm audit warnings (0 vulnerabilities)
- Updated
- API v1 SQL Errors - Fixed "no such column: bookCount" errors in API v1 endpoints
- Fixed orderBy clause in authors, narrators, series, genres, formats, and tags endpoints
- Computed columns now properly referenced in SQLite queries
- Fresh Docker Setup Database Error - Fixed "no such column: booksContained" error on new container installations
- Added missing
booksContainedcolumn to auto-migration for fresh databases - Fixes GitHub issue #2
- Added missing
- REST API v1 Fully Featured - Complete external API for automation and integrations
- Search on all resources -
?search=nameparameter on books, authors, series, narrators, genres, formats, and tags - Full Narrator CRUD - New endpoints at
/api/v1/narratorsand/api/v1/narrators/[id]- GET (list with search and pagination), POST (create), PUT (update), DELETE
- Returns book and audiobook counts per narrator
- Full Genre CRUD - Added POST to
/api/v1/genresand GET/PUT/DELETE to/api/v1/genres/[id] - Full Format CRUD - Added POST to
/api/v1/formatsand GET/PUT/DELETE to/api/v1/formats/[id] - Full Tag CRUD - Added POST to
/api/v1/tagsand GET/PUT/DELETE to/api/v1/tags/[id] - Narrator lookup by name - Book creation supports
narratorfield (looked up by name) in addition tonarratorId - booksContained field - Book creation/response now includes
booksContainedfor omnibus editions - originalCoverUrl field - Book response includes
originalCoverUrlfrom metadata sources - Updated API documentation - OpenAPI spec includes all v1 endpoints with full schema definitions
- Search on all resources -
- Dependency Updates - Fixed all Dependabot security alerts
- Updated
fast-xml-parserto 5.5.8 via override (fixes entity expansion vulnerabilities - High + Medium) - Updated
music-metadatato 11.12.3 (fixes infinite loop in ASF parser - High) - Updated
file-typeto 21.3.4 via music-metadata (fixes ZIP decompression bomb and ASF loop - Medium x2) - Updated
devalueto 5.6.4 via override (fixes prototype pollution - Medium + Low) - Resolved all npm audit warnings (0 vulnerabilities)
- Updated
- Omnibus/Collection Support in Statistics - Books can now count as multiple books in your reading stats
- New "Books Contained" field in the book editor (Basic Info tab)
- Automatically calculated from series book ranges (e.g., books 1-5 = 5 books)
- Can be manually overridden for collections, anthologies, or omnibus editions
- Affects all statistics: total books, books read this year, reading goals, etc.
- Default value is 1 for regular books
- Dependency Updates - Fixed all security vulnerabilities
- Updated
svelteto 5.53.7 (fixes XSS vulnerabilities in SSR) - Updated
rollupto 4.59.0 (fixes arbitrary file write via path traversal) - Updated
fast-xml-parserto 5.3.8 (fixes stack overflow in XMLBuilder) - Updated
@sveltejs/kitto 2.53.3 (fixes DoS in form handling) - Resolved all npm audit warnings (0 vulnerabilities)
- Updated
- Metadata Search Not Applying Authors/Series/Cover - When adding a new book via metadata search, authors, series, and cover image were not being saved
- Authors, series, and genres are now included in default selected fields
applyMetadataResultnow handles authors (lookup or create by name)applyMetadataResultnow handles series with book number (lookup or create by name)applyMetadataResultnow handles genres (lookup or create by name)
- Cover Images Not Displaying - Book covers from metadata search now display properly
- Added
originalCoverUrlfallback to all book display components - Library cards, rows, modals, and search results now show external cover URLs when local cover not downloaded
- Added
- Full REST API v1 Write Operations - Complete CRUD support for the REST API
- POST, PUT, DELETE for
/api/v1/books- Create, update, and delete books - POST, PUT, DELETE for
/api/v1/authors- Create, update, and delete authors - POST, PUT, DELETE for
/api/v1/series- Create, update, and delete series - Status/genre/format lookup by name (case-insensitive)
- Full API specification available at
GET /api/v1?token=YOUR_TOKEN
- POST, PUT, DELETE for
- API Token Authentication - Full API token system for external integrations
- Users can generate API tokens from Account → API Tokens page
- Tokens use secure
bks_prefix format with SHA-256 hashing - Support for optional expiration dates
- Bearer token authentication for all API endpoints
- Token management UI with create, view, and revoke functionality
- Last used tracking for security monitoring
GET /api/tokens- List all API tokens for authenticated userPOST /api/tokens- Create a new API tokenDELETE /api/tokens- Revoke all tokensGET /api/tokens/[id]- Get a specific tokenPUT /api/tokens/[id]- Update token nameDELETE /api/tokens/[id]- Revoke a specific token
- Dashboard Chart - Fixed "Books Read This Year" chart showing 0 instead of actual count
- Chart was querying wrong table (
userBooksinstead ofbooks) - Now uses same data source as the "Read This Year" stat for consistency
- Chart was querying wrong table (
- Dependency Updates - Fixed all security vulnerabilities
- Updated
bcryptfrom 5.1.1 to 6.0.0 (fixes high severity tar vulnerabilities) - Updated
@sveltejs/kitto 2.50.1 - Updated
svelteto 5.48.1 - Updated
@sveltejs/adapter-nodeto 5.5.2 - Fixed lodash prototype pollution vulnerability
- Resolved all npm audit warnings (0 vulnerabilities)
- Updated
- EPUB Reader Progress Percentage - Fixed reading percentage always showing 0%
- epub.js requires locations to be generated before percentage can be calculated
- Now generates locations on book load so percentage tracking works immediately
- Progress bar now shows actual reading progress
- Kobo Reading Progress Regression - Fixed reading progress being reset to 0% by race conditions
- Web reader sometimes sends 0% progress on initial load or visibility changes
- Now prevents overwriting higher progress with lower values
- Kobo sync will no longer regress progress to 0%
- Kobo Reading Progress Sync (Web → Device) - Improved reading state sync from web reader to Kobo devices
- Changed from
ChangedReadingStatetoChangedEntitlementformat for better device compatibility - Added
PriorityTimestampfield to reading state for proper sync ordering - Added debug endpoint for viewing reading state sync status
- Kobo devices should now receive reading progress updates from the web reader during sync
- Changed from
- Kobo Settings Authentication - Fixed "Unauthorized" error when enabling Kobo sync from settings page
- The
/api/kobo/settingsendpoint was incorrectly bypassing session authentication - Settings endpoint now properly authenticates via session cookie like other API endpoints
- The
- UI - Increased sidebar logo size by 20% for better visibility
- Kobo Reading Progress Sync - Fixed bidirectional reading progress sync between web reader and Kobo devices
- Web reader progress now syncs to Kobo devices during next sync
- Fixed
ChangedReadingStateformat to use nestedReadingStatewrapper expected by Kobo devices - Added
lastSyncedToDevicetracking to detect unsynced progress updates
- Kobo Initialization - Added many missing fields to the initialization response that Kobo devices expect
- Added
api_endpoint,reading_services_host,user_ratings,autocomplete,store_search, and many other fields - Now matches the configuration format used by other Kobo sync implementations (calibre-web, BookLore)
- Added
- Kobo Debug Logging - Added request logging to initialization and sync endpoints to help diagnose connection issues
- Kobo Debug Endpoint - Added entitlement generation test to debug endpoint for troubleshooting sync issues
- Kobo Sync - Fixed books without ebook files being incorrectly marked as synced
- Only books that actually generate entitlements (have ebook files) are now marked as synced
- Debug endpoint now shows ebook path info to help diagnose sync issues
- Kobo Sync Book Filtering - Fixed books with no owner (from single-user setups) not appearing in Kobo sync
- Kobo API Authentication - Fixed Kobo sync endpoints requiring session auth instead of token-based auth
- Kobo devices now properly authenticate via the token in the URL path
- Previously, requests would redirect to login page
- Kobo Device Sync - Sync your BookShelf library directly to Kobo e-readers
- BookShelf acts as a Kobo sync server - your device connects to BookShelf instead of Kobo's servers
- Tag-based sync: Add the "kobo" tag to any book to sync it to your device
- Reading progress sync: Bidirectional progress synchronization between device and BookShelf
- Kobo Store proxy: Still access your purchased Kobo books - those requests are forwarded to Kobo's servers
- New settings section with detailed setup instructions for configuring your Kobo device
- Connected device tracking with last sync time
- Troubleshooting guide included in settings
- New database tables:
kobo_users,kobo_devices,kobo_sync_state,kobo_reading_state - New API endpoints under
/api/kobo/[token]/v1/:/initialization- Kobo resources configuration/library/sync- Library sync with pagination/library/[bookId]/metadata- Book metadata/library/[bookId]/state- Reading state (GET/PUT)/books/[bookId]/download- Ebook download/books/[imageId]/thumbnail/...- Cover images/auth/deviceand/auth/refresh- Device authentication- Catch-all proxy for Kobo store requests
- Ebook Download - Fixed 404 error when downloading ebooks from the media page
- Added missing
/api/ebooks/[id]/downloadendpoint - Downloads now trigger proper file download (attachment) instead of inline viewing
- Added missing
- KOReader Sync Info - Added info box in KOReader settings explaining sync limitations
- Clarifies that KOReader → Browser works perfectly
- Explains that Browser → KOReader only syncs percentage (not exact position)
- Recommends reading a few pages on KOReader first for best sync experience
- KOReader Sync - Prevent false sync prompts when browser can't provide navigation data
- KOReader uses XPointer format for EPUB navigation; browser uses EPUB CFI (incompatible)
- When no valid XPointer exists, return null so KOReader doesn't show misleading prompts
- Browser progress is still stored internally but not advertised until KOReader provides XPointer
- How sync works now:
- KOReader → Browser: Works perfectly (browser uses percentage)
- Browser → KOReader: Only prompts if KOReader previously set an XPointer (navigates to last KOReader position)
- If you only read in browser, KOReader won't prompt until you also read on device
- KOReader Sync Navigation - Only return valid XPointer to KOReader
- KOReader calls
GotoXPointer(progress)which fails with non-XPointer strings - Now returns empty progress string unless it's a valid XPointer (starts with
/) - KOReader will show "continue at X%?" but won't navigate to wrong location
- This matches Booklore's approach: web and KOReader track positions separately
- KOReader calls
- KOReader Sync Position Format - Preserve XPointer when syncing from browser
- KOReader uses XPointer format for EPUB positions, not EPUB CFI
- Browser was overwriting KOReader's XPointer with incompatible CFI format
- Now preserves KOReader's XPointer and only updates percentage
- This fixes "goes to title page" issue when syncing from browser to KOReader
- KOReader MD5 Hash Algorithm - Finally correct! 32-bit overflow means offset 0 first
- LuaJIT
lshift(1024, 30)= 0 due to 32-bit signed integer overflow - So i=-1 produces offset 0, not a huge number that gets skipped
- Correct offsets: 0, 1024, 4096, 16384, 65536, 262144, 1048576, ...
- Verified by downloading epub and comparing hash with KOReader's actual hash
- IMPORTANT: After upgrading, run "POST /api/admin/rehash-ebooks?force=true"
- LuaJIT
- KOReader MD5 Hash Algorithm - Wrong assumption about overflow (superseded by 2.5.19)
- Assumed
1024 << 30was huge, but it's actually 0 in 32-bit signed - Effective offsets: 1024, 4096, 16384, 65536, ... (missing offset 0)
- Reference: http://bitop.luajit.org/api.html
- IMPORTANT: After upgrading, run "POST /api/admin/rehash-ebooks?force=true"
- Assumed
- KOReader MD5 Hash Algorithm - Incorrect assumption about Lua lshift (superseded by 2.5.18)
- Incorrectly assumed negative shift acts as right shift
- Offsets: 256, 1024, 4096... was wrong
- Reference: koreader/koreader#14448
- IMPORTANT: After upgrading, run "POST /api/admin/rehash-ebooks?force=true"
- KOReader MD5 Hash Algorithm - Use Booklore's proven implementation (superseded by 2.5.17)
- Matches Booklore's Java FileFingerprint.java exactly
- Offsets: 1024, 4096, 16384, 65536, ... (starting at i=0)
- This implementation is known to work with KOReader devices
- IMPORTANT: After upgrading, run "POST /api/admin/rehash-ebooks?force=true"
- KOReader MD5 Hash Algorithm - Attempted Lua lshift matching (superseded by 2.5.16)
- Delete KOReader Sync Entries - Added delete button to remove individual sync entries from KOReader settings
- Useful for cleaning up stale or duplicate progress entries after hash algorithm changes
- Each recent activity entry now has a trash icon to delete it
- KOReader Bidirectional Sync - Fixed browser-to-KOReader progress sync not working
- Previous algorithm started reading at offset 0 due to JavaScript bit shift behavior with negative numbers
- Now matches Booklore's proven Java implementation: starts at offset 1024 (i=0), not offset 0
- IMPORTANT: After upgrading, run "POST /api/admin/rehash-ebooks?force=true" to recalculate all hashes
- Then sync from KOReader once to update progress entries with correct hashes
- KOReader Progress Not Loading in Browser Reader - Fixed critical bug where progress from KOReader wasn't applied when opening book in browser
- KOReader stores percentage as 0-1 (e.g., 0.30 for 30%), but browser reader expected 0-100
syncProgressToBooknow converts KOReader percentage to 0-100 format before storing- Browser reader now normalizes percentage values, handling both formats for backwards compatibility
- Books synced from KOReader will now correctly resume at the synced position
- Chapter Title Update Error - Fixed "Cannot read properties of undefined (reading 'then')" error
book.navigation.get()can return undefined or a synchronous value, not always a Promise- Now checks if result is a Promise before calling
.then()on it - Handles both async and sync navigation results correctly
- Browser Reader Null Reference Errors - Fixed console errors when reading ebooks
- Added null checks to
updateProgress,saveProgress, andsaveProgressBeaconfunctions - Prevents "Cannot read properties of null" errors in epub.js location handling
- Reader now gracefully handles incomplete location data from epub.js events
- Added null checks to
- Reading Progress Display on Book Page - Show ebook and audiobook progress
- Ebook card shows progress bar, percentage, and "Last read X ago"
- Audiobook section shows listening progress and "Last listened X ago"
- Button changes from "Read/Listen" to "Continue" when there's progress
- Browser Reader KOReader Progress Crash - Fixed "Cannot Read Book" error when opening books with KOReader-synced progress
- KOReader uses different location format than EPUB.js CFI
- Now falls back to percentage-based navigation when CFI location is invalid
- Reader checks for "epubcfi" prefix before attempting CFI-based navigation
- KOReader MD5 Hash Compatibility - Fixed MD5 hash mismatch between BookShelf and KOReader
- Implemented KOReader's partial MD5 algorithm (samples 1024-byte chunks at specific offsets)
- BookShelf now generates the exact same MD5 hash that KOReader uses
- Previously, full-file MD5 was used which didn't match KOReader's partial MD5
- Reference: KOReader GitHub Discussion #14448
- Regenerate All Hashes button in Admin Settings → Storage
- Use
?force=trueparameter with POST /api/admin/rehash-ebooks to regenerate ALL ebook hashes - Needed after algorithm change to update existing hashes to KOReader-compatible format
- Use
- Admin UI now shows separate buttons for "Generate Missing" vs "Regenerate All"
- Manual KOReader Progress Linking - Link unlinked KOReader sync entries to books in your library
- Useful when the same ebook has different MD5 hashes (e.g., sideloaded vs OPDS-downloaded versions)
- Unlinked entries show a "Link" button in Account Settings → KOReader Sync
- Search for books by title or author to link
- Linking also updates the book's MD5 hash for future automatic syncing
- MD5 Hash Generation UI - Admin button in Settings → Storage to generate missing ebook MD5 hashes
- Shows stats: how many ebooks have hashes vs need them
- One-click generation for all missing hashes
- Required for KOReader sync to match ebooks uploaded before v2.5.2
- Detailed KOReader sync error messages - Browser console now shows specific failure reasons
No KOReader credentials configured- Need to set up credentials in Account SettingsKOReader sync is disabled- Need to enable sync in Account SettingsBook has no MD5 hash- Run the hash generation in Admin Settings
- Browser console logging for KOReader sync - See sync status directly in browser DevTools console
- Shows
[KOReader Sync] Progress synced to KOReader: XX%when sync succeeds - Shows
[KOReader Sync] Not synced (no credentials, disabled, or missing MD5 hash)when sync fails
- Shows
- API now returns
koreaderSyncedboolean in progress save response
- KOReader Sync Percentage Fix - Fixed percentage conversion between browser (0-100) and KOReader (0-1) formats
- Added admin endpoint
POST /api/admin/rehash-ebooksto compute MD5 hashes for existing ebooks - Added detailed console logging for KOReader sync debugging
- Books uploaded before v2.5.2 need MD5 hashes computed via the admin endpoint for sync to work
- KOReader ↔ BookShelf Bidirectional Sync - Reading progress syncs between e-reader and browser
- Progress from KOReader automatically updates the book's reading position in BookShelf
- Progress from BookShelf's browser reader syncs back to KOReader
- Automatic matching via MD5 hash of ebook files
- When you read on your Kobo, you can continue in the browser (and vice versa)
- Works with EPUB, PDF, and CBZ files
- Added
ebookMd5column to books table for ebook file identification - MD5 hash computed and stored when ebooks are uploaded or imported
- Bidirectional sync only occurs when book has matching MD5 hash
- KOReader Sync Activity History - See recent sync activity in the KOReader settings panel
- Shows last 5 sync events with book title, progress percentage, device name, and relative time
- Visual progress bars for each synced document
- Displays total sync entry count
- KOReader Sync - Sync reading progress from KOReader on e-readers (Kobo, Kindle, etc.)
- Compatible with KOReader's built-in sync protocol (KOSync)
- Configure KOReader credentials in Account Settings → KOReader Sync
- Progress syncs automatically when reading on your e-reader
- Separate credentials from your BookShelf login (username/password for KOReader)
- Enable/disable sync per user
- Instructions for configuring KOReader included in the UI
- Compact Books Toolbar - Redesigned the books page toolbar to be more space-efficient
- All controls now fit on a single line (search, sort, view toggle, book count, items per page, pagination)
- New items-per-page selector: choose between 12, 24, 48, or 96 books per page
- Inline pagination controls in the toolbar header
- Reduced vertical space usage for more room to display books
- OPDS Ebook Downloads - Fixed ebook downloads not working from OPDS clients (e-readers)
- Created dedicated OPDS download endpoint at
/opds/download/[id]with Basic Auth support - E-readers can now successfully download ebooks using the same credentials as the OPDS catalog
- Created dedicated OPDS download endpoint at
- HTTP Access on Local Networks - Fixed login not working when accessing via IP address over HTTP
- Session cookies now use
secureflag based on ORIGIN setting (https:// = secure, http:// = not secure) - Allows self-hosted users to access BookShelf via local IP without HTTPS
- Created shared cookie utility for consistent cookie settings across all auth endpoints
- Session cookies now use
- Setup Wizard Email Verification - First admin user created during setup is now automatically email-verified
- Eliminates chicken-and-egg problem where email isn't configured yet during initial setup
- Admin can log in immediately after completing the setup wizard
- Fresh Install Schema Errors - Fixed additional table schema mismatches preventing fresh installations
- Added missing
slugcolumn to genres table - Fixed series table: uses
titlefield (notname), addednumBooks,comments,statusId,genreId - Fixed authors table: added
birthPlaceandcommentscolumns - Fixed seriesstatuses table: added
keyandisSystemcolumns - Fixed tags table: added
isSystemcolumn - All raw SQL table definitions now match Drizzle ORM schema
- Added missing
- Fresh Install Setup Error - Fixed "NOT NULL constraint failed: users.passwordHash" error on new installations
- Updated database migration to use correct column name (
passwordinstead ofpasswordHash) - Added missing
usernamecolumn to users table creation script - Synchronized raw SQL schema with Drizzle ORM schema
- Updated database migration to use correct column name (
- Update Available Banner - Non-intrusive notification when a new version is released
- Slim banner appears at the top of the page when an update is available
- Shows current version and latest version with link to release notes
- Dismissible - won't show again until a newer version is released
- Checks GitHub Releases API (cached for 24 hours to minimize API calls)
- Respects theme colors with accent gradient background
- Rebranding - Renamed "BookShelf V2" to "BookShelf" throughout all documentation
- Updated package.json name from "bookshelf-v2" to "bookshelf"
- Updated all docs-site HTML pages with correct GitHub and Docker image URLs
- Updated README, CONTRIBUTING, ROADMAP, and other documentation
- Updated Dockerfile labels and docker-compose configurations
- Standardized GitHub repo URL to
iamernie/BookShelf - Standardized Docker image to
ghcr.io/iamernie/bookshelf
- Sidebar & Profile Menu Redesign - Cleaner layout for links
- GitHub icon now appears inline next to version number in sidebar footer
- Documentation link moved to profile dropdown menu (with external link indicator)
- Docs URL now points to GitHub Pages
- GitHub & Documentation Links - Added links to GitHub repo and documentation in sidebar footer
- Links appear below the collapse button
- Work in both expanded and collapsed sidebar modes
- HTML Stripping in Metadata - Book descriptions from metadata providers now have HTML tags stripped
- Converts
<br>tags to newlines for proper paragraph formatting - Converts
</p>tags to double newlines for paragraph breaks - Applied to all metadata providers: Google Books, Open Library, Goodreads, Hardcover, Amazon, ComicVine
- Converts
- Back Button Navigation - Fixed issue where back button on book detail page would navigate to dashboard instead of the page you came from
- Now properly stores return URL when navigating from books list (including page number)
- Falls back to
/booksinstead of unpredictablehistory.back()
- Improved Cover Image Display - Book covers now use a modern blur-background technique
- Full cover image is always visible without cropping (uses
object-contain) - Blurred version of cover fills the background for non-standard aspect ratios
- Adds subtle drop shadow for depth
- Applied to BookCard grid, book detail page, similar books, and edit page preview
- Full cover image is always visible without cropping (uses
- Fixed Code Scanning Alerts - Resolved 13 high-severity security issues flagged by GitHub CodeQL
- Incomplete multi-character sanitization: Added
stripHtmlTags()utility that loops until all HTML tags are removed, preventing bypass with nested tags like<<script> - Incomplete string escaping: Added
escapeGraphQLString()utility that escapes both backslashes and quotes for GraphQL queries - Double escaping vulnerability: Fixed XML entity decoder to decode
&last, preventing double-decode attacks - Affected services: goodreadsProvider, amazonProvider, comicVineProvider, hardcoverProvider, wikipediaService, narratorService, emailService, ebookMetadataService, settingsService
- Incomplete multi-character sanitization: Added
- Fixed Dependabot Vulnerabilities - Resolved 2 security alerts
- Updated
drizzle-kitto 0.31.8 (fixes esbuild vulnerability) - Added npm overrides for
cookie(^0.7.0) andesbuild(^0.25.0) to patch transitive dependencies
- Updated
- Sidebar Logo Size - Increased logo size from 32px to 40px for better visibility
- Series Number Spacing - Added missing space between series name and number on book view page (e.g., "Undying Mercenaries #24" instead of "Undying Mercenaries#24")
- Metadata Lookup Button - Renamed "Update" to "Lookup" for clarity on book view page
- Provider Ratings - Imported ratings from metadata providers (Google Books, Goodreads, etc.) are now stored separately from your personal rating
- New "Community Rating" card on book view page shows the provider's rating, source, and rating count
- Your personal star rating is never overwritten by metadata imports
- Provider rating includes source name (e.g., "googlebooks", "goodreads") and total rating count
- Google Books Cover Import - Fixed blank/placeholder images when importing covers
- Changed to use zoom=1 (more reliable than higher zoom levels)
- Added fallback to thumbnail URL if main cover fails
- Added minimum file size check to reject placeholder images
- Metadata Lookup Button - Added "Lookup" button directly on book view page header
- Quickly search and apply metadata from Google Books, Goodreads, etc. without going to edit page
- Improved Back Navigation - After editing a book, back button returns to where you came from (e.g., series page, author page) instead of always going to books list
- ntfy Push Notifications - Real-time push notifications via ntfy
- Admin Configuration - New "Notifications" tab in admin settings
- Enable/disable ntfy system-wide
- Configure ntfy server URL (default: ntfy.sh)
- Set admin topic for system notifications (backup completed, etc.)
- Test notification button for admin topic
- User Preferences - Personal notification settings in account settings
- Configure your own ntfy topic
- Master enable/disable toggle
- Per-event preferences: book added, book completed, goal reached, series completed
- Test notification button
- Automatic Notifications
- Book added to library
- Book marked as completed (READ status)
- Series completed (all books in series marked as read)
- Backup completed (admin topic)
- Works with self-hosted ntfy servers or the public ntfy.sh service
- Subscribe to your topic in the ntfy mobile app or web UI to receive notifications
- Admin Configuration - New "Notifications" tab in admin settings
- Create New Entities Inline - When adding/editing a book, you can now create new authors, series, narrators, and genres directly from the dropdown
- Type a name that doesn't exist and click "Create [name]" to add it
- The new entity is immediately selected and available for use
- Searchable dropdowns for Genre and Narrator (previously simple selects)
- Dashboard Null Rating - Fixed crash when highest rated book has null rating
- Added null check before calling toFixed() on rating
- Dashboard Query Fix - Fixed SQL query using wrong table alias for audiobook_progress
- Changed raw SQL
ap.durationto proper Drizzle column references - Fixes "no such column: ap.duration" error on dashboard
- Changed raw SQL
- Database Migration - Added missing
durationandprogresscolumns toaudiobook_progresstable- Ensures columns exist in upgraded databases
- Secure Session Cookies - Session cookies now set
secure: truein production- Prevents session hijacking over unencrypted connections
- Development mode (HTTP) still works for local testing
- Settings API Restricted - Settings endpoint now requires admin role
- Prevents non-admin users from reading sensitive configuration (SMTP credentials, etc.)
- Build Error - Fixed duplicate variable declaration in book API endpoint
- Security Recommendations - Added security audit document with prioritized recommendations
- What's New Modal Icons - Fixed section icons not displaying in the What's New changelog modal
- Changed from direct component tag to
svelte:componentfor proper dynamic component rendering
- Changed from direct component tag to
- Public Library Book Editing - Fixed permission error when editing public library books
- Admins and librarians can now edit public library book metadata
- The PUT endpoint was using personal library permission checks for all books
- Now correctly checks
canManagePublicLibrarypermission for public books
- Enhanced Dashboard Statistics - More stats on the dashboard
- Average pages per book (Avg Pages)
- Total narrators count
- Listening hours (for audiobook users)
- DNF rate percentage (for users with DNF books)
- Top Narrators section (like Top Authors, for audiobook listeners)
- Highest Rated Book highlight with cover, title, author, and rating
- Dashboard Chart Bars - Fixed "Books Read This Year" chart bars not displaying
- CSS percentage heights weren't propagating through Tailwind classes
- Changed to explicit inline height styles for reliable rendering
- Admin Console Logs - Fixed 404 error on admin logs endpoint in Docker production
- The
logs/gitignore pattern was incorrectly ignoringsrc/routes/api/admin/logs/ - Changed to
/logs/to only ignore root-level logs directory
- The
- Debug Chart Endpoint - Added
/api/admin/debug-chartfor diagnosing chart data issues
- Dashboard Charts - Fixed "Books Read This Year" chart not displaying data
- Date comparisons were failing due to timezone-formatted date strings in SQLite
- Also fixes "Read This Year" count and "Pages This Year" stats
- Media Sources - Track where your books are purchased or owned
- Add sources like Audible, Kindle, Physical, Kobo, Apple Books, etc.
- Books can have multiple sources (bought both Kindle and audiobook)
- "Owned On" badges display on book detail page with icons and colors
- Manage sources in the new Media tab on book edit page
- Per-User Private Sources - Regular users can create their own custom sources
- Add private sources like local bookstores, Storytel, or any custom source
- Private sources only visible to the user who created them
- System-wide sources managed by admins in Admin → Media Sources
- Media Sources Admin Page - New admin page to manage system-wide sources
- Default sources seeded: Audible, Kindle, Physical, Kobo, Apple Books, Google Play Books
- Customize icons, colors, URLs, and display order
- Diagnostics Updates - Media sources now included in database health checks
- Shows total, system, and user-created source counts
- Detects orphaned book-media source relationships
- Detects unused user-created sources
- Repair functions to clean up orphaned data
- Ebook Missing Files - Fixed false "missing" status for uploaded ebooks
- Ebook existence check now properly resolves storage paths
- AI Book Recommendations - Get personalized book suggestions based on any book
- New "Get Recommendations" button in the Similar Books tab on book detail pages
- AI analyzes the book's title, author, series, genre, and description
- Click "Add to Wishlist" to add recommended books directly to your library
- Requires OpenAI API key configured in Admin Settings
- Ebook Reading Position Sync - Reading progress now reliably syncs across devices
- Added
visibilitychangeandpagehideevent handlers to save progress when page is hidden - Using
sendBeaconAPI for reliable progress saves on page close/navigation - Fixes position not syncing when switching from iPhone to computer
- Added
- Audiobook Access Permissions - Fixed audiobook streaming for public library audiobooks
- Stream, progress, and chapters APIs now properly check public access and user library membership
- No longer incorrectly denies access to audiobooks the user should be able to play
- Photo Upload for Authors & Narrators - Add photos via file upload or URL download
- Upload photos directly from your device on author/narrator edit pages
- Download photos from any URL (including Wikipedia)
- Photos served via
/photos/route for runtime-uploaded content - Supports JPG, PNG, GIF, WebP, and AVIF formats
- Enhanced Narrator System - Narrators now match the author experience
- Narrator Tags - Tag narrators with custom tags, colors, and icons
- Wikipedia Metadata Search - Look up narrator info from Wikipedia and import bio, photo, dates
- Narrator Detail Page - New
/narrators/[id]page with inline bio editing, stats, and audiobook grid - Extended Narrator Fields - Birth/death dates, birthplace, photo URL, website, Wikipedia URL, comments
- Narrator Cards - Show photos, cover images, tags, and audiobook counts on list page
- OIDC Token Exchange - Fixed "unexpected state response parameter" error
- Pass
expectedStateto openid-client'sauthorizationCodeGrantfor proper CSRF validation
- Pass
- OIDC Account Linking - Fixed logged-in users being redirected to dashboard instead of linking their account
- Account linking now properly handles the
linkingUserIdbefore checking for existing links - Shows appropriate messages for "already linked", "linked to another account", and successful linking
- Added error/success feedback in the Connected Accounts section
- Account linking now properly handles the
- OIDC Setup Instructions - Comprehensive setup guide on the OIDC settings page
- Step-by-step instructions for Authentik, Keycloak, Google, and GitHub
- Links to official documentation for each provider
- Displays the correct Redirect URI (callback URL) to configure
- Troubleshooting tips for common issues
- OIDC Authentication - Fixed redirect loop preventing login with OIDC providers
- SvelteKit's redirect was being incorrectly caught as an error
- What's New Modal - Admin users see a changelog popup after app updates
- Shows latest version changes with organized sections
- "Don't show again for this version" checkbox
- Links to full changelog page at /admin/changelog
- Toggle in Settings → UI to disable globally
- Environment variable
DISABLE_WHATS_NEW=trueto disable completely
- Customizable Dashboard Companion Section - Choose what shows beside Currently Reading
- Options: Up Next in Series (default), Smart Collection, or Nothing (full width)
- Side-by-side layout when companion section has content
- Configure in Dashboard Settings modal
- Updated App Logo - New colorful logo for sidebar, favicon, and PWA icons
- Renamed "Continue Reading" to "Currently Reading" throughout the app
- Inline Rating Control - Click stars directly on book detail page to rate books
- Hover effect shows preview of rating
- Click same star again to clear rating
- Instant save with toast notification
- Inline Status Selector - Change book status directly from detail page
- Dropdown selector styled with status color
- No need to enter edit mode
- Updates immediately via API
- Author Tags - Authors now support tags just like books and series
- Tag authors from their detail page or edit page
- Tags display on AuthorCard with colors and icons
- Filter authors by tag from the authors page
- Improved Tag Visibility - Tags are now more prominent and interactive
- BookCard shows up to 4 tags (up from 2) with colors
- BookRow shows up to 3 tags with colors
- All tags are now clickable links that filter by that tag
- Inline Tag Editor - New component for editing tags directly on detail pages
- Add/remove tags without opening edit mode
- Shows tags with colors and icons
- Used on book detail pages
- Quick Tag Picker - New reusable dropdown component for rapid tagging
- Dynamic Date Filters for Smart Collections - Use "Today" as a relative date
- Create shelves like "Upcoming Books" (release date after today)
- Create shelves like "Recently Released" (release date before today)
- Date rules now have a dropdown to choose between "Today" or a specific date
This is the first stable release of BookShelf V2, a complete rewrite from the ground up with modern technologies and a significantly expanded feature set.
- Full audiobook playback with custom audio player
- Multi-track support (MP3 collections) and single-file M4B audiobooks
- Chapter navigation with automatic chapter detection
- Sleep timer with gradual volume fade
- Bookmarks with notes
- Playback speed control (0.5x - 2x)
- Keyboard shortcuts for hands-free control
- Progress syncing across devices
- Automatic completion tracking (syncs to book status)
- Install BookShelf to your home screen on mobile or desktop
- Offline support via service worker caching
- App-like experience with no browser chrome
- Custom app icons and splash screens
- Quick action shortcuts (Add Book, My Library, Audiobooks)
- Role-based access (admin, member)
- Personal libraries - each user has their own book collection
- Public library for shared books with file requirements
- OIDC/SSO authentication (Authentik, Keycloak, Google, GitHub)
- Invite codes for controlled registration
- Email verification and password reset
- Toggle sections on/off
- Drag-and-drop section reordering
- Smart Collection section (display any Magic Shelf on dashboard)
- Reading goal progress
- Continue Reading, Up Next in Series, Recently Added sections
- EPUB reader with progress persistence
- PDF viewer
- CBZ comic reader
- Touch navigation on mobile
- Metadata extraction from uploaded files
- SvelteKit 2 with Svelte 5
- SQLite with Drizzle ORM
- TypeScript throughout
- Tailwind CSS
- Lucide icons
- PWA support - Install as app, offline caching, home screen shortcuts
- Service worker - Caches static assets for faster loads and offline access
- Optimized app icons - Multiple sizes for all platforms (16px to 512px)
- Web app manifest - Proper PWA configuration with theme colors and shortcuts
- Admin settings for audiobook storage - Configure audiobook storage path and file naming pattern in Settings → Storage
- Dropdown selectors for settings - Converted freeform fields to dropdowns where appropriate (Default Role, Default Sort, Default View, Amazon Domain)
- Mobile audiobook playback - Fixed audio not playing on mobile devices due to browser autoplay restrictions
- Mobile ebook navigation - Fixed ebook reader page navigation not working on mobile devices
- Added touch zones on left/right edges for tap-to-navigate
- Added click handler inside epub iframe for navigation
- Fixed chapter title stuck on "Loading..." - now properly shows chapter name or "Reading..."
- Public Library Toggle - Admins can now disable the public library feature in Settings → General
- When disabled, the "Public Library" sidebar link is hidden
- Library page only shows personal library tab
- Add Book page doesn't allow adding to public library
- Perfect for single-user or family deployments that don't need a shared library
- Consistent media upload buttons - "Upload Ebook" and "Add Audiobook" buttons on book detail page now have consistent styling and both link to the Media tab in edit mode
- Customizable dashboard - Click the gear icon on the dashboard header to:
- Toggle sections on/off (Reading Goal, Continue Reading, Smart Collection, Up Next in Series, Recently Added, Recently Completed)
- Drag and drop to reorder sections
- Add a Smart Collection section that displays books from any Magic Shelf
- Renamed "Read" status to "Done" - To avoid confusion with the "Read" button for reading ebooks, the completed book status is now called "Done" with a circle-check icon. Existing databases are automatically migrated.
- Import reliability - Audible and Goodreads imports now use status keys instead of names for more reliable matching
- Prominent eBook/Audiobook format badges on book cards - Books with eBook or audiobook files now show prominent "Read" and "Listen" buttons directly on book covers for easy one-tap access to content, especially helpful on mobile devices
- Global search button now works - The search magnifying glass icon in the top navigation bar now properly opens the global search modal when clicked
- Search icon in books page is now clickable - The search icon in the books page search bar now acts as a submit button
- Metadata extraction no longer hangs on large audio files (added timeout and optimized settings)
- Duplicate book detection when uploading files - prevents accidentally adding the same book twice
- Email/SMTP Settings in UI - Configure email settings directly from the admin panel
- New "Email" tab in Settings with SMTP configuration (host, port, SSL/TLS, credentials)
- Hybrid configuration: environment variables take precedence over UI settings
- Shows "Configured via Environment Variables" notice when using env vars
- Test email functionality to verify SMTP configuration
- Supports common providers (Gmail, Mailgun, SendGrid, SES, etc.)
- Redesigned Settings Page - New tabbed interface for cleaner navigation
- Tabs: General, Storage, Metadata, OPDS, Import, Users, Email, SSO, AI
- SSO tab links to dedicated OIDC provider management page
- Each tab contains only relevant settings, reducing clutter
- Reorganized Sidebar - Cleaner admin navigation
- Added collapsible "Admin" section for admin users
- Admin section includes: Users, Invite Codes, BookDrop, Diagnostics, Settings
- Removed redundant "System Settings" from bottom of sidebar
- Database migration now properly handles settings table schema changes from V1
- User password migration from V1 databases (passwordHash → password column)
- Amazon metadata provider settings (enable/disable, domain selection)
- Comic Vine metadata provider settings (enable/disable, API key)
- OIDC/SSO settings link on admin settings page
- Cover images and ebooks now properly served in Docker deployments
- Added dynamic file serving routes for
/covers/and/ebooks/ - Fixes issue where runtime-mounted volumes weren't accessible via static paths
- Added dynamic file serving routes for
- V1 to V2 migration now correctly marks existing users as email-verified
- Existing V1 users no longer blocked from login due to missing email verification
- Password reset CLI script for Docker deployments
- Usage:
docker exec -it bookshelf-v2 node scripts/reset-password.js <email> <new-password>
- Usage:
-
OIDC/SSO Authentication - Single Sign-On support via OpenID Connect
- Support for multiple OIDC providers (Authentik, Keycloak, Google, GitHub, etc.)
- Provider presets for quick configuration (Google, GitHub, Authentik, Keycloak)
- Admin UI for provider management at
/admin/settings/oidc - Account linking in user settings - connect/disconnect OIDC providers
- First-time OIDC user flow with option to link existing account or create new
- Local login always available as fallback
- Secure state/nonce handling for CSRF protection
-
Database Migration System
- Automatic pre-migration backups before schema changes
- Upgrade progress page at
/upgradewith real-time status - Safe V1 to V2 database upgrades
- Case-insensitive table name handling
- Multi-user system with roles (admin, member)
- User signup with email verification
- Invite code system for controlled registration
- Admin approval workflow for new users
- Catalog manager for genres, formats, narrators, tags, and statuses
- Improved UI consistency across admin pages
- Enhanced settings organization
- EPUB reader with progress tracking
- PDF reader support
- CBZ comic reader
- Reading progress persistence
- EPUB metadata extraction on upload
- Improved book detail modal
- Enhanced file upload handling
- Initial release with feature parity to V1
- Book management (CRUD, search, filters)
- Author management with Wikipedia import
- Series management with gap tracking
- Reading status tracking
- Reading goals and challenges
- Statistics dashboard
- CSV/JSON import and export
- Audible library import
- OPDS feed support
- Dark mode
- Mobile-responsive design