98 Commits

Author SHA1 Message Date
Admin
db59d55f42 Fix summary overlay scrolling and paragraph formatting on mobile
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- Make overlay scroll within the viewport instead of being clipped (overflow-y-auto on backdrop, items-start alignment)
- Split summary text into paragraphs in the zoom overlay (newline-split with sentence-boundary fallback)
- Add Summary heading in overlay for context
- Remove old merge-poller JS; simplify generateAudio to use data.url directly (Kokoro backend rewrite cleanup)
2026-03-01 23:37:05 +05:00
Admin
13a3eacca6 Use full page navigation for double-tap chapter switching
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-01 23:12:55 +05:00
Admin
398a4703eb Add double-tap left/right navigation on chapter content page
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-01 23:06:49 +05:00
Admin
e4624d0a0c Refactor chapter page: semantic HTML, accessibility improvements, Tailwind hover classes, and book page summary zoom overlay 2026-03-01 23:03:18 +05:00
Admin
5f4b1d96f6 Fix ranking filter to search across all pages using full JSON dataset
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
Embed the complete ranking JSON into the page and replace the DOM-only
filter with a client-side search over ALL_ITEMS. When a filter is active
the grid is re-rendered from the full dataset; clearing filters restores
the server-paginated view. Also adds summary zoom overlay on the book page.
2026-03-01 22:59:03 +05:00
Admin
69582ea5a7 Add cover zoom overlay to rankings page
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-01 22:47:31 +05:00
Admin
33b0ee4771 Add chapter count badges, cover zoom, latest chapter button, and dismiss continue-reading cards
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- Home page book cards show downloaded chapter count (amber badge) via new CountChapters method
- Book page cover image is clickable to zoom into a fullscreen overlay; click anywhere to dismiss
- Book page shows a 'Latest Chapter' button for unstarted books linking to the last downloaded chapter
- Continue-reading cards on home page have a dismiss (×) button that removes progress from localStorage and slides the card out to the left
2026-03-01 22:45:18 +05:00
Admin
05a1cc04c0 Move filter bar below continue-reading section on home page
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-01 22:29:32 +05:00
Admin
f03ff39397 Replace ranking Scrape button with two-click card interaction
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- Remove Scrape form/button and Source text link from non-local ranking cards
- First click on a card highlights it amber and shows 'Click again to scrape' hint
- Second click POSTs to /ui/scrape/book and replaces card with polling status badge
- Pending state auto-cancels after 3 s or when clicking outside
- Source icon (external link SVG) retained but dimmed; stops click propagation
2026-03-01 22:28:47 +05:00
Admin
fb5d22eb8d Move scrape form to dedicated /scrape page, add '+ Add' link in home header
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- Extract scrape form and autocomplete JS from homeTmpl into new scrapeTmpl
- Add handleScrape GET handler serving /scrape with ranking autocomplete
- Register GET /scrape route in server.go
- Replace inline scrape form on home page with '+ Add' flat button in header
- handleHome no longer loads ranking items (only needed on /scrape)
2026-03-01 22:26:50 +05:00
Admin
7397085ecb Fix ranking pagination: sliding ±2 window around current page
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
rankingPageNums now takes a current page parameter and always renders
first 2, last 2, and current±2 — so navigating to page 3 shows
1 2 3 4 5 … 80 81 instead of only the fixed quarter-mark anchors.
2026-03-01 22:22:42 +05:00
Admin
939562ba67 Add facet filtering to ranking page: genre, status, in-library (AND logic)
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- Server collects distinct genres and statuses from all cached items and
  passes them as AllGenres/AllStatuses slices to the template
- Facet chips rendered as pill toggles below the text search bar
- Cards gain data-status, data-genres (pipe-delimited), data-local attributes
- JS filter engine: AND between facets, OR within status facet (a book has
  one status), AND within genre facet (all selected genres must be present)
