Querying Random Blog Posts with Netlify Functions ================================================= By George Mandis https://george.mand.is/2019/12/querying-random-blog-posts-with-netlify-functions Wednesday, December 4th 2019 Inspired by something [Derek Sivers](https://sivers.org) implemented on his site, I decided to add a URL to this site that automatically redirects to a random blog post. You can find the link via the **/dev/random** menu item or simply go to [george.mand.is/random](https://george.mand.is/random). I like it because it adds a quality that's tricky to capture on the web: "skimmability." It reminds me of being able to thumb through the pages of a book before committing. ### With a Traditional Server Setup Setting this up on a traditional server would've been fairly straightforward. If it was running on Apache or NGINX for example it probably would've been just a matter of adding a line to the configuration file to redirect requests to another script on the server that could pick a blog post at random and tell the browser to redirect. There would be other implementation details, but that's the gist of it. ### With Netlify This site, however, is hosted on [Netlify](https://netlify.com). In all the ways Netlify eases the development and deployment experience for some types of sites, doing relatively simple backend things often requires finding interesting workarounds. For this random URL redirection idea I was able to get this up and running without too much trouble using [Netlify Functions](https://www.netlify.com/products/functions/). Here are the steps to take: #### Install the Netlify Command Line Tool. This will allow you to setup and test your functions locally. You can find more information on the [documentation site](https://cli.netlify.com/ "Netlify CLI Documentation") on how to configure your project locally and connect it to one of your Netlify sites. Once you've successfully installed the command line tools and connected your local working folder to your site you can run `npm run dev` in the console and access your site at `localhost:8888` in the browser. Functions, redirects and other Netlify-specific features will behave just as though they're in production on Netlify's servers and allow us to test this feature as we're building it. #### Setup Netlify functions. I suggest calling the folder `functions` and configuring it via a `netlify.toml` file instead of using the web interface. There is more informatoin about how to set that up on Netlify's [documentation page about configuring functions](https://docs.netlify.com/functions/configure-and-deploy/#configure-the-functions-folder). #### Setup Your Redirect Create a **_redirects** file in your Netlify site and add this line: ``` /random /.netlify/functions/random 302! ``` You can also set this up in your `netlify.toml` file, which is explained in [this blog post](https://www.netlify.com/blog/2019/01/16/redirect-rules-for-all-how-to-configure-redirects-for-your-static-site/ "Netlify Redirect Rules"). My site has a lot of simple redirects though and I find the separation to be more manageable. #### Selecting a Random URL From Your Blog We'll need a way to have all the URLs available in our function. This is the trickier part and will vary depending on how you built your site. There are many approaches, but this was my approach: - Create a special URL that returns a JSON feed that's nothing but URLs for all my blog posts - Use `node-fetch` in my function to pull in that data and pick one at random - Send information in the header response to tell the browser to perform a 302 redirect to the random selection I debated adding some measuer of security to this special URL, but decided it didn't much matter. It's really no different than a sitemap and I've ensured that only blog post URLs are presented in this feed. You can see it here: [george.mand.is/_all.json](https://george.mand.is/_all.json). You'll notice it's returning relative URLs. This is helpful for testing it locally. I found creating this feed fairly straightforward with [Eleventy](https://11ty.io) but you could probably do this with whatever static generator you're using. If you're using [Jekyll](https://jekyllrb.com/) I'd taking a look at my [Jekyll JSON feed templates](https://github.com/snaptortoise/jekyll-json-feeds) on GitHub. #### Creating the Function Last but not least we need to create the actual function! I've written mine in Node.js, but you could write yours in Go as well. It's worth noting that the directory structure influences the URL structure for your Netlify function. I've saved the file that contains my function at `functions/random.js` in my project folder. This function's endpoint is automatically created at `/.netlify/functions/random` both in production and locally. Here is the code: ``` /** * Random Blog Post (/random) * === * George Mandis (george.mand.is) */ require("dotenv").config(); const fetch = require("node-fetch"); exports.handler = function(event, context, callback) { fetch(`${process.env.URL}/_all.json`, { headers: { "Accept": "application/json" } }) .then(res => res.json()) .then(response => { const randomPost = response.posts[Math.round(Math.random() * response.posts.length - 1)]; callback(null, { statusCode: 302, body: `Location:${process.env.URL}${randomPost}`, headers: { "Location": `${process.env.URL}${randomPost}` } }); }); }; ``` If you've completed all of these steps you should be able to test your redirection URL locally at `localhost:8888/random` and see a random blog post returned! So far I really enjoy this feature. Anecdotally I'm noticing a few more hits on older posts than normal, but it's nice even for my own sake. It's fun to be able to flip back through the posts I've written over the years.