A vibe coded frontend and server for sending news articles to an e-reader.
Prevents abuse before exposing the app publicly. Limits each client IP to 20 article sends per hour. trust proxy is set so the real client IP is used (not Nginx's loopback) once the app is behind a reverse proxy. |
||
|---|---|---|
| public | ||
| src | ||
| .env.example | ||
| .gitignore | ||
| .prettierrc.json | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
Send to E-Reader
Convert web articles to EPUB and email them straight to your e-reader. Works with any device that accepts emailed files — Kindle, PocketBook, or anything else with a similar service.
Built with Express 5 + TypeScript. Hosted at read.atanasov.fi.
How it works
- You paste an article URL and your e-reader's email address.
- The server fetches the page, runs Mozilla Readability over it to strip ads/chrome, builds an EPUB, and emails it to the address you gave.
- The EPUB is deleted from the server immediately after sending.
Supported devices
Any device that accepts files via email works — the app doesn't restrict by domain.
| Device | Email pattern |
|---|---|
| Amazon Kindle | *@kindle.com |
| PocketBook | *@pbsync.com |
| Anything else | whatever address your device gives you |
You'll need to add the sender address (the Gmail account this app sends from) to your device's approved-senders list — that's a one-time per-device setup.
Prerequisites
- Node.js 20 or newer
- An SMTP-capable email provider. Defaults are set up for Resend — sign up (no waitlist), verify your domain, grab an API key.
Local development
git clone <your-fork>
cd send_to_kindle
npm install
cp .env.example .env # then fill in GMAIL_USER and GMAIL_APP_PASSWORD
npm run dev
Server listens on http://localhost:3000 (override with PORT).
Production build
npm run build
npm run start
Environment variables
| Variable | Required | Default | Notes |
|---|---|---|---|
SMTP_HOST |
no | smtp.resend.com |
Any SMTP server works |
SMTP_PORT |
no | 465 |
465 = SSL, 587 = STARTTLS |
SMTP_USER |
yes | — | For Resend, literally the string resend |
SMTP_PASSWORD |
yes | — | For Resend, your API key (re_…) |
MAIL_FROM |
yes | — | Sender address, e.g. read@atanasov.fi. Must be from a verified domain on your provider. |
PORT |
no | 3000 |
Listen port |
Resend setup (quick)
- Sign up at resend.com.
- Add your domain (e.g.
atanasov.fi) and add the SPF/DKIM/return-path DNS records they generate. Verification usually completes in a few minutes. - Create an API key.
- In
.env:SMTP_USER=resend SMTP_PASSWORD=re_xxxxxxxxxxxxxxxxxx MAIL_FROM=send@read.atanasov.fi
For a different provider, just point SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASSWORD at it — any standard SMTP service works.
API
POST /send-article
{
"url": "https://example.com/article",
"readerEmail": "your-device@kindle.com"
}
Response on success:
{
"success": true,
"message": "Article sent to your e-reader",
"title": "Article Title"
}
Limitations
- Articles must be publicly accessible — no paywalled or login-required pages.
- Server-side fetch means JS-heavy SPAs may extract poorly (the page must render meaningful HTML without JavaScript).
- Some sites block non-browser user-agents; the app sends a Chrome UA but can still be refused.
Stack
- Express 5 — HTTP server
- @mozilla/readability — article extraction
- jsdom — DOM for Readability
- @lesjoursfr/html-to-epub — EPUB generation
- nodemailer — SMTP via Gmail
License
GPL-3.0-only. See LICENSE.