Eleventy - Add CSV data file support

A file with the label 'CSV' and an excel-like table as its content is in the center of the frame. It is cast againt a soft purple background with the eleventy possum floating beside it on a balloon.

It would be cool to be able to drop a CSV (Comma-separated values) file into a project and use it in a page. CSV is the most common export file format for spreadsheets and databases, you may need to work with one sometime soon!

My motivation was to show bookshelves from my library database. 📚

Currently reading page
A 'currently reading' bookshelf listing the books that I am currently reading. The source is a CSV export from the Calibre app.

How do you work with CSV files in Eleventy?

TLDR

Out of the box, Eleventy does not support CSV files. You will need to register it as a data file format. Eleventy has a built-in way to do this through the eleventyConfig.addDataExtension() function.

I will use the csv-parse library for parsing the CSV data and transforming it to an array of JavaScript objects. Here how you set it up in your eleventy config:

Javascript
// eleventy.config.js

const { parse } = require("csv-parse/sync");

module.exports = function (config) {
config.addDataExtension("csv", (contents) => {
const records = parse(contents, {
columns: true,
skip_empty_lines: true,
relax_column_count: true,
delimiter: ";",
trim: true,
});

return records;
});

// more config
};

Now when you drop a CSV file into the project’s data folder, it will be transformed into a collection.

If you want to know more about the options used for the csv-parse library, you can read the Add CSV support section below.

My use case - Add a bookshelf to an eleventy site

I want to show my “currently reading” bookshelf. I can export the data as a CSV from the Calibre e-book management app that I use to manage my e-book libary.

Calibre e-book management app showing my library filtering by currently reading

This is the outline of the project folder.

.
├── _data
│   └── reading.csv
├── eleventy.config.js
├── _includes
│   ├── layouts
│   │   ├── base.njk
├── index.njk
├── reading.njk
└── style.css

The CSV data file - reading.csv

I can run the following command to create an export of my “currently reading” books with the isbn, authors, and title fields from Calibre:

Shell
calibredb list --fields=isbn,authors,title 
--sort-by=title --ascending
--line-width 700 --separator=";"
--search "#currently_reading:true" > reading.csv;

It produces the following CSV file:

CSV
id  ;isbn         ;authors                                                                                                                                                ;title                                                                                                                                             ;
9293;9781101160664;Wilfred Thesiger ;Arabian Sands
1959;9780553898194;Neal Stephenson ;Snow Crash
8766;9780544272996;Randall Munroe ;What If?: Serious Scientific Answers to Absurd Hypothetical Questions

I choose to use the semi-colon as the delimiter. There can be commas in the title field, so choosing another delimiter can prevent parsing issues. You could go for a more obscure character to make even more unlikely if you wish!

One of the limitations of the export function from Calibre is that if the width of field is long, it can force a record to be written over multiple lines. This is troublesome for parsing. I choose a large number for the line-width option to ensure this does not happen, but it results in a lot of whitespace around the data.

Add CSV support in the eleventy config file - eleventy.config.js

I will use the csv-parse library for parsing the CSV data and transforming it to an array of JavaScript objects.

Install the package from npm with your package manager of choice e.g. npm install csv-parse, and require/import it in your eleventy config.

Through the config.addDataExtension() function we can register the csv file extension as a data type. We can access the file content through the contents parameter.

I will use the parse function from the sync API of parse-csv. You can customise the parsing behaviour through the options object which can be provided as the second parameter (it is optional).

This is what I did to fit my use case:

Javascript
// eleventy.config.js

const { parse } = require("csv-parse/sync");

module.exports = function (config) {
config.addDataExtension("csv", (contents) => {
const records = parse(contents, {
columns: true,
skip_empty_lines: true,
relax_column_count: true,
delimiter: ";",
trim: true,
});

return records;
});

// more config
};

I choose the following options to fit my data and make parsing more accepting of variable data:

Use the CSV data in a nunjucks template - reading.njk

We can use a reading variable for our collection of “currently reading” books. Here I loop through the collection to generate an ordered list of books.

Nunjucks
<section class="reading">
<ol>
{% for book in reading %}
<li class="book">
<h2 title="{{ book.title }}">{{ book.title }}</h2>
<img class="cover" src="https://covers.openlibrary.org/b/isbn/{{ book.isbn }}-M.jpg" />
<span class="author"> {{ book.authors }}</span>
</li>
{% endfor %}
</ol>
</section>

This produces this page:

A 'currently reading' bookshelf listing the books that I am currently reading. It lists 3 books: Snow Crash, What If, and Arabian Sands. Each book is shown with a title, a cover image, and the author names

I use the Open Library Covers API to get a book cover image programaticaly. Open Library offers a URL pattern that you can use in the src of an img to access book covers using the ISBN (or other keys such as OCLC, LCCN, OLID). This is a simple way to grab covers, you may want a more rigorous method if you are adding the same thing to your website.

Source code

The source code is available in this GitHub repo – https://github.com/robole/eleventy-tutorials. You can find it as an independent project in the csv folder.

Can you give the repo a star to indicate that this was a worthwhile tutorial please? 🌟

Conclusion

There are plenty of scenarios where you may want to work with a CSV file in eleventy. It is handy to be able to drop a CSV file into an eleventy project and use in a page in some form. My motivation was to be able to show bookshelves from my digital library database.

Out of the box, Eleventy does not support the CSV file format. However it does not take much work to add it as a data file format. I hope this tutorial got you up and running faster! 🚀

Thanks for reading! 😊

Tagged