DEV Community

loading...

Creating JSON Files with Eleventy

Matt Waler
Overly generous lover of pragmatic front-end development. In my off-time, you'll find me lifting, eating, and playing chess.
・2 min read

TLDR: Here is a nifty way to export 11ty data to JSON so it can be consumed on the client side!

In 11ty, you are able to customize the filetype of the exported template just by appending any filetype to the permalink field.

In the following example, I am looping over a pretend posts collection inside 11ty to build a JSON file of data.

---
permalink: /api/posts.json
---
[
  {% for post in collections.posts  %}
    {% set data = post.data %}
    {
      "title": "{{ data.title }}",
      "description": "{{ data.description }}",
      "url": "{{ post.url }}"
    }{{ '' if loop.last else ',' }}
  {% endfor  %}
]
Enter fullscreen mode Exit fullscreen mode

This template will output the following JSON file.

[
  {
    "title": "Fake Post 1",
    "description": "Quis platea ut dolor dictumst felis",
    "url": "/posts/1/"
  },
  {
    "title": "Fake Post 2",
    "description": "Quis platea ut dolor dictumst felis",
    "url": "/posts/2/"
  },
  {
    "title": "Fake Post 3",
    "description": "Quis platea ut dolor dictumst felis",
    "url": "/posts/3/"
  }
]
Enter fullscreen mode Exit fullscreen mode

With this data now exported to a file in your site, you could consume it with a library like axios (or fetch if you're hardcore) in order to build out functionalities like search and sorting/filtering with a library like Svelte!

Here is how you would now access your new JSON file.

import axios from 'axios'
async function getPosts() {
  const { data } = await axios.get('/api/posts.json')
  return data
}
Enter fullscreen mode Exit fullscreen mode

Note! You can also configure all files in a directory to output to JSON by adding a directory data file. That file can look something like this:

// File: /pages/api/api.11tydata.js
module.exports = {
  permalink: '/api/{{ page.fileSlug }}.json',
}
Enter fullscreen mode Exit fullscreen mode

This will automatically export any templates inside this directory straight to JSON!

Eleventy is a fantastic platform and it has the potential to exceed traditional static site generation to include data files that can be consumed and made more dynamic on your site!

Discussion (12)

Collapse
davidrhoden profile image
David Rhoden

This works quite nicely except the quote marks are getting translated to their HTML equivalents and HTML tags are added, like this:
&quot;title&quot;: &quot;My Post Title&quot;,<br>

Might be related to this Eleventy issue:
github.com/11ty/eleventy/issues/402

Do you know how to make it stop doing that?

Collapse
davidrhoden profile image
David Rhoden

I solved it. i had made the template as a Markdown (.md) file, like the rest of my templates. I changed the suffix to .html and got the output I was looking for.

Collapse
mattwaler profile image
Matt Waler Author

Awesome! I was going to come back to this and help debug because I've never witnessed that same issue. Glad you figured it out and thank you for reading!

Collapse
makingthings profile image
James Grubb

Hi thanks for this, sorry Im late to this party. Would you mind expanding a little when you suggest "With this data now exported to a file in your site, you could consume it with a library like axios (or fetch if you're hardcore) in order to build out functionalities like search and sorting/filtering with a library like Svelte!"
Do you mean using it as an API for another site or using the data within the existing eleventy.js site? Thanks in advance.

Collapse
mattwaler profile image
Matt Waler Author

In my example, I was referring to using the data on the same site. So, you could hit your new data route with axios or fetch, and use that JSON to power something like a real time search/filter on your blog listing page, possibly with a library like Fuse.js!

Collapse
makingthings profile image
James Grubb

Thank you for the clarification :)

Collapse
gndclouds profile image
William Felker • Edited

Thanks for the great example. Is there a way to pass HTML or markdown from the json into the build?

for example:

 {
    "title": "Fake Post 3",
    "description": "Quis platea ut dolor [some link](HTTP://example.com) felis",
    "url": "/posts/3/"
  }
Enter fullscreen mode Exit fullscreen mode
Collapse
mattwaler profile image
Matt Waler Author

That data is already available to the build! You would get this data via a loop in collections.posts or the like.

Collapse
zulvkr profile image
zulvkr

Nice post.

I did this long ago with custom JSON.stringify() 11ty filter. The code is very clean, but it will print all posts object properties.

{{ collections.posts | JSONstringify | safe}}
Enter fullscreen mode Exit fullscreen mode

As a solution, maybe make another 11ty filter to filter the object, or combine it with this post approach to print only specific data.

I also inline the JSON as object within <script> tag since the data is specific to a page, this way no need for additional api call.

Collapse
mattwaler profile image
Matt Waler Author

This is super clever!

Collapse
ben profile image
Ben Halpern

Nice writeup

Collapse
mattwaler profile image
Matt Waler Author

Thank you so much Ben!