blog

Netlify Functions + Buttondown

Learn how to use Netlify Functions and Buttondown to create a custom newsletter subscription form for your website.

I enjoy the process of designing and building a custom personal website. It’s a great way to experiment with different technologies and have fun learning new tools and concepts along the way.

This time, I was eager to learn how to use serverless functions.

The Challenge

I use a static site generator called Jekyll to build and publish my website. The result is a collection of static HTML, CSS, and JS files that are lightweight, fast, and easy to maintain. It reduces my overhead, both in cost and time because I don’t need to manage a server. But it does have one drawback: I can’t easily handle small background actions, like form submissions.

After all the effort I put into building my personal website, the last thing I wanted to do was slap a pre-designed newsletter subscription form on it. Most email providers offer forms you can quickly embed on your website, but they come with a series of tradeoffs. They are difficult to customize to exactly match your website’s design, and they usually require users to load third-party scripts and styles. Often these third-party resources get blocked by browser privacy settings, and even if they don’t, they can be slow to load.

Eventually, this led me to serverless functions. A serverless function is really just a piece of code that runs like an API endpoint, independently of your website or app. Despite the name, serverless functions do, indeed, run on a server. It’s just a server you don’t have to build or maintain.

The Team: Netlify and Buttondown

I use a service called Netlify to build and deploy my website. It’s key for this project because it publishes the static HTML, CSS, and JavaScript assets from my static site generator to a global CDN and runs the serverless function for my email subscription form.

I’m using Buttondown as my email list provider. Buttondown is a simple, privacy-first newsletter platform. It offers an API with extensive documentation, including an OpenAPI Specification file. Buttondown is free for up to 100 subscribers, after which it costs $9 a month for up to 1,000. The API is available for paying customers starting at the $9/mo plan.

As a side note, Buttondown offers extensive customization options for HTML form embeds, so you can accomplish almost everything in this tutorial with less work. But this is a good starting point to learn how to build serverless functions and as an introduction to creating advanced automation with the Buttondown API.

Here is a brief overview of the steps involved:

  1. Prepare your environment
  2. Create the newsletter subscription form
  3. Write the serverless function
  4. Deploy with Netlify

Ok, let’s get started!

1. Prepare your environment

To begin, you need to configure a few settings within Netlify before you can start building serverless functions.

Configure your Netlify.toml file

First, you need to tell Netlify where it should find and process your serverless functions. If you don’t have one already, create a file in your root directory called netlify.toml. The most basic version should include information about how to build and publish your website. Refer to the Netlify documentation for additional information.

In this example, publish tells Netlify to deploy the HTML and CSS files saved in the public folder for a simple, static website. This example also includes a command Netlify should run (npm install). Netlify will install the single node module dependency you will need later.

[build]
  publish = "public"
  command = "npm install"

Now you can add the path to the functions directory. The default functions directory is YOUR_BASE_DIRECTORY/netlify/functions. You will need to use the node-fetch v3 module later. Due to a change to node-fetch, you will need to enable ESM for the site by adding node_bundler = "esbuild" under the [functions] section of your netlify.toml file:

[functions]
  directory = "netlify/functions/"
  node_bundler = "esbuild"

For this tutorial, your completed netlify.toml file should look like this:

[build]
  publish = "public"
  command = "npm install"

[functions]
  directory = "netlify/functions/"
  node_bundler = "esbuild"

Save your API Key as an environment variable

Next, you must add your Buttondown API Key as an environment variable for your Netlify site. Environment variables are useful to hold information that we don’t want to make public, like API Keys.

Find and create your API Key in Buttondown under Settings > Power Tools > API. Copy this value and then add it as an environment variable using the Netlify Admin interface under Site Settings > Environment Variables.

For this tutorial, we’ll name the key BUTTONDOWN_API_KEY, add the value from Buttondown, and save it.

Add the Buttondown API key as an environment variable

2) Create the newsletter subscription form

Now that Netlify is set up, I need a way to collect email submissions. The HTML for my email subscription form is very basic to start:

<form name="newsletter" method="POST" action="/success/" data-netlify="true">
  <label for="email">Your Email Address:</label>
  <input type="email" name="email" required />
  <button type="submit">Subscribe</button>
