My current process for writing and publishing content to the web using a static site generator looks like this:
- Open a text file in my project repo on my laptop
- Write/edit content
- Save file
- Stage and commit file using Git
- Push changes to remote repo
- Changes are automatically deployed to live site
This process works pretty well, but I’ve been searching for an even more low-friction process.
When it comes to writing for the web and managing content, I love plain-text files written in markdown. For me, there’s nothing more simple, portable, longevous, or easily editable across operating systems and devices.
I found myself in a situation where I began asking: look I have a collection of plain text files here which represent the state of my blog. When I create a new text file (or edit an existing one) and then save it, why can’t that be the equivalent of hitting “Publish”? Well I’m here to tell you it can.
First, let me tell you which technologies I’m leveraging:
- GitHub (for code)
- Jekyll (for static site generation)
- Dropbox (for content)
- Netlify (for build tool + host)
These technologies work in concert to cut even more steps out of my process, making writing and publishing content to the web an act of editing and saving a text file.
First, I use Dropbox to manage a bunch of plain-text markdown files. Why Dropbox? Because of cross-platform sync. I can edit a plain-text markdown file on my laptop, a mobile device, or just about anywhere, and when that update is synced to Dropbox, I can configure a webhook to be sent from Dropbox to Netlify, triggering a new build. Then, my build process fetches my plain-text markdown files from Dropbox and builds my static site with the most up-to-date content.
In other words, the simple act of “saving” a file kicks off a process which builds and publishes my site to the web with the latest content. When I update content, I don’t even have to think about committing, building, or deploying my site. I merely edit and save plain-text files. With Netlify, my production site is a function of my content: plain-text files. A picture is worth a thousand words, so allow me to illustrate:
Here’s my newly revised process for writing and publishing content to the web using a static site generator:
- Open a text file in my project repo on my laptop on any device
- Write/edit content
- Save file
- Stage and commit file using Git
- Push changes to remote repo
- Changes are automatically deployed to live site
You can dive right into the code behind how this works by looking at my simple starter repo: Netlibox (it’s Netlify + Dropbox, I know, naming is hard). Or, check out the demo site that gets generated by visiting netlibox.netlify.com
The Nuts and Bolts
I briefly covered what technologies I’m using to achieve my simplified process for writing and publishing content to the web, but allow me to expand a little more.
Git + Static Site Generator (GitHub + Jekyll)
For my static site, I have a git repo in GitHub where I store the HTML, CSS, JavaScript, and other configuration files which constitute the code of my site. Quite often, the plain-text markdown files of your content would also live in your Git repo, but I abstracted those into a separate space (Dropbox) and pull them in at build time.
To generate a site, you’ll need some framework for generating a static site. You could use anything you want here, but for my example, I use Jekyll because it’s probably the most familiar to the most people (plus it’s easy to setup with little configuration).
The key difference here is that, rather than have a _posts
folder with a bunch of markdown files (as dictated by Jekyll) directly in my Git repo, I create that folder and its contents at build time by pulling all my plain-text markdown files from Dropbox. This is done via a custom node script that gets run before Jekyll does its thing. For example, rather than your build command being jekyll build
you would do something like node fetch-posts.js && jekyll build
.
Dropbox + Netlify
In Dropbox, you can create an app which is essentially a way of getting programmatic access via the API to files inside your Dropbox. In my case, I created a new app with its own folder, which is advantageous because your associated API tokens will automatically scope access to that specific folder (as opposed to your entire Dropbox). This folder is essentially my Jekyll _posts
folder that gets pulled in at build time.
Once you have an “app” in Dropbox, you can enable webhooks for that app:
Webhooks are a way for web apps to get real-time notifications when users’ files change in Dropbox. Once you register a URI to receive webhooks, Dropbox will send an HTTP request to that URI every time there’s a change
Netlify allows you to generate incoming webhooks which give you a unique URL you can use to trigger a build of your site. At first glance, the integration between Dropbox and Netlify seems quite simple: add the incoming webhook URI Netlify generates for you to your Dropbox app, then Dropbox will ping that Netlify URI to trigger a build every time a file changes. However, it’s not quite so straightforward.
Dropbox requires you to register your URI via a “verification request”:
The first request to your new webhook URI will be a verification request to confirm that Dropbox is communicating with the right service. The verification request will be a GET request with a challenge parameter, which is a random string…Your app should echo back the challenge parameter as the body of its response. Once Dropbox receives a valid response, the endpoint is considered to be a valid webhook, and Dropbox will begin sending notifications of file changes.
In other words, Dropbox wants to know that the URI you enter to receive HTTP requests is expecting these requests and that you, therefore, control the endpoint. The incoming webhook URI that Netlify gives you cannot do that. It merely listens for a POST
request, then triggers a build if it gets one. But Dropbox won’t send a POST
request until it verifies the endpoint by getting a response it expects. So now what?
This is the point at which you might think “well, this whole JAMstack thing is great, but you’ll always find yourself needing a server for something.” But guess what? Netlify can solve this problem for you with its Functions feature which “opens a world of possibilities for running on-demand, server-side code without having to run a dedicated server”. The best part is Functions are free below a certain usage tier, which is 125k requests/month at the time of this writing (a limit I do not plan on hitting for Dropbox notifications).
So, in my use case, I was able to write my own function endpoint to handle the verification request. Once the verification request is handled by my Netlify function, Dropbox will start sending POST
requests to it. Then I merely forward those to the webhook URI Netlify gave me for triggering builds. In essence, the logic is:
- My custom endpoint (
https://mynetlifysite.netlify.com/.netlify/functions/dropbox-webhook
) gets pinged by Dropbox (substitutemynetlifysite
for your own) Is this a verification request? Send a response to Dropbox in the format it expects to verify the request. Otherwise, forward the request to my webhook URI generated in Netlify, which triggers a build.
Conclusion
Netlify is amazing for many reasons, but in this particular case, it gave me tools that previously would’ve been too complicated for me to setup and maintain on my own. Because I now have these additional tools, the size of what’s possible for me to build on my own has increased. This is one of the reason I love Netlify: it grows the possibilities for me to create whatever I can envision.
In this particular case, Netlify gives me control over my build process such that I can abstract my content from my code then pull it in at build time. On top of that, I can automate the triggering of builds based on when a file is edited or saved, so I don’t have to worry about building/deploying a website. With Netlify, I can create and edit plain-text markdown files then trust that the current state of those files at any point in time represents my live website.
Checkout Netlibox on GitHub to learn more or try this out yourself.