A self-hostable web service for sending ebooks to a Kobo, Kindle, or Tolino through its built-in browser — no account, no cloud, no cables.
Live at bookdrop.cc · Forked from send2ereader by djazz
- Open the site in your ereader's browser — it shows a 4-character key and a QR code.
- Scan the QR code with your phone to open the upload page with the key pre-filled, or enter the key manually on any computer.
- Pick one or more files and click Upload and send.
- Download links appear on the ereader within seconds.
Supported formats: EPUB, MOBI, PDF, CBZ, CBR, HTML, TXT.
Optional conversions (requires external tools — see below):
- EPUB → KEPUB (Kobo, via kepubify) — better typography and font control
- EPUB → MOBI (Kindle, via KindleGen) — Kindle doesn't support EPUB natively
- PDF margin cropping (via pdfCropMargins) — fills more of the small screen
- Update EPUB metadata from Google Books — patches title, author, publisher, etc. and shows a before/after diff on the download page (requires a
GOOGLE_BOOKS_API_KEY)
- Node.js 22 or later
- pnpm (
npm install -g pnpmor via corepack) - (Optional) kepubify in
PATH - (Optional) KindleGen in
PATH - (Optional) pdfCropMargins (
pip install pdfCropMargins)
pnpm install
pnpm dev # watches SCSS and TypeScript; starts Express on :3001pnpm build # compiles SCSS to client/public/ and TypeScript to dist/
pnpm start # runs dist/server.jspnpm test
pnpm typecheck
pnpm lintUses Node.js's built-in test runner (node:test) — no extra test framework needed.
Copy .env.example to .env to customise these values.
| Variable | Default | Description |
|---|---|---|
NODE_ENV |
(unset) | Set to test to disable HSTS and upgrade-insecure-requests (e.g. for local HTTP dev) |
PORT |
3001 |
HTTP port the server listens on |
UPLOAD_DIR |
uploads |
Directory for temporary file storage |
EXPIRE_DELAY_MS |
300000 |
Inactivity timeout per key (ms) |
MAX_EXPIRE_MS |
3600000 |
Hard maximum key lifetime (ms) |
MAX_FILE_SIZE |
838860800 |
Upload size limit in bytes (800 MB) |
MAX_DISK_BYTES |
1073741824 |
Total upload directory size cap in bytes (1 GB); uploads returning 507 when exceeded |
MAX_FILES_PER_KEY |
5 |
Max files staged per session key; further uploads return 400 |
MAX_URLS_PER_KEY |
20 |
Max URLs staged per session key; further submissions return 400 |
MAX_KEYS_PER_IP |
3 |
Max concurrent sessions per IP; further requests return 429 |
RATE_LIMIT_WINDOW_MS |
900000 |
Rate-limit window for /generate (ms) |
RATE_LIMIT_MAX |
20 |
Max key generations per window per IP |
LOG_LEVEL |
info |
Pino log level (trace, debug, info, warn, error) |
GOOGLE_BOOKS_API_KEY |
(unset) | Google Books API key for EPUB metadata enrichment; without it the API may rate-limit requests |
docker compose build
docker compose up -dThe service will be available at http://localhost:3001.