Back to Blog

Adding a newsletter to my site for zero dollars

Aleks Popović

There is a new card at the bottom of this post that asks for your email address. This is everything I had to set up to make it work.

Why bother with a newsletter in 2026

A few weeks ago I moved this site to a new domain and spent days making sure Google and my RSS subscribers would follow me there. That project left me thinking about who actually gets notified when I publish something. The honest answer was whoever the LinkedIn algorithm decides to show it to (because I usually link my latest posts there), plus a handful of RSS subscribers I can't see or count.

Email doesn't have that problem. There is no ranking algorithm and no platform deciding my post isn't engaging enough that day. If you give me your address, you get the post, and that's the entire arrangement.

I also know myself, and I have a history of starting publishing schedules I can't hold. My YouTube channel has two multi-year gaps that both started right after my most productive months. So I decided before writing any code that this would be a notification list rather than a proper newsletter with issues and a schedule. When I publish something you get it, and when I go quiet for two months nothing is broken and nobody gets a "sorry for the silence" email.

Letting the RSS feed do the work

My original plan was to use Buttondown's RSS-to-email feature, where it watches your feed and emails every new item to the list by itself. This site already has a feed (the same one I almost forgot to migrate during the domain move), and it contains the full text of every post, so the fit seemed perfect. Then I found out that feature is a nine dollar per month add-on, which felt like a strange amount of money for a list with zero subscribers on it.

What saved the plan is that Buttondown's API is available on the free plan. So I wrote a small GitHub Action that runs whenever a new post lands in the repository. It waits for the site to deploy, reads the feed, asks Buttondown which posts have already been emailed, and sends anything new. It's around a hundred lines of JavaScript with no dependencies, and it does the same job as the paid add-on. The important part is that there is still no step where I sit down and compose anything, which was a requirement. I know that if every post came with extra chores attached, I would eventually stop publishing rather than do them.

The signup form itself is deliberately boring. It's a plain HTML form that POSTs your email straight to Buttondown, the same way my contact form POSTs to FormSubmit. There is no JavaScript involved and no API routes were added. Buttondown's docs actually warn against submitting to their endpoint with fetch, because the visitor sometimes needs to follow the response to a CAPTCHA or a validation error. A regular form handles all of that for free, and my site stays fully static.

I originally put a second, compact version of the form in the footer of every page. It lasted about an hour. The footer of this site is deliberately the quietest thing on it, small gray text and a hairline, and a coral subscribe button down there jumped out like a sales banner. The card at the end of posts is a better spot anyway. If you just finished reading an article, there is a decent chance you might want the next one.

Working around the free plan

Buttondown's free tier covers everything I need except one thing: it sends a welcome email to new subscribers, but customizing what that email says is a paid feature. I had already written a welcome message I liked and didn't want to throw it away.

The workaround came from a different setting. Buttondown lets you redirect people to any URL after they subscribe and after they confirm. By default the post-signup redirect drops people on Buttondown's own site, which I only discovered by subscribing to my own list and suddenly not being on my own website anymore. So I built two small pages instead. Right after you sign up you land on a page telling you to go click the confirmation link. Once you confirm, you land on a welcome page that contains, word for word, the welcome email I wasn't allowed to send. Nobody leaves the site, and the message I wrote still gets read.

Getting an address at my own domain

This is the part that ate the rest of my week. Newsletters go out from an email address, and mine was going to be my personal Gmail, which contains my full formal name and the number 88 (my birth year) right in the middle. Unlucky for me to have a very common first and last name in Serbia, so most of its Gmail variations were already taken. That is not the impression I was going for, so I wanted the emails to come from aleks@alekspopovic.com instead.

What I learned is that "having an email address at your domain" is actually two unrelated systems that happen to share DNS records.

The sending side is about permission. Buttondown's servers send the emails, and the world needs proof they're allowed to use my domain's name, or everything lands in spam. That proof is a set of DNS records (DKIM and friends) that Buttondown generates and you paste into your DNS. One catch worth knowing: their recommended managed setup wants you to delegate a whole subdomain to them, which would make the address aleks@mail.alekspopovic.com. To send from the root domain you want their manual mode, which is just a short list of records to copy.

The receiving side is a different story, because Buttondown doesn't give you a mailbox at all. If someone replies to aleks@alekspopovic.com and nothing exists there, the reply bounces, and replies are half the reason to run a personal list. I assumed I would solve this with GoDaddy's email forwarding, which used to come free with every domain. It doesn't anymore. My dashboard offered me two paid mailbox subscriptions and nothing else. The free answer turned out to be ForwardEmail, which forwards any address on your domain to your real inbox using nothing but DNS records: two MX records and a TXT record that literally spells out the forwarding rule.

One trap if you ever do this: a domain can only have one SPF record. I added one for GoDaddy's mail servers early on, then switched forwarding providers and had to edit that same record instead of adding a second one. Two SPF records don't merge, they just break authentication for both services.

The last piece was making my replies come from the custom address too, since forwarding only handles incoming mail. Gmail can send as another address if you feed it an SMTP server and an app password, and this fought me harder than everything else combined. Google's dialog first threw a temporary error that wasn't temporary, then an authentication error that turned out to be my own fault. The dialog pre-fills the username field from the alias you're adding, and the username it actually wants is your full Gmail address. The confirmation code Google then sends goes to the custom address itself, so when it showed up in my inbox it also proved that the whole forwarding chain works.

Mistakes I made while testing

Three things I ran into while testing:

  • You can't test email forwarding by sending from the same Gmail account it forwards to. Gmail sees its own message ID coming back and quietly hides the copy, so a working forward looks broken. Send the test from any other account.
  • Don't unsubscribe and delete yourself to reset a test. Buttondown soft deletes subscribers and remembers that your address opted out, precisely so unsubscribed people can't be re-added against their will. My own address is now on that list, which is fair, but inconvenient.
  • Gmail plus aliases solve both problems. Subscribing as yourname+test1@gmail.com gives Buttondown a fresh address that still lands in your inbox, and you can increment the number forever.

The checklist

The compressed version, for anyone adding email to their own site:

  1. Decide what you're promising before you build anything. A notification list and a weekly publication are very different commitments, and I knew I could only keep one of them.
  2. If your site has a full-content RSS feed, you already own the hard part. Your provider can watch it for a fee, or a small script can do the same thing through an API.
  3. Use a plain HTML form for signups. It does everything you need and keeps the site static.
  4. Sending and receiving are separate systems. Budget for setting up both, and check whether your registrar still offers free forwarding before assuming it does.
  5. Watch the SPF record. A domain only gets one, so when you switch providers you edit the existing record instead of adding another.
  6. Test with plus aliases, from a different account than the one you forward to.

The whole thing cost me nothing except a few evenings of reading about DNS records. The card is right below this paragraph, and now you know exactly what happens when you type your address into it. If you set up something similar and hit a trap I didn't cover, feel free to send me a message through the site. I would love to hear about it.


If you have any questions or comments you can reach out to me on X or send me a message through the site.

I also have a YouTube channel where I upload React and web dev tutorials. If that's your cup of tea, feel free to support me by subscribing.

New posts by email

If you want to know when I publish something new, leave your email and I'll send you the post. No schedule, no spam, and you can unsubscribe whenever you want.