</form>

There are a few important things to note. First, I need to tell Netlify to process the form. All I need to do is add the data-netlify="true" attribute to the form tag.

Next, I must give the form a unique name using the name attribute. In this case, that’s simply name="newsletter". The form’s name attribute determines what shows up in the Netlify interface:

List of forms in the Netlify app

I wanted to redirect users to a confirmation page, so I added action="/success/" to display a page that contains the success message.

The next input in the form is named email. That’s where we collect the email addresses. You could name it anything, but make sure you note what you call it for the next step.

I’ve specified the input type as email and indicated that is required. This means that the browser will do all my validation for me, and won’t let users submit anything besides a valid email address.

Enable bot and spam protection

I’m going to take advantage of the built-in anti-spam and bot protection that comes with Netlify Forms, so I'll tweak the form a bit. I added the netlify-honeypot="bot-field" attribute and created a hidden label and input:

<label class="hidden">Don’t fill this out:</label>
<input class="hidden" name="bot-field" />

This should catch any bots and filter them out before they ever hit my subscriber list. Here is the completed HTML for the newsletter subscription form:

<form
  name="newsletter"
  method="POST"
  action="/success/"
  netlify-honeypot="bot-field"
  data-netlify="true"
>
  <label class="hidden">Don’t fill this out:</label>
  <input class="hidden" name="bot-field" />
  <label for="email">Your Email Address:</label>
  <input type="email" name="email" required />
  <button type="submit">Subscribe</button>
</form>

3) Write the serverless function

Now that I have a working email submission form, it’s time to create the serverless function. To start, create a file in the functions folder called submission-created.js. If you used the default functions directory, you should save your function at YOUR_BASE_DIRECTORY/netlify/functions.

I’m going to use the submission-created event trigger, which will tell Netlify to run my function every time the form is submitted. To accomplish that, I have to make sure the file is named submission-created.js.

Here’s the code for the serverless function:

const { BUTTONDOWN_API_KEY } = process.env;
import fetch from "node-fetch";

exports.handler = async (event, context) => {
  const email = JSON.parse(event.body).payload.email;
  console.log(`Received a submission: ${email}`);

  const response = await fetch("https://api.buttondown.email/v1/subscribers", {
    method: "POST",
    headers: {
      Authorization: `Token ${BUTTONDOWN_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ email }),
  });

  let responseText = await response.text();
  console.log("Response:", responseText);

  return {
    statusCode: 200,
    body: JSON.stringify({}),
  };
};

Let’s look at this line-by-line to understand how it works.

Configure prerequisites

First, I import the Buttondown API key I saved earlier as an environment variable for my function:

const { BUTTONDOWN_API_KEY } = process.env;

On line 2, I import a small library called node-fetch. This allows me to use Javascript’s Fetch API, which is how we’ll format an API POST request to send data to our email service:

import fetch from "node-fetch";

NOTE: When I was writing this post, many of the tutorials available used the require method to import the Fetch API, which resulted in errors when I tried to deploy the function. Make sure you use the method I described above. If you upgrade to node-fetch v3, you'll also need to update either your netlify.toml file or package.json to use ESM.

[functions]
  node_bundler = "esbuild"

You can find more information about how to make a fetch request using node-fetch v3 in an excellent guide by Tatyana Novell on the Netlify blog.

Define the serverless function

Line 4 is where I define the function. The exports.handler value is where Netlify expects to find the function. This is the basic syntax I’ll use to create the serverless function:

exports.handler = async function (event, context) {
  // your server-side functionality
};

Parse the form submission

The first thing I need to do is retrieve the email address from the form submission. I’m going to use JSON.parse. Since I’m using an event to trigger the function, we’ll use event.body to parse the submission and payload.email to retrieve the value of the email input field.

const email = JSON.parse(event.body).payload.email;

Then log the data in the console for debugging:

console.log(`Received a submission: ${email}`);

Create the API request

After retrieving the email address from the event value using JSON.parse, I’m ready to add the email to my list of subscribers using the Buttondown API. I’ll use the node-fetch library I imported earlier to create the POST request.

I need to authorize the API request by passing the BUTTONDOWN_API_KEY environment variable in the headers, and I’ll need to add the email address to the body of the request as a string:

const response = await fetch("https://api.buttondown.email/v1/subscribers", {
  method: "POST",
  headers: {
    Authorization: `Token ${BUTTONDOWN_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ email }),
});

Log the response

Then capture and log the response from the email service. We do this to diagnose any issues that happened. Netlify makes it easy to check your function’s logs, so use console.log often!

let responseText = await response.text();
console.log("Response:", responseText);

And finally, we return the response from the function with an empty body:

return {
  statusCode: 200,
  body: JSON.stringify({}),
};

4) Deploy the function

