Use Gemini-generated dark artwork as splash source instead of stretched logo.
Add missing media queries for iPad Mini 6, iPad Pro M4 11"/13", iPhone 16 Pro/Pro Max.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only render <img> when blob URL is available from prefetch, preventing
broken image icons from src={undefined} or failed direct URL fallbacks.
Reset error state when blob URL arrives to recover from transient failures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fetch metadata from GET /libraries/{id}/series/{name}/metadata and display
authors with icon and description in the series header.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use the API's sort parameter to explicitly request most recently added
items. Simplify latest series fetch by using /series?sort=latest instead
of N+1 calls per library.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the 16px font-size rule outside @layer base and scope it to iOS
via @supports (-webkit-touch-callout: none) so it takes priority over
Tailwind utility classes without affecting desktop rendering.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Temporarily inject maximum-scale=1 into viewport meta tag on orientation
change to cancel the automatic zoom iOS Safari applies, then restore
it to keep pinch-zoom available.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After pinch-zoom then de-zoom, visualViewport.scale may not return
exactly to 1.0, blocking swipe navigation. Use 1.05 threshold instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Arrow buttons now swap next/previous in RTL mode. Swipe navigation
receives isRTL from parent state instead of creating its own independent
copy, so toggling direction takes effect immediately without reload.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Return null for readProgress when Stripstream book status is "unread"
with no current page, aligning behavior with Komga provider.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
bookCount and booksReadCount were hardcoded to 0, causing all series
covers to appear completed (opacity-50). Now queries the series endpoint
to get actual counts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Uses /books/ongoing as single source for Stripstream, displayed with
featured header style. Removes separate "up next" section.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces manual ongoing series derivation (fetching 200 series per library)
with the new API endpoints, reducing API calls and improving accuracy.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Displays a carousel of favorite series after the ongoing sections.
Hidden when the user has no favorites.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Stripstream provider was showing all books and first library's series
instead of using reading status filters. Now ongoingBooks uses
reading_status=reading, ongoing series are derived from books being read,
and latest series are fetched from all libraries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stream image responses directly to the client instead of buffering the
entire image in memory, reducing perceived latency. Increase image fetch
timeout from 15s to 60s to avoid AbortError on slow page loads.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix POST requests (series/list, books/list) not being cached by Next.js fetch cache
by wrapping them with unstable_cache in the private fetch method
- Wrap getHomeData() entirely with unstable_cache so all 5 home requests are cached
as a single unit, reducing cold-start cost from 5 parallel calls to 0 on cache hit
- Remove N+1 book count enrichment from getLibraries() (8 extra calls per cold start)
as LibraryDto does not return booksCount and the value was only used in BackgroundSettings
- Simplify getLibraryById() to reuse cached getLibraries() data instead of making
separate HTTP calls (saves 2 calls per library page load)
- Fix cache debug logs: replace misleading x-nextjs-cache header check (always UNKNOWN
on external APIs) with pre-request logs showing the configured cache strategy
- Remove book count display from BackgroundSettings as it is no longer fetched
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add `output: standalone` to next.config.js for faster cold start
- Rebuild runner stage around standalone bundle (node server.js instead of pnpm start)
- Replace prisma db push with prisma migrate deploy (proper migration workflow)
- Remove npx/pnpm at runtime, use direct binary paths
- Add HOSTNAME=0.0.0.0 for standalone server to listen on all interfaces
- Fix next.config.js not copied in builder stage
- Update README: pnpm instead of yarn, correct ports, full env vars documentation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Introduced a new resolver function to streamline fetching Stripstream configuration from the database or environment variables.
- Updated various components and API routes to utilize the new configuration resolver, improving code maintainability and reducing direct database calls.
- Added optional environment variables for Stripstream URL and token in the .env.example file.
- Refactored image loading logic in the reader components to improve performance and error handling.
- Introduce provider abstraction layer (IMediaProvider, KomgaProvider, StripstreamProvider)
- Add Stripstream Librarian as second media provider with full feature parity
- Migrate all pages and components from direct Komga services to provider factory
- Remove dead service code (BaseApiService, HomeService, LibraryService, SearchService, TestService)
- Fix library/series page-based pagination for both providers (Komga 0-indexed, Stripstream 1-indexed)
- Fix unread filter and search on library page for both providers
- Fix read progress display for Stripstream (reading_status mapping)
- Fix series read status (books_read_count) for Stripstream
- Add global search with series results for Stripstream (series_hits from Meilisearch)
- Fix thumbnail proxy to return 404 gracefully instead of JSON on upstream error
- Replace duration-based cache debug detection with x-nextjs-cache header
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Show a clean placeholder (icon + label) instead of the browser's broken image icon when a page fails to load
- Track error state per page (page 1 and page 2) and reset on page navigation
- Center each page within its half in double page mode instead of pushing toward the spine
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add revalidateForRefresh(scope, id) server action for home/library/series
- Library/Series wrappers: revalidate cache then router.refresh(), 400ms delay for animation
- Home: revalidate home-data + path before refresh
- RefreshButton uses refreshLibrary from RefreshContext when not passed as prop
- Library/Series pages pass id to wrapper for context and pull-to-refresh
- read-progress: pass 'max' to revalidateTag for Next 16 types
Made-with: Cursor
- Add LIBRARY_SERIES_CACHE_TAG to getLibrarySeries fetch
- Revalidate library-series tag in updateReadProgress and deleteReadProgress
- Add eslint ignores for temp/, .next/, node_modules/
Made-with: Cursor
Refine the global loading experience to feel smoother and less flashy while keeping brand accents. Simplify the home continue-reading highlight by styling the section header instead of using a heavy card wrapper.