mirror of
https://github.com/sakaljurgis/kob.git
synced 2026-07-08 22:17:41 +00:00
6.8 KiB
6.8 KiB
kob — article-to-EPUB for e-reader
A tiny self-hosted web app: paste an article URL → it's fetched via Jina Reader, packaged as EPUB, and listed for download. Designed to be browsed from an e-reader: HTML-only, no JS, big fonts, full-width, paginated (no scrolling).
Decisions (locked)
- Stack: Python + Flask,
ebooklibfor EPUB,requestsfor HTTP,markdownfor md→html. - Hosting: home server, Docker. README explains env vars and volumes.
- Fetcher:
https://r.jina.ai/<url>. OptionalJINA_API_KEYenv var, sent asAuthorization: Bearer ...if set. - Articles per page: configurable via
ARTICLES_PER_PAGE, default 8. - Delete: button per article → confirmation page (no JS) → POST to actually delete.
- Storage: filesystem +
index.json. Keep source URL and original markdown alongside the EPUB. - Title: taken from Jina response, used as EPUB title and slug for filename.
- No auth: single user on home network. Document in README that this should not be exposed publicly without putting a reverse proxy + auth in front.
Storage layout
Mount one volume at /data:
/data/
index.json # ordered list, newest first
articles/
<id>/ # id = timestamp + slug, e.g. 20260428-153012-how-to-x
article.epub
source.md # original markdown from Jina
meta.json # { id, url, title, fetched_at }
index.json is the source of truth for ordering and listing. Format:
{
"articles": [
{ "id": "20260428-153012-how-to-x", "title": "How to X", "url": "https://...", "fetched_at": "2026-04-28T15:30:12Z" }
]
}
On delete: remove from index.json first, then rm -rf the article folder. (Order matters: if rm fails, the index is still consistent — orphan folders are harmless and can be GC'd later if ever needed.)
Routes
| Method | Path | Purpose |
|---|---|---|
| GET | / |
Main page: URL input + paginated list (?page=N). |
| POST | /add |
Fetch URL → build EPUB → save → redirect to /. |
| GET | /download/<id> |
Stream the .epub file. |
| GET | /delete/<id>?page=N |
Confirmation page ("Delete ' |