How to use CSV data with Eleventy

I like to use spread­sheets as a CMS for one-off web­site pro­jects. This means I au­thor what­ever in­for­ma­tion I need in Google Sheets, ex­port it to a CSV file, and throw that file into a sta­tic site gen­er­a­tor to pro­duce the HTML pages I need.

Eleventy does­n’t have a built-in way to do that. It does have a con­cept of global data files, but those only sup­port json files out of the box. If you just throw your CSV into the _data folder, noth­ing hap­pens.

But there’s an­other fea­ture that does al­low us to do this: Javascript Data Files. Instead of a sta­tic JSON file, we can put a Javascript file into the data folder that exports what­ever data we need. Eleventy ex­e­cutes that file, and adds the out­put to its global data ob­ject, mak­ing it avail­able in tem­plate files.

We can use this to parse our CSV file, and hand the data over to Eleventy. I’m us­ing csv-parse here.

Install it with npm install csv-parse.

Then we can write a script like this:

const parse = require("csv-parse/lib/sync");
const fs = require("fs");

function readCSV() {
const input = fs.readFileSync("./_data/values.csv");
const records = parse(input, {
columns: true,
skip_empty_lines: true,
});
console.log(`${records.length} records found.`);
return records;
}

module.exports = function () {
const data = readCSV();
return data;
};

We’ll save that file as myData.js in­side the _data folder, next to our orig­i­nal CSV file. As with reg­u­lar data files, the file­name con­trols un­der which key the data will be avail­able. Once that’s done, we can write tem­plate code like this, and it works just as ex­pected:

{% for row in myData %}
{{ row.title }}
{% endfor %}

We could also use Eleventy’s pag­i­na­tion fea­ture to turn our data into in­di­vid­ual pages.

The idea that you can run ar­bi­trary Javascript pipe the re­sults right into Eleventy’s data ob­ject is pretty pow­er­ful. The doc­u­men­ta­tion gives ex­am­ples of fetch­ing data from an API and ex­pos­ing en­vi­ron­ment vari­ables, but you could also do cal­cu­la­tions, parse data in any for­mat, or any­thing else you could need.

Update

Five min­utes af­ter I wrote this, I re­alised that Eleventy has a built-in way to add sup­port for cus­tom data for­mats. Javascript data files are still the way to go if you’re fetch­ing data from an API or other do­ing other fanci­ness, but to read data from a CSV file adding this to your .eleventy file will do the trick:

eleventyConfig.addDataExtension("csv", (contents) => {
const records = parse(contents, {
columns: true,
skip_empty_lines: true,
});
return records;
});