Writing in Markdown, keeping a subscriber list, confirming addresses and sending an issue to a few hundred people is a short build; an agent does it in an evening on top of Amazon SES, Postmark or Resend. The weekend goes on what makes email arrive and stay legal: double opt-in, unsubscribe, bounce and complaint handling, authentication records on your domain, and a sender that lets you send. Paid subscriptions, automations and imports from other platforms are further weekends.
Before you buildButtondown is free up to 100 subscribers, so under that size there is nothing to replace. Self-hosting listmonk or Keila may beat a build for larger lists.
Build me a small newsletter tool to replace Buttondown for a list under 1,000 subscribers. Requirements: - Python 3.12: FastAPI with Jinja2 templates, run with `uvicorn app:app` on http://127.0.0.1:4890. Public pages are /subscribe, /confirm/<token>, /unsubscribe/<token> and /archive; the admin lives under /admin behind one password in .env. - Storage: SQLite through SQLModel in ./data/news.db for subscribers (email, status, confirmed_at, tags), issues (slug, subject, markdown, status, sent_at), deliveries (issue, subscriber, SES message id, status) and a suppression list. - Writing: a split-pane Markdown editor in /admin with a live preview. Render with `markdown-it-py` (tables, footnotes), inline the CSS with `premailer`, make a plain-text alternative, and send a test issue to my own address before any real send. - Signup: double opt-in. The form sends a confirmation link valid for 3 days and only confirmed addresses receive issues; rate-limit the form per IP and add a honeypot field. - Sending: Amazon SES through `boto3`, with AWS keys and SES_FROM in .env, at most 14 messages a second, `List-Unsubscribe` and `List-Unsubscribe-Post` headers and one unsubscribe link per recipient. A crash mid-send must never email anyone twice (unique key on issue and subscriber) and the job resumes where it stopped. - Bounces and complaints: an endpoint at /ses/events that verifies the SNS signature, confirms the subscription itself, and suppresses hard bounces and complaints. - Archive: published issues render at /archive/<slug>, with an Atom feed at /archive/feed.xml. - Import and export: CSV in (email, tags, optional confirmed date); CSV out of subscribers, and issues out as Markdown files with front matter. - Single author. No reader accounts, no tracking pixels or link rewriting, no telemetry; the only outbound traffic is to AWS. - Out of scope: paid subscriptions, automations, segments beyond tags, open and click analytics. - README: SES setup (verify the domain, add DKIM, request production access: AWS reviews it, so do not expect to send the same day), the SNS topic and HTTPS endpoint, and the footer rules that CAN-SPAM and GDPR expect (a postal address and a working unsubscribe link).
Opens your agent with the prompt filled in, you press enter. Or copy it and paste it into an empty folder.
The first prompt builds the core. Run these one at a time in the same folder to grow it into your own Buttondown.
Add an importer to the newsletter tool in this folder. Requirements: - A command `news import --from substack|kit|csv <file>` that reads the platform's subscriber export (email, subscribed date, status) and maps it to subscribers. - Import only addresses that were active and confirmed on the old platform; skip unsubscribed, bounced and complained addresses and put them on the suppression list. - Print counts of imported, skipped and duplicate rows before writing; support `--dry-run`. - Keep the original subscription date as confirmed_at. - Update the README.
Add a link digest draft to the newsletter tool in this folder. Requirements: - A /admin page with a box where I paste URLs, one per line, each with an optional note. - A command that fetches each page title and meta description (10-second timeout, no JavaScript) and builds a Markdown draft: a heading per link, my note, the description. - The draft opens in the normal editor; nothing is sent automatically. - Update the README.
Add a sponsor block to the newsletter tool in this folder. Requirements:
- A sponsor table (name, text, URL, start and end date, impressions sent).
- A Markdown shortcode `{{sponsor}}` that inserts the active sponsor's text and link, marked
"Sponsored", at render time; if none is active, render nothing.
- Count how many emails each sponsor was in, and show it on a /admin page that exports CSV.
- No link rewriting or click tracking.
- Update the README.A newsletter list is the asset, and writers want it to send reliably without becoming email engineers. Buttondown charges mostly by active subscribers, lets you pick add-ons, and says it is profitable and self-funded. For a few hundred readers, $9 a month is cheap insurance against a bad deliverability week.
Estimate · SES charges per message sent, which is cents at this size; a small VPS adds about $5. The build is token usage on your agent plan.
| Plan | Monthly | Annual, per month | What you get |
|---|---|---|---|
| Free (up to 100) | $0 | $0 | Up to 100 subscribers; Markdown or rich-text editor, sending from a custom domain, hosted archives. |
| Up to 1,000 subscribers | $9 | $7.50 | Same base features, priced for up to 1,000 active subscribers. |
| Up to 5,000 subscribers | $29 | $24.17 | Priced for up to 5,000 active subscribers. |
| Up to 10,000 subscribers | $79 | $65.83 | Priced for up to 10,000 active subscribers. |
| Up to 20,000 subscribers | $139 | $115.83 | Priced for up to 20,000 active subscribers. |
Free for your first 100 subscribers, with a rich-text or Markdown editor, a custom sending domain and hosted archives.
Kinda. The core is a weekend build with the prompt on this page, but real gaps remain: Paid subscriptions through Stripe, Automations, tagging and segmentation, and multiple newsletters under one account.
About $9 a month on the Up to 1,000 subscribers plan, $108 a year (checked 2026-10-19).
Paid subscriptions through Stripe; Automations, tagging and segmentation, and multiple newsletters under one account; Open and click analytics, comments and surveys, sponsorships; Free migration help and import guides for other platforms; An API with a CLI, webhooks and integrations kept up by someone else. If any of those matter to you, keep paying.
Yes: listmonk (open source), Ghost (open source), Keila (open source).