Serving an Eleventy website with full paths locally

2019-04-19

Eleventy by Zach Leatherman has become my default static site generator. It is simple, uses JavaScript, and is easy to extend. Before, I used Jekyll. However, I switched to Eleventy because I wanted a JavaScript alternative that allows me to include custom code to access additional data sources, such as RDF datasets.

There is one option of Jekyll that I missed in Eleventy: when you serve a website locally via jekyll s, then the url in _config.yml, for example http://example.com, is ignored and http://127.0.0.1 is used instead. The variable url contains the root url of your website, and can be used in templates, for example, to create HTML links. However, when serving the website locally your url does not necessarily point to your local machine. In that case, links with that url will not work. For example, if our url is http://example.com and we serve the website locally, then browsing to http://example.com/contact does not work. However, browsing to http://127.0.0.1/contact does work. Therefore, replacing all links with http://example.com with http://127.0.0.1 does the trick. Note that this problem does not occur if you only rely on relative paths.

Eleventy has also the option to serve a website locally via eleventy --serve, but considering there is no predefined way to define your url, that url is also not replaced with http://127.0.0.1 or a local IP address. However, due to ease of integrating custom code we can resolve this with not too much of a hassle. This is done by using the following two files:

  • site.js: a JavaScript file that contains the url and and sets it to the local IP address if available.
  • 11ty-serve.sh: a Bash script that gets the local IP address and runs Eleventy.

Site.js

const site = {
  "title": "My example website",
  "baseURL": "http://example.com",
  "description": "My example website built using Eleventy."
};

module.exports = function() {
  // use the URL that is set via an environment variable
  if (process.env.ELEVENTY_URL) {
    site.baseURL = process.env.ELEVENTY_URL;
  }

  return site;
};

The variable site contains the details about the website: title, baseURL, and description. We can add more details if needed. The function that is exported is called by Eleventy and the object that is returned by this functions is available in the pages. If the environment variable ELEVENTY_URL is set, we use that as baseURL. Thus, the original baseURL is in that case overwritten.

11ty-serve.sh

rm -rf _site
export ELEVENTY_URL="http://`ifconfig en0 | grep inet | grep -v inet6 | awk '{print $2}'`:8080"
npx eleventy --serve --port 8080

First, we remove the old files generated by Eleventy. Strictly speaking this is not necessary, but I have noticed that removed files are not removed from _site, which might result in unexpected behaviour. Second, we extract the local IP address via ifconfig. Note that I have only tested this on macOS 10.12.6 and 10.14.4. Changes might be required for other OSs. Finally, we start Eleventy: we serve the website locally on port 8080.

Putting it all together

To get it all running, we put both files in our Eleventy project folder: site.js in the folder _data and 11ty-serve.sh in the root. Do not forget to make the script executable. Update both files where needed and run the script in the root folder.

----

If you have any questions or remarks, don’t hesitate to contact me via email or via Twitter.