A vibe coded frontend and server for sending news articles to an e-reader.
Hetzner (and most VPS providers) block outbound 465 by default as anti-spam policy. Port 587 with STARTTLS is open and supported by Resend (and any standard SMTP service). The transporter code already flips `secure: false` automatically when port != 465, so no code change is needed — just the default. |
||
|---|---|---|
| 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.