- Pagination row hidden while any filter is active; restored on clear
- 'Clear filters' button appears when any filter is active
- sortedKeys helper added to produce stable sorted facet chip order
2026-03-01 22:20:05 +05:00
Admin
dcde92d118 Flatten all UI buttons: remove background fills, use text-only styling
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
All filled/pill buttons across home, ranking, book detail, and chapter
pages now use transparent backgrounds with colored text only, consistent
with the chapter reader nav bar style:
- Home: Browse Rankings (amber text), Scrape (amber text)
- Ranking: View Markdown, page numbers, fetch buttons, Scrape/Source on cards
- Book detail: Source, Refresh, Resume, chapter pagination
- Chapter: bottom Prev/Next nav, article-end nav links
2026-03-01 22:15:58 +05:00
Admin
c8c5264f27 Chapter nav: hide Prev/Next when at boundary, remove date from header
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-01 22:08:30 +05:00
Admin
42ed77b7b8 Flatten chapter reader nav buttons: remove background fill from Prev/Next/Listen
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-01 22:07:40 +05:00
Admin
008a89340d Fix ranking card split: replace nested <a> Source link with button in local book cards
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
An <a> element nested inside the card's outer <a> is invalid HTML — browsers
auto-close the outer anchor before the inner one, causing the card to be split
across two grid cells visually. Replace with a <button> that calls window.open()
with event.preventDefault/stopPropagation to avoid interfering with card navigation.
2026-03-01 22:05:53 +05:00
Admin
7e4bb87da0 Fix chapter reader nav bar: use hamburger icon for back-to-book, show chapter date below title
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- Replace bare ← back-to-book link with ☰ (hamburger) icon to eliminate
  the visual double-arrow confusion with the ← Prev chapter button
- Export SplitChapterTitle in writer package and call it in handleChapter
  to split the raw heading into (title, date) — fixes concatenated title+date bug
- Display ChapterDate as a smaller muted line below the chapter title
  in the center nav button
- Bump nav bar height from h-12 to h-14 to accommodate two-line center button
2026-03-01 22:03:47 +05:00
Admin
ca33f8c3cf fix: correct ScrapeRanking DOM selectors for real novelfire.net HTML
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
The previous selectors were based on a hypothetical structure that does not
match the actual site. The real novelfire.net popular listing uses:

  <li class="novel-item">          (not <div>)
    <a href="/book/slug" title="Title">
      <figure class="novel-cover"><img data-src="/path.jpg"></figure>
      <h4 class="novel-title text2row">Title</h4>
    </a>
  </li>

And pagination uses <a rel="next"> (not <a class="next">).

Changes:
- ScrapeRanking: use li.novel-item, h4.novel-title, figure.novel-cover,
  img[data-src]; strip base64 placeholder covers
- hasNextPageLink(): new helper walking all <a> nodes for rel="next"
- Import golang.org/x/net/html for Node.Attr access
- Test fixtures rewritten to match real structure (li/h4/rel=next)
- Status and genres removed from ranking items (not present on listing page)

Verified end-to-end: ranking.json written with 24 items on first fetch
2026-03-01 21:54:11 +05:00
Admin
9837c89075 fix: add server-side pagination to ranking page (?page=N)
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
Previously all cached ranking items were dumped into one page and the
page buttons only triggered refetches from novelfire — not navigation.

- handleRanking now reads ?page=N query param (default 1)
- Items sliced server-side at 20 per page (rankingPageSize constant)
- Template receives DisplayNums/CurrentPage/TotalPages for browse nav
- Display pagination bar renders GET /ranking?page=N HTMX links with
  the active page highlighted in amber; hidden when only 1 page
