David Atanda Building scalable applications on the web.

Going serverless with Eleventy

4 min read 1239

Eleventy Logo Over a Pink Background

Using Eleventy alone can help you produce great static websites efficiently and boost performance. However, this does not work well when using dynamic data in your application.

In this tutorial, we’ll walk through the process of creating Eleventy components and then show you how to use the Eleventy Serverless plugin to handle logic and data.

What is Eleventy?

Eleventy is a static site generator that uses various templating languages to assemble finished HTML webpages you can host with your provider.

Eleventy cycles through all the files in your project to gather data from different template languages, including markdown, Nunjucks, Liquid, Haml, JavaScript, etc. Then, during build time, it uses the templating languages to generate an output folder with *.html files — i.e., a static HTML website.

This makes for outstanding performance, but it comes with a drawback around dynamic content and user input.

What is Eleventy Serverless?

Eleventy Serverless is a plugin that enables you to manage dynamically generated data in Eleventy using serverless functions. It uses Netlify Functions but can also work with Netlify’s On-demand Builders, as we will explain later.

Eleventy Serverless works hand in hand with your static site, but it runs one or more template files at the point of HTTP requests to generate dynamic pages. It can unlock many new use cases to move beyond static webpages into dynamically generated content.

On-demand Builders are functions that cache the result. Run it once and get static HTML on every other run.

Eleventy installation

Let’s initiate our project and add our package.json by running this command:

npm init

To use Eleventy Serverless, we need the latest version of the 1.0 release of 11ty, which is 1.0.0.canary.44 at the time of writing:

We made a custom demo for .
No really. Click here to check it out.

npm i @11ty/[email protected]^1.0.0-canary.44

Also, we can install Netlify Functions:

npm install @netlify/functions

Eleventy configuration

To use Eleventy Serverless, we need to go to our root folder to create and configure our .eleventy.js file. This file helps us configure Eleventy Serverless in our project. The Eleventy Serverless plugin ships with Eleventy itself, which we just installed).

The Eleventy configuration is as follows:

const { EleventyServerlessBundlerPlugin } = require("@11ty/eleventy");
// Require the package we just installed
const axios = require("axios");
module.exports = function (eleventyConfig) {
  eleventyConfig.addPlugin(EleventyServerlessBundlerPlugin, {
    name: "rick", // The serverless function name for the permalink object 
    functionsDir: "./netlify/functions/",


As mentioned earlier, we import EleventyServerlessBundlerPlugin from our 11ty/eleventy. Then, we set the config for our serverless plugin using eleventyConfig.addPlugin.

We can add the name of our serverless function and the Netlify Function directory that’ll handle our serverless function.

Getting started

Now it’s time to see Eleventy Serverless in action. We’ll demonstrate how to make requests or add business logic to display dynamic content on your site.

We’ll use the Rick and Morty API to display all characters named Rick who are still alive on the show.

Rick Finder


First, let’s go back to our .eleventy.js file and create our filter:

const { EleventyServerlessBundlerPlugin } = require("@11ty/eleventy");
// Require the package we just installed
const axios = require("axios");
module.exports = function (eleventyConfig) {
  eleventyConfig.addPlugin(EleventyServerlessBundlerPlugin, {
    name: "rick",
    functionsDir: "./netlify/functions/",
  eleventyConfig.addFilter("rickList", (name) => {
    const list = axios
      .then((res) => {
        let i = res.data.results
        return i
      .catch((err) => console.log(err));
      return list 

This rickList filter takes in a name parameter and sends a request to the Rick and Morty API, which returns a response. We’ll display this response in our UI.

The build will automatically create the netlify/functions folder for our serverless functions.

Netlify Functions

Our Netlify Functions can either be dynamic or cached. By default, it’ll be a dynamic serverless function that runs on every load.

With cache, we’ll use Netlify On-demand Build to improve performance and cache its results. So if our filter has reoccurring arguments, we don’t need to run that script again. Instead, we can use the previously cached result. This way, we only run the functions when there are new arguments for our serverless functions. The cache serverless function uses Netlify On-demand Builders to run.

To set our function to cache, go into the generated netlify/functions/rick/index.js, scroll to the bottom, and replace the following:

exports.handler = handler;

With the following:

const { builder } = require("@netlify/functions");
exports.handler = builder(handler);

Before getting into the actual code, we should add the right files to our .gitignore file. We need to add our Netlify Function files, so we will not upload them to a version control tool such as Git.


Eleventy components

Now, create a new folder called _includes. Within this folder, create a base.njk file. By default, Eleventy uses _includes to find the template file to render.

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://unpkg.com/some-nice-basic-css/global.css" />
    <style>.container{max-width: 80ch;margin: auto;</style>
    <title>{{ title }}</title>
    <main class="container">
        {{ content | safe }}

Let’s go to our root folder and create an index.njk file that we will import into the _includes/base.njk. This index.njk file will contain our homepage, which is what the user sees once they open the site.

title: "Rick Finder"
layout: "base.njk"
    build: "/"       
{% set pageTitle %}
    {% if eleventy.serverless.path.title %}
        {{ eleventy.serverless.query.query | safe }}
    {% else %}
        {{ title }}
    {% endif %}
{% endset %}
<h1>{{ pageTitle }}</h1>

<button onclick="window.location.href = '/rick/'" id="rickForm"> Follow this button to see rick</button>

The index.njk file displays a title and button to help us navigate to the /rick page.

Create a rick.html file in the root folder, the same level as the index.njk file:

layout: "base.njk"
    rick: "/rick/"

<a href="/">&laquo; Head on home</a>

{% assign name = "rick" %}
{% assign results = name | rickList %}
<div class="card-grid">
  {% for result in results %}
    <h1>{{ result.name }}</h1>
  {% endfor %}

Here, we set the permalink of this page to be the same as the name of our serverless plugin.

We’ll create a variable called name and assign it to the string rick. Then, we’ll trigger the rickList filter in our config file by providing with name as an argument. The response is assigned to results. Then, we loop through the response and display the names.

We can kickstart it by running npm run start.

Now, if we go to localhost:8080/rick/, we’ll see a list of characters in Rick and Morty that bear the name Rick:

List of Ricks


Congratulations if you made it to the end!

In this tutorial, we introduced you to Eleventy Serverless, walked through the steps of installing configuring Eleventy, and demonstrated how to use Eleventy Serverless to handle asynchronous logic in a real-world project. Most importantly, we showed how this can be done beyond static sites.

The complete code used for this demonstration is available on GitHub.

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page and mobile apps.

David Atanda Building scalable applications on the web.

Leave a Reply