Some checks failed
CI / v3 / Check ui (pull_request) Failing after 15s
CI / v3 / Test backend (pull_request) Failing after 16s
CI / v3 / Docker / backend (pull_request) Has been skipped
CI / v3 / Docker / runner (pull_request) Has been skipped
CI / v3 / Docker / ui (pull_request) Has been skipped
- Remove all pre-v3 code: scraper, ui-v2, backend v1, ios v1+v2, legacy CI workflows - Flatten v3/ contents to repo root - Add Doppler secrets management (project=libnovel, config=prd) - Add justfile with doppler run wrappers for all docker compose commands - Strip hardcoded env fallbacks from docker-compose.yml - Add minimal README.md - Clean up .gitignore
5.0 KiB
5.0 KiB
API Endpoint Reference
Routing ownership map: see
docs/d2/api-routing.svg(source:docs/d2/api-routing.d2) for a visual overview of which paths Caddy sends to the backend directly vs. through SvelteKit, with auth levels colour-coded.
All traffic enters through Caddy :443. Caddy routes a subset of paths directly to the Go backend (bypassing SvelteKit); everything else goes to SvelteKit, which enforces auth before proxying onward.
Health / Version
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/health |
— | Liveness probe. Returns {"ok":true}. |
GET |
/api/version |
— | Build version + commit hash. |
Scrape Jobs (admin)
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/scrape |
admin | Enqueue full catalogue scrape. |
POST |
/scrape/book |
admin | Enqueue single-book scrape {url}. |
POST |
/scrape/book/range |
admin | Enqueue range scrape {url, from, to?}. |
GET |
/api/scrape/status |
admin | Current job status. |
GET |
/api/scrape/tasks |
admin | All scrape task records. |
POST |
/api/cancel-task/{id} |
admin | Cancel a pending task. |
Browse / Catalogue
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/browse |
— | Live novelfire.net browse (MinIO page-1 cache). Legacy — used by save-browse subcommand. |
GET |
/api/catalogue |
— | Primary browse endpoint. Meilisearch-backed, paginated. Params: q, page, limit, genre, status, sort (popular|new|update|rank|top-rated). Falls back to empty when Meilisearch is not configured. |
GET |
/api/search |
— | Full-text search: Meilisearch local results merged with live novelfire.net remote results. Param: q (≥ 2 chars). Used by iOS app. |
GET |
/api/ranking |
— | Top-ranked novels from PocketBase. |
GET |
/api/cover/{domain}/{slug} |
— | Proxy cover image from MinIO (redirect to presigned URL). |
Book / Chapter Content
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/book-preview/{slug} |
— | Returns stored metadata + chapter list, or enqueues a scrape task (202) if unknown. |
GET |
/api/chapter-text/{slug}/{n} |
— | Chapter content as plain text (markdown stripped). |
GET |
/api/chapter-markdown/{slug}/{n} |
— | Chapter content as raw markdown from MinIO. |
POST |
/api/reindex/{slug} |
admin | Rebuild chapters_idx from MinIO objects. |
Audio
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/api/audio/{slug}/{n} |
— | Trigger Kokoro TTS generation. Body: {voice?}. Returns 200 {status:"done"} if cached, 202 {task_id, status} if enqueued. |
GET |
/api/audio/status/{slug}/{n} |
— | Poll audio generation status. Param: voice. Returns {status, task_id?, error?}. |
GET |
/api/audio-proxy/{slug}/{n} |
— | Redirect to presigned MinIO audio URL. |
GET |
/api/voices |
— | List available Kokoro voices. Returns {voices:[]} on error. |
Presigned URLs
All presign endpoints return a 302 redirect to a short-lived MinIO presigned
URL. The URL is cached in Valkey (TTL ~55 min) to avoid regenerating on every
request.
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/presign/chapter/{slug}/{n} |
— | Presigned URL for chapter markdown object. |
GET |
/api/presign/audio/{slug}/{n} |
— | Presigned URL for audio MP3. Param: voice. |
GET |
/api/presign/voice-sample/{voice} |
— | Presigned URL for voice sample MP3. |
GET |
/api/presign/avatar-upload/{userId} |
user | Presigned PUT URL for avatar upload. |
GET |
/api/presign/avatar/{userId} |
— | Presigned GET URL for avatar image. |
Reading Progress
Session-scoped (anonymous via cookie session ID, or tied to authenticated user).
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/progress |
— | Get all reading progress for the current session/user. |
POST |
/api/progress/{slug} |
— | Set progress. Body: {chapter}. |
DELETE |
/api/progress/{slug} |
— | Delete progress for a book. |
Notes
- Auth: The backend does not enforce auth itself — the SvelteKit UI layer enforces admin/user guards before proxying requests. The backend trusts all incoming requests.
/api/cataloguevs/api/browse:/api/catalogueis the primary UI endpoint (Meilisearch, always-local, fast)./api/browsehits or caches the live novelfire.net browse page and is only used internally by thesave-browsesubcommand.- Meilisearch fallback: When
MEILI_URLis unset,/api/cataloguereturns{books:[], has_next:false}and/api/searchfalls back to a PocketBase substring scan. BACKEND_API_URL: The SvelteKit UI reads this env var (defaulthttp://localhost:8080) to reach the backend server-side. In docker-compose it is set tohttp://backend:8080.