- Fetch section collapsed into a <details> to reduce visual noise
- FetchNums replaces old PageNums field name in template data
2026-03-01 21:47:39 +05:00
Admin
0aba23de1f feat: switch ranking storage from markdown to JSON, fix round-trip test
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- WriteRanking now writes ranking.json via json.MarshalIndent (replaces markdown table)
- ReadRankingItems uses json.Unmarshal (no fragile pipe-split parsing)
- ReadRanking() (raw string reader) removed; handleRankingView uses ReadRankingItems
- handleRankingView renders a <pre> JSON block instead of goldmark markdown
- RankingItem gains json: struct tags; slug and genres now survive the round-trip exactly
- TestWriteRanking_RoundTrip updated: checks ranking.json, verifies Slug/Genres/SourceURL
- Add RankingPageCacher interface and per-page HTML disk cache support in scraper
2026-03-01 21:44:39 +05:00
Admin
0521ef11ee fix: show source URL in search input on ranking autocomplete selection
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- selectItem() now sets the visible input to source_url (not the title), so the user can see and copy the link before scraping
- Keyboard navigation (ArrowUp/Down) also previews the URL in the input
- Added URL hint line inside each dropdown item showing the full source_url
- Genres included in search haystack (was missing before)
- Deduplicated filter logic into filterRanking() helper
- Raised max results from 8 to 10
2026-03-01 21:40:18 +05:00
Admin
9cf94576d8 feat: ranking page pagination, popular URL, and per-page HTML disk cache
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- Switch ScrapeRanking to novelfire.net/genre-all/sort-popular URL and updated DOM selectors (div.novel-item, h3.novel-title, div.genres)
- Replace 5 hardcoded refresh buttons with dynamic 100-page paginator (smart ellipsis via rankingPageNums)
- Add RankingPageCacher interface and writer methods to cache raw HTML per page under static/books/_ranking_cache/page-N.html
- ScrapeRanking serves from disk cache on hit and writes to cache on miss, skipping Browserless round-trip
- Thread writer as PageCacher through novelfire.New and main.go
- Add TestScrapeRanking_CacheHit and TestScrapeRanking_CacheMiss tests
2026-03-01 21:32:50 +05:00
Admin
73869f01fa Ranking page: fix card wrapping, add filter bar, replace refresh buttons with pagination
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- Cards now use flex layout with break-words/min-w-0 so long titles wrap
  instead of stretching the column; grid uses gap-3 for tighter density
- Added filter bar (title/author/genre/status) with live result count,
  consistent with the home page filter
- Replaced four big refresh buttons with compact pagination buttons
  (p.1, p.1-3, p.1-5, p.1-10, All) labelled with page ranges; source
  link points to novelfire.net/genre-all/sort-popular/status-all/all-novel
- Template data field renamed from RefreshPages to Pages; pagination
  entries updated to reflect 100 novels per page
2026-03-01 21:06:18 +05:00
Admin
26a46a4d31 Add chunked TTS audio generation and ranking search autocomplete on home page
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- Split chapter TTS into up to 10 paragraph-aligned parts; part 0 is
  generated synchronously so playback starts immediately, parts 1-9 and
  the final merge happen in a background goroutine
- New routes: GET /ui/audio/{slug}/{n}/status (merge poll) and
  GET /ui/audio-file/{slug}/{n}/part/{p} (serve individual part)
- JS polls status every 3 s and seamlessly swaps audio.src to the merged
  file once ready, preserving playback position proportionally
- Home page scrape form replaced with a ranking-search autocomplete:
  type a title/author to see matching ranking items (cover + metadata),
  click or keyboard-select to inject the source URL, or paste a raw URL
  directly; ranking data is embedded as JSON at page render time
2026-03-01 21:03:18 +05:00
Admin
81e5d015b4 feat: server-side TTS audio generation, audio queue panel, and home screen fix
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- Add POST /ui/audio/{slug}/{n} endpoint: calls Kokoro-FastAPI server-side,
  writes MP3 atomically to disk, deduplicates concurrent requests via
  in-flight channel map, wraps route with 10-min TimeoutHandler
- Add GET /ui/audio-file/{slug}/{n} endpoint: serves cached MP3 with 1-day
  cache headers
- Add AudioDir/AudioPath helpers to writer.go
- Rewrite JS TTS: remove all MSE/blob/stream code; use plain fetch to
  generate endpoint then set audio.src to returned URL