Now that I’ve written my function, configured my netlify.toml file, and added my environment variables, everything is ready to go. Deploying is painless: just set up Netlify’s GitHub integration, push your changes, and your function will be deployed.

Conclusion

It took me less than 50 lines of code to build a custom newsletter subscription form using a serverless function. I wrote it all in HTML, CSS, and JavaScript, and everything is served from my domain. Plus, my website visitors get a nice experience whether they have JavaScript enabled or not, and I’m protected from bot and spam submissions by default.

If you’d like to experiment with creating your own custom newsletter form, you can clone and deploy the GitHub Repository below to Netlify. It comes with a minimal HTML landing page, a simple form, and everything you need to deploy the Netlify Function:

Good luck, and I hope you have fun building a custom newsletter subscription form for your website!

A version of this article originally appeared at andrewstiefel.com on August 28, 2022.

What customers say about Buttondown

Overall, Buttondown has been terrific to work with and I recommend them for anybody who's thinking of starting a newsletter or moving over like I did.
Andy Magnusson
Customer Engineering Leader
Wanna know how good Buttondown as a product experience is? I upgraded to Basic before sending the first email, and then upgraded again two days later.
Zak El Fassi
Founder, Zaigood Labs
Mailchimp lost me due to their inferior product and the nightmarish merry-go-around experience with their overseas support team. Buttondown won me over with their superior product and second to none customer service.
Sav Tripodi
CEO, Sanico Software
Your support is amazing and I deeply appreciate how available and helpful you are. I LOVE being able to turn tracking pixels off. I didn't even realize this was an option when I signed up and am SO HAPPY to not track people.
Andrea Mignolo
Method & Matter
I'm also impressed with how responsive you are, and how you directly answer customers. Makes it really clear that signing up for your service was a good decision.
Nicole Tietz-Sokolskaya
Software engineer and writer
Very happy with Buttondown, works smoothly, it's very configurable and I love the minimalist design of the UI. It makes me focus on my writing. Plus, I'm super happy to support independent software and I should mention - the support I receive whenever I have a question is warm and quick :)
Martina Pugliese
Data scientist and storyteller
I just tested the RSS to Email feature for one of my blogs and it was incredibly easy to set up. It took me about 30 mins to figure out the same feature in Mailchimp.
Nicolas Bernadowitsch
Blogger
This long weekend I fulfilled a long-standing promise to myself to switch my RSS-to-email provider from Mailchimp to Buttondown, and it’s been such a great experience. It’s cheaper, more flexible, less cluttered, and it’s run by Justin Duke who is just delightful and answered a bunch of my questions over the weekend (even though I asked him to please not!).
Rian van der Merwe
Director of Product at PagerDuty
I've been wrangling half a dozen tools to get my stuff up and running recently, almost all of which had some hiccup. Buttondown had zero. It did everything I expected and needed the first time.
Catherine Cusick
Self-Employed FAQ
I, like almost everyone else I've seen talk about Buttondown, am IMMENSELY happy and impressed with your customer service. It turns out we can have nice things, which is really refreshing.
Ed Yong
Staff writer, The Atlantic
Email makes the world go ‘round, and Buttondown is how I manage it all for my keyboard projects.
Tim van Damme
Founder, MVKB
It's a truth, that should be more universally acknowledged, that Buttondown is the best newsletter software. Simple, does exactly what it sets out to do, and reasonably priced.
Noel Welsh
Founder, Inner Product
Buttondown is the perfect fit for my headless newsletter use case. And I contacted support with some specific requests and Justin responded within 30 minutes with great answers and a nice pinch of charm.
Sam Roberts
Software engineer, Tamr
Hands down the easiest way to run a newsletter - and the free version is generous!
Javeed Khatree
SEO expert
With API and Markdown support, you can build workflows that make it so easy to write.
Westley Winks
Peace Corps
I’ve never enjoyed writing newsletters as much as I do with Buttondown.
Kevin Lewis
You Got This!
Buttondown remains the easiest thing I use regularly, and I am grateful for that.
Casey
Journalist
It's a humble app doing a common job but with end users in mind.
Si Jobling
Engineering Manager
Buttondown has been an amazing experience for me. The service is constantly being improved and customer service is the best. My newsletter with Buttondown has grown from a fairly small list to over 15,000 subscribers, and it hasn't broken a sweat yet.
Cassidy Williams
CTO, Contenda
I switched over to Buttondown from Mailchimp because of the difficulty I had with Mailchimp's campaigns, so Buttondown's easy and user-friendly system has been a genuine breath of fresh air.
Jessi Eoin
Illustrator + Comic Artist
You’ve truly built a great product that I feel good about using (vs a monopoly from our tech overlords).
Rachel
2030 Camp
I love how personal Buttondown feels, especially compared to Mailchimp, Convertkit, and services like that.
Simen Strøm Braaten
Designer
This product has been exactly what I’ve needed!
Nathan Bird
Podcast host, Chattanooga Civics
It's already so refreshing compared to the mega companies.
Casey Watts
Author, Debugging Your Brain
Definitely will be using for the foreseeable future. It’s a great service and I feel well cared for. Thank you!
Phoebe Sinclair
Author
I’m a sucker for elegant UI and I really love your site, but above that I think your product has so much value for so many different people. I’m not a coder, I’m only familiar with the bare basics, but I was able to figure out and utilise Buttondown quickly.
Claudia Nathan
Founder, The Repository
The killer feature for me: Buttondown will take an RSS feed then automatically slurp up the content (in their words) and then send it to our subscribers. Job done. They seem like a good company too, so I’d say this is a winner.
Andy Bell
Founder, Set Studio
As a recent user of Buttondown, they are super on the ball. A week ago I discovered a security vulnerability and reported it on Friday afternoon. They acknowledged and fixed it in under two hours. On a Friday night! Talk about going above and beyond for your users!
Predrag Gruevski
Principal Engineer, Kensho
Well may I just say your support experience is already approximately 1 billion times better than ConvertKit. Excited to be switching!
Michael J. Metts
Author, Writing is Designing
Privacy focused sending and sign up form; lets me focus on writing - editor is "just" markdown; simple, elegant design template looks like a blog post; the founder is amazing - he's helped with every question I've had, even outside of Buttondown.
Joe Masilotti
Founder, RailsDevs
We need more nice and professional services like yours on the web.
Tobias Horvath
Designer and developer
No one is paying me to say this, but I love @buttondown so far for my lil newsletter. It’s so smart, simple, and attractive (and to my knowledge, not actively anti-trans!). Customer service is also legitimately excellent.
Julie Kliegman
Copy chief, Sports Illustrated
I love it! It lets me breathe, not compete as I write with other writers.
Devin Kate Pope
Writer and editor
It’s a pleasure working with you. Thank you! (And what a contrast with Mailchimp, where I spent two weeks and a dozen of emails trying find out why our form goes down sometimes (only sometimes), and never really got a real answer.)
Anton Sotkov
Software Engineer, IA
Buttondown exemplifies how I wish most software worked, and I hope to achieve a similar thing with the software I develop in the future.
Matt Favero
Software engineer
It feels incomparably good to be able to email just like a guy named Justin when you have a @buttondown question 15 minutes before you’re about to blast a Geistlist email. (Not a guarantee but wow this guy is human-level good.)
Jacob Ford
Designer About Town
Enter Buttondown, Justin Duke’s lovely little newsletter tool. It’s small, elegant, and integrates well. And it is also eminently affordable.
Will Buckingham
Author
Your settings page is a joy to use and everything about Buttondown makes me happy.
Gareth Jelley
Magazine editor
have been on Buttondown for ~18 months and I can't recommend it enough.
Elizabeth Minkel
Podcast host
You really do make ALL other customer service look terrible by comparison.
Chris Mead
Improv teacher
There is a caring person on the other side of this software, which is one of the things I like the most about Buttondown.
Keith Calder
Film & TV Producer
I’d also like to add that @buttondown is an absolute joy to use. Hats off, Justin!
Elliot Jay Stocks
Creative Director, Google Fonts
Shoutout to @buttondown and @jmduke for building an amazing bootstrapped product for newsletters, all while being very open to feedback and connecting directly with customers 🙏 Easily one of the most enjoyable product experiences I've had.
Den Delimarsky
Head of Ecosystem, Netlify
if you are looking for "newsletter tool for hackers" i tentatively believe the answer is @buttondown full api, compose in markdown, good docs for setting up domain auth, simple subscribe form HTML that you style yourself (or not)
Brian David Hall
Author, Your Website Sucks
I really like @buttondown as a blogging platform, it has the simplicity of Substack but the corporate culture is less toxic.
Chad Loder
Extremism researcher
I worked with @buttondown and asked for some new payment support beyond the supporter single tier / pay-what-you-want options. Justin was great and built it in just a couple days.
Dan Hon
Author & consultant
I write nonfiction and I use @buttondown buttondown.email/Changeset - indie, GREAT personal customer support, very nice default styling, all the options I want including ones to protect my readers' privacy
Sumana Harihareswara
Open source maintainer
I use @buttondown because it does exactly what I need (manage subscribers and send markdown emails), not more and not less 👍 As a bonus it's made by an indie dev which I love!
Max Stober
Founder, GraphCDN
If you’re considering running an email newsletter, or if you already run one and are considering a change of provider, I highly recommend @buttondownemail. Super-easy app, very fair pricing with a generous free tier, and exemplary support. 💯
Peter Gasston
Technologist and speaker
imo @buttondown is easily one of the best-designed services i’ve used in recent years, if you have a substack you should really consider switching!
Kabir Goel
Engineer, Cal
Thanks for getting me excited about email newsletters again.
Garrick van Buren
I'm very thrilled that I can just write in Markdown without having to deal with email builders and all that crap.
Parham Doustdar
Thanks again for all the help! You’ve really turned something super complex into something super easy – sending new issues is as simple as firing off a text message.
Kartik Chaturvedi
Thanks for creating a simple way for people who want to, like, put words in a hole and have it sent to people... I am just thankful that something just nice and human exists on the internet.
Emmanuel Quartey
I tried 3 other newsletter services today and I felt like wanting to rip my hair out. They were all painfully slow. I'm so glad I found Buttondown.
Mohamed Elbadwihi
I’ve found Buttondown to be a great fit for my workflow and have been delighted by all of Justin’s thoughtful features and improvements to the product.
Michael Lee
Like seriously, so many lovely little easter eggs in one could-be-boring service.
Alexandra Muck
I just switched over from Tinyletter and I'm really excited to have found a place to host my tiny newsletter that doesn't seem like it's assuming everyone sending newsletters is an email marketer / growth hacker.
Tessa Alexanian
I'm in love with the simplicity of Buttondown.
Ekfan
I’ve used similar tools in the past and Buttondown is by far the simplest to use and most promising.
Fabrizio Rinaldi
Thank you for creating such a simple and brilliant tool. I’ve just signed up and the experience has been smooth and painless (the docs are great too!)
Oliver Holms
As a developer who has hated every email system I've ever used this is so nice.
Drew Hornbein
I wish I still wrote a newsletter just so I could use buttondown again. It’s like that.
Steven Kornweiss

Ready for a better newsletter?

See why thousands of businesses and creators use Buttondown to send millions of emails every day.

Best practices, news, and more. Every month.

See why thousands of businesses and creators use Buttondown to send millions of emails every day.

Have a question? We’re here to help.

We're email experts who are always available to answer your questions.