import express from "express"; import React from "react"; import fs from "fs"; import ReactDOMServer from "react-dom/server"; import { Builder } from "xml2js"; import cryptoRandomString from "crypto-random-string"; export const webServer = express() .use(express.static("static")) .use(express.urlencoded({ extended: true })) .get("/", (req, res) => res.send( renderHtml(
) ) ) .post("/", (req, res) => { const inbox: Inbox = { name: req.body.name, token: newToken() }; fs.writeFileSync(feedPath(inbox.token), renderXml(Feed(inbox))); res.send( renderHtml( ) ); }) .listen(8443); type Inbox = { name: string; token: string; }; function Layout({ children }: { children: React.ReactNode }) { return ( Kill the Newsletter!

Kill the Newsletter!

Convert email newsletters into Atom feeds

Convert email newsletters into Atom feeds

{children}
); } function Form() { return (

); } function Created({ inbox: { name, token } }: { inbox: Inbox }) { return ( <>

“{name}” Inbox Created

Sign up for the newsletter with
{feedEmail(token)}

Subscribe to the Atom feed at
{feedUrl(token)}

Don’t share these addresses.
They contain a security token that other people could use
to send you spam and to control your newsletter subscriptions.

Enjoy your readings!

Create Another Inbox

); } // https://validator.w3.org/feed/docs/atom.html // https://validator.w3.org/feed/#validate_by_input function Feed(inbox: Inbox) { const { name, token } = inbox; return { feed: { $: { xmlns: "http://www.w3.org/2005/Atom" }, link: [ { $: { rel: "self", type: "application/atom+xml", href: feedUrl(token) } }, { $: { rel: "alternate", type: "text/html", href: "https://www.kill-the-newsletter.com/" } } ], id: id(token), title: name, subtitle: `Kill the Newsletter! Inbox “${feedEmail(token)}”`, updated: now(), ...Entry({ title: `“${name}” Inbox Created`, author: "Kill the Newsletter!", content: ReactDOMServer.renderToStaticMarkup( ) }) } }; } function Entry({ title, author, content }: { title: string; author: string; content: string; }) { return { entry: { id: id(newToken()), title, author: { name: author }, updated: now(), content: { $: { type: "html" }, _: content } } }; } function newToken() { return cryptoRandomString({ length: 20, characters: "1234567890qwertyuiopasdfghjklzxcvbnm" }); } function now() { return new Date().toISOString(); } export function feedPath(token: string) { return `static/feeds/${token}.xml`; } function feedUrl(token: string) { return `https://www.kill-the-newsletter.com/feeds/${token}.xml`; } function feedEmail(token: string) { return `${token}@kill-the-newsletter.com`; } function id(token: string) { return `urn:kill-the-newsletter:${token}`; } function renderHtml(component: React.ReactElement): string { return `\n${ReactDOMServer.renderToStaticMarkup(component)}`; } function renderXml(xml: object): string { return new Builder().buildObject(xml); }