- Add AbortController to generateAudio; abort on stop() and navigation
- Keep voice/speed controls disabled until setPlaying() fires
- Reset prefetchFired on voice/speed change
- Upgrade prefetch from fire-and-forget to promise chain updating queue badge
- Add sticky bottom audio queue panel: always-visible scrubber with timestamps,
  expandable rows for Now/Next/Dbg with color-coded state badges
- Fix iOS Reader Mode: header->nav aria-hidden, audio outside nav, role=main,
  visible h1 in content area, hover-only paragraph highlight
- Fix home screen Available books hidden: stop hiding cards in #books-grid
  when they appear in Continue Reading; Available always shows all books
2026-03-01 20:44:03 +05:00
Admin
79f5edf80c feat: chapter list drawer in sticky header + remove duplicate title heading
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- Remove the duplicate <h1> that appeared in the content area below the
  sticky bar (title is already shown in the header)
- Replace the static title span with a clickable button (title + ▼ caret)
  that opens a full-width chapter list drawer below the sticky bar
- Drawer is server-rendered with all chapters; current chapter is highlighted
  in amber and scrolled into view on open; clicking any row navigates to it
  and closes the drawer
- Opening the chapter list closes the settings panel and vice versa
- Both panels dismiss on outside click
- Pass AllChapters to the chapter template data struct
2026-03-01 20:18:45 +05:00
Admin
de998d5932 fix: prevent continue-reading card from duplicating chapter label on repeated back-navigation
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
The previous approach cloned the card DOM node and used removeChild to move it,
which meant the source node was gone on re-runs and a stale clone could persist
across history restores. Replace with: clear continueGrid, build a fresh <a>
element from the source card's attributes/innerHTML on every run, and hide
(not remove) the original in #books-grid so it is always available as a clean
source. Also scope the data-slug selector to #books-grid to avoid accidental
matches against the continue-reading cards themselves.
2026-03-01 20:13:04 +05:00
Admin
5b527919f6 feat: sticky chapter reader toolbar with settings menu
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
Replace the separate top nav bar and TTS player bar with a single compact
sticky header that stays visible while scrolling. Navigation (← back, Prev,
Next) and the Listen/Pause button are always accessible. Voice, speed and
auto-next settings are moved into a ⚙ dropdown that opens from the header,
keeping the reading area clean. A thin status strip below the toolbar shows
Buffering/Playing/Error states only when active.
2026-03-01 20:11:39 +05:00
Admin
ffadf7a0c6 fix: prevent book cards duplicating in continue-reading on repeated back-navigation
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
HTMX was snapshotting the post-JS mutated home DOM into history; on back-navigation
it restored the stale snapshot then re-ran the inline script, appending cards that
were already present. Fix by:
- hx-history="false" on the home root div so HTMX never caches the mutated DOM
- clearing #continue-reading-grid before each script run as a defensive guard
2026-03-01 20:09:06 +05:00
Admin
c431fc5869 fix: use semantic nav/header elements to prevent iOS Reader Mode from including chapter navigation links in article content
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-01 20:04:16 +05:00
Admin
1222653858 feat: add source link with icon to book page and ranking cards
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-01 19:51:22 +05:00
Admin
03d7cc6234 feat: replace ranking pages input with Top 100/300/500/All buttons
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-01 19:48:31 +05:00
Admin
26302058d0 fix: ranking refresh deadlock, switch to direct HTTP, add CI pipeline
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
- Fix channel drain goroutine deadlock in handleRankingRefresh: replace
  'for { ... continue ... if nil break }' with 'for A != nil || B != nil'
  so the select never blocks on two nil channels
- Switch ScrapeRanking from urlClient (Browserless) to client (direct HTTP)
  since novelfire.net/ranking is fully server-rendered — no JS needed
- Add ranking unit tests (single page, multi-page, empty page, write round-trip)
- Add .gitea/workflows/ci.yaml: lint, test, build jobs with commented-out
  Docker image push step for when runner has Docker available
