Building a Mini CMS with Node, Handlebars, and Airtable
Tags: glitch, cms, airtable, tinyletter
Published: 2019-07-05 20:23:43

---
title: Building a Mini CMS with Node, Handlebars, and Airtable
published: true
description: Generate HTML for a Newsletter from Airtable Records
tags: ['glitch', 'cms', 'airtable', 'tinyletter']
---

I recently started [a newsletter on housing & streets policies using TinyLetter.com](https://tinyletter.com/cassey). For my first couple editions, I used TinyLetter's WYSIWYG editor, but I found before long that [the HTML & styling it generates can be very inconsistent](https://tinyletter.com/cassey/letters/america-the-update). How embarrassing! 

Fortunately, the TinyLetter WYSIWYG editor also lets you enter HTML source directly. I decided that would be the best route, but I'd prefer to write my newsletters in Markdown and generate the HTML in a structured way. I also was looking for a way to enter ideas for my newsletter on the go - the TinyLetter editor on mobile isn't the most friendly, and I don't have a go-to notes app that I use already. 

I came across [this blog post on using Trello as a CMS](https://changelog.com/posts/trello-as-a-cms) and decided to try to build something similar using [Airtable](https://airtable.com), which I already use for storing structured personal data and to-do lists. I knew that there are some [great Airtable starter projects to remix on Glitch.com](https://glitch.com/@cassey/airtable-examples-starters), so building off one of those felt like a natural step. I remixed [the Glitch project Airtable-Example](https://glitch.com/~airtable-example) and began hacking. 

First, I built the [Airtable base to hold my newsletter content](https://airtable.com/shrCO5ikWX59JShpn). My newsletter is typically in the form of a link roundup, so I expect each newsletter to have multiple entries with a title and associated URL, and a description that tells why I think people might find this link interesting. 

![The Kanban view of the Airtable base where I store my newsletter content ideas](https://thepracticaldev.s3.amazonaws.com/i/98pbttaw4angz25n469b.PNG)

Next, I started working on the code. At first I thought maybe I'd want to write the generated HTML to a file that I could copy, but I also wanted to be able to see the rendered HTML of a given newsletter before pasting it in to the TinyLetter editor. So, I decided on a format where the HTML will be displayed side-by-side with the rendered newsletter contents. 

![The view I want for my newsletter: raw HTML I can easily copy on one side, with the rendered version of that HTML on the other side](https://cdn.glitch.com/b4ff59ce-a95e-497f-8233-9a876d70e561%2Fairtable-newsletter-rendered.PNG?v=1562357949190)

At first I was using EJS, as it's a templating engine that has worked well for me on simple projects in the past. I soon found some limitations though that led to a switch to Handlebars. Primarily, there is no support for custom filters in the latest major version of EJS. I wanted a filter to render some of my data (the description field of each newsletter item) as markdown, so that I could have nicely formatted descriptions when I had a lot to say about a given link.

The case where I had a lot to say about one particular link also led to a new format for my newsletter: instead of an `<ul>` with many links, I wanted to send out info about just a single link, which wouldn't belong in a `<ul>`. So, I found some helper code for a `compare` filter in Handlebars that would let me render a `<ul>` if I have multiple links to show, and a `<div>` if there is just one link. I found it a bit odd that this isn't built in to Handlebars, but it was easy enough to add a custom helper for it. 

I wanted my work-in-progress newsletters to be private, so I added some very basic authentication. I created a form on the index page with a password field, which has to be filled in to match the value I set in `.env` in order to reveal the contents of the newsletter.  

I also wanted my newsletter CMS to be as generalized as possible so others who found it useful could use it. So, I stored all the info that's custom to my app (the name of my newsletter, my name, the values to configure the base to pull newsletter contents from, etc.) in the `.env` file. When you [remix the Airtable-Newsletter-CMS project on Glitch](https://glitch.com/edit/#!/remix/airtable-newsletter-cms), you'll get a version of the project with the `.env` ready to fill in with your own values. 

You can see [the running project on Glitch](https://airtable-newsletter-cms.glitch.me) and remix it for your own use if this is something that feels useful to you.
{% glitch airtable-newsletter-cms %} 

And of course, if you care about housing & streets policy developments, [subscribe to Cassey's Livable Communities Roundup](https://tinyletter.com/cassey), which was the main impetus for creating this app.