2026-03-01 19:45:28 +05:00
Admin
afa457cedd feat: show current chapter in Continue reading cards
Each card in the Continue reading section now displays the saved chapter
number (e.g. 'Chapter 42') in amber below the author line, read from
localStorage.reading_progress.
2026-03-01 18:55:26 +05:00
Admin
07fbfe5555 feat: show in-progress books under 'Continue reading' on home page
Reading progress lives in localStorage so sorting is done client-side.
On page load, JS reads the reading_progress map, moves any matching book
cards into a 'Continue reading' grid above the main grid, and reveals an
'Available' heading for the remainder. Books with no saved progress are
unaffected and no server changes are required.
2026-03-01 17:24:55 +05:00
Admin
e0dc4678b3 feat: replace load-more with page-number pagination and fix progress dot
- Replace 'Load more chapters' append pattern with discrete page-number
  pagination bar (« 1 2 3 … N ») on /books/{slug}
- Clicking a page number swaps #chapter-list via HTMX (innerHTML replace)
  and updates the OOB #chapter-pagination bar; URL is pushed via hx-push-url
- applyProgress() is called after each swap to re-highlight saved chapter
- Fix empty bullet bug: progress-dot span no longer contains the '●'
  character; replaced with a small amber circle via Tailwind (w-2 h-2
  rounded-full bg-amber-400) so hidden spans are truly space-free
- Add template FuncMap (pages/prev/next helpers) to both handleBook and
  handleBookChaptersPage; remove HasMore/NextPage from template data structs
2026-03-01 17:22:42 +05:00
Admin
1469e49190 feat: paginated ranking scrape with lazy page fetching
- ScrapeRanking now accepts a maxPages int parameter (0 = all pages).
  Each page is fetched strictly sequentially; the next page is only
  requested after every entry from the current page has been sent,
  so there is no pre-fetching or look-ahead.
  Pagination stops automatically when no next-page link is present
  or when the rank-novels container is absent/empty.

- The ranking URL pattern follows the existing catalogue convention:
  /ranking?page=N (next-page link detection as the stop condition).

- Server: handleRankingRefresh reads an optional 'pages' form field
  and passes it to ScrapeRanking. Timeout scales at 90 s/page.

- UI: Refresh Rankings button is now a small form with a numeric
  'Pages' input (default 1), letting the user choose how many pages
  to pull in one refresh without touching the server config.
2026-03-01 16:54:52 +05:00
Admin
e9f880f7f7 fix: make ranking refresh async and use JS-rendered client for ScrapeRanking
Two bugs caused the 'Refresh Rankings' button to silently fail in production:

1. ScrapeRanking was using the plain HTTP client (s.client) instead of the
   browserless content client (s.urlClient). The /ranking page requires
   JavaScript rendering, so a plain fetch returned HTML without any novel
   entries. Now uses s.urlClient so the page is fully rendered before scraping.

2. handleRankingRefresh was synchronous, holding the HTTP connection open for
   up to 60 s while scraping. Reverse proxies and HTMX timeouts closed the
   connection before the scrape finished. Rewritten to the same async pattern
   used for book scraping: POST /ranking/refresh returns immediately with a
   polling badge; the browser polls GET /ui/ranking/status every 3 s; when
   the goroutine finishes the status endpoint sends HX-Redirect to /ranking.
2026-03-01 16:52:03 +05:00
Admin
bcdef02997 feat: paginate chapter list and track reading progress in localStorage
Chapter list:
- Book page now shows the first 50 chapters only; a 'Load more' button
  (HTMX, GET /books/{slug}/chapters-page?page=N) appends the next page
  without a full navigation, replacing itself with the next load-more
  button or disappearing when all chapters are loaded.

Reading progress:
- Visiting a chapter saves {slug: chapterN} to localStorage under
  'reading_progress'.
- The book page reads that key on load and, if a saved chapter exists,
  highlights the saved chapter row with an amber dot and shows a
  'Resume — Chapter N' button that navigates directly to it.
- Progress dots are also re-applied after each Load More via
  hx-on::after-request.
2026-03-01 16:39:26 +05:00
Admin
286c30696f fix: fall back to full blob download on iOS where MSE is unsupported
iOS Safari does not reliably support MediaSource for audio/mpeg streaming,
causing an 'audio decode error' when the MSE SourceBuffer path is used.

Detect iOS (and any browser without audio/mpeg MSE support) at runtime and
fall back to a single fetch(...).blob() download with stream:false. Playback
begins after the full chapter audio is received rather than mid-stream, but
it works on all devices. Desktop browsers keep the existing MSE streaming
path (stream:true) for faster time-to-first-audio.

The same detection applies to the next-chapter prefetch pipeline.
2026-03-01 15:41:23 +05:00
Admin
a4def535d8 feat: persist TTS speed, voice, and auto-next in localStorage
Settings are loaded on page init and saved on every change so they carry
over across chapter navigation and page reloads.
2026-03-01 15:39:18 +05:00
Admin
46f49f47ac chore: replace host-path bind mount with named volume for static books
Scraped content is now stored in the 'static_books' Docker named volume
instead of a host bind mount, removing the dependency on STATIC_ROOT and
the need to pre-create ./static/books on the host.
2026-03-01 15:11:22 +05:00
Admin
79a2a942fe chore: ignore scraper/bin/ build output 2026-03-01 14:58:07 +05:00
Admin
178cb5a3d6 fix: use container-internal port 3000 for browserless inter-container and healthcheck URLs
The 3030:3000 port mapping only exposes port 3030 on the host. Container-to-container
traffic (scraper → browserless) and the healthcheck (which runs inside the browserless
container) must use the container's own port 3000. Only the host-side default in
main.go and the Dockerfile ENV remain on 3030.
2026-03-01 14:56:51 +05:00
Admin
e7b915c6aa chore: update Browserless port references from 3000 to 3030
Update all default URLs, port mappings, healthcheck endpoints, Dockerfile
ENV defaults, and integration test run instructions to use port 3030.
2026-03-01 14:51:28 +05:00
Admin
7879a51fe3 feat: add Kokoro TTS, ranking page, direct HTTP strategy, and chapter-number fix
- Add Kokoro-FastAPI TTS integration to the chapter reader UI:
  - Browser-side MSE streaming with paragraph-level click-to-start
  - Voice selector, speed slider, auto-next with prefetch of the next chapter
  - New GET /ui/chapter-text endpoint that strips Markdown and serves plain text

- Add ranking page (novelfire /ranking scraper, WriteRanking/ReadRankingItems
  in writer, GET /ranking + POST /ranking/refresh + GET /ranking/view routes)
  with local-library annotation and one-click scrape buttons

- Add StrategyDirect (plain HTTP client) as a new browser strategy; the
  default strategy is now 'direct' for chapter fetching and 'content'
  for chapter-list URL retrieval (split via BROWSERLESS_URL_STRATEGY)

- Fix chapter numbering bug: numbers are now derived from the URL path
  (/chapter-N) rather than list position, correcting newest-first ordering

- Add 'refresh <slug>' CLI sub-command to re-scrape a book from its saved
  source_url without knowing the original URL

- Extend NovelScraper interface with RankingProvider (ScrapeRanking)

- Tune scraper timeouts: wait-for-selector reduced to 5 s, GotoOptions
  timeout set to 60 s, content/scrape client defaults raised to 90 s

- Add cover extraction fix (figure.cover > img rather than bare img.cover)

- Add AGENTS.md and .aiignore for AI tooling context

- Add integration tests for browser client and novelfire scraper (build
  tag: integration) and unit tests for chapterNumberFromURL and pagination
2026-03-01 12:25:16 +05:00
Admin
e6e6f7dc4d feat: add exponential backoff, some UI elements to see the resut of a scrape 2026-02-26 18:51:32 +05:00
Admin
d68ea71239 feat: initial commit 2026-02-26 12:56:25 +05:00