Skip to content

Instantly share code, notes, and snippets.

@matbrgz
Forked from MichaelCurrin/README.md
Created February 24, 2025 01:30
Show Gist options
  • Select an option

  • Save matbrgz/2c8db43d0ec3a9bd1670599a9e7039a8 to your computer and use it in GitHub Desktop.

Select an option

Save matbrgz/2c8db43d0ec3a9bd1670599a9e7039a8 to your computer and use it in GitHub Desktop.
Jekyll - how to build a REST API

Jekyll JSON API

How to make a read-only JSON REST API using Jekyll and some builtin templating features in Jekyll 3 or 4.

This is useful if you have content in your pages which you want to make available to an external service or a JavaScript single-page application that reads from your API backend.

The headers also get set correctly by using .json instead of .md or .html as the source files.

Content-Type	application/json

Resources

Taking it further

See also Data files in the Jekyll docs. You might iterate over data in a JSON or YAML file or files to build up output on a page. The data files are your database and then Jekyll builds your API. This is also a way to build a databse JSON file to be consumed on the frontend such as for search functionality.

Or you might store your data in the frontmatter of Jekyll Collections which get outputted as pages similar to the Page example below. That way you can group your JSON data into collections as interate over them easily.

Page

  • _layouts/page.html - build up the JSON object, quoting all values and in the case of the body text we convert from markdown to HTML.
    ---
    layout: none
    ---
    {"title":{{ page.title | jsonify }},"content":{{ page.body | markdownify | jsonify }},"links":{{ page.links | jsonify }}}
  • foo.json - a Jekyll HTML/markdown page with a .json extension.
    ---
    layout: page
    title: Foo
    body: |
      Hello, **world**.
      I am here.
      
    links:
      - title: Go track on Exercism
        url: https://exercism.io/tracks/go
    
      - title: Go tour  welcome page
        url: https://tour.golang.org/welcome/1
    
      - title: Learn Go with Tests
        url: https://quii.gitbook.io/learn-go-with-tests/
    
      - title: Go for Python programmers
        url: https://golang-for-python-programmers.readthedocs.io/en/latest/index.html
    ---

Output file

Visit at http://localhost:4000/foo.json

{"title":"Testing","content":"<p>Hello, <strong>world</strong>.\nI am here.</p>\n","links":[{"title":"Go track on Exercism","url":"https://exercism.io/tracks/go"},{"title":"Go tour  welcome page","url":"https://tour.golang.org/welcome/1"},{"title":"Learn Go with Tests","url":"https://quii.gitbook.io/learn-go-with-tests/"},{"title":"Go for Python programmers","url":"https://golang-for-python-programmers.readthedocs.io/en/latest/index.html"}]}

Here it is in a more readable format:

{
  "title":"Testing",
  "content":"<p>Hello, <strong>world</strong>.\nI am here.</p>\n",
  "links": [
    {"title":"Go track on Exercism","url":"https://exercism.io/tracks/go"},
    {"title":"Go tour  welcome page","url":"https://tour.golang.org/welcome/1"},
    {"title":"Learn Go with Tests","url":"https://quii.gitbook.io/learn-go-with-tests/"},
    {"title":"Go for Python programmers","url":"https://golang-for-python-programmers.readthedocs.io/en/latest/index.html"}
  ]
}

Post

Input file

Here we make a post in the usual _posts directory.

The layout is also much lighter and more flexible - using the data object without caring about keys, values and formatting.

The downside is that you have to be more verbose in your post frontmatter to define a YAML variable with & and then use it with *. Based on this YAML tutorial.

Also note unlike in the page example above, we don't covert to body content from markdown to HTML.

  • _layouts/post.html - a layout which uses frontmatter and converts it to JSON output.
    ---
    layout: none
    ---
    {{ page.data | jsonify }}
  • _posts/2020-12-12-hello.json - a post with a .jsonextension.
    ---
    layout: post
    
    title: &title Hello world
    categories: &categories
      - Go
      - Python
    content: &content |
      Hello, **world**
      I am here
    
    data:
      title: *title
      categories: *categories
      content: *content
    ---

Output file

Visit at http://localhost:4000/go/python/2020/12/12/hello.json

{"title":"Hello world","categories":["Go","Python"],"content":"Hello, **world**\nI am here\n"}

Post listing

If you want to make as summary of all your posts.

Input file

  • posts.json
    ---
    layout: none
    permalink: /posts/
    ---
    [
    {%- for post in site.posts %}
        {
        "title": {{ post.title | jsonify }},
        "date": {{ post.date | jsonify }},
        "url": {{ post.url | jsonify}}
        }
    {% endfor -%}
    ]

You can change out site.posts for site.pages if you want to list your all pages. You can do something similar with site.my-collection.

If you mix your posts as HTML and JSON, you can add a filter to get only JSON files - {% if post.ext == '.json' %}. This works for posts only. For pages, you'll have to use item.name (e.g. foo.md) and check if it ends with .json.

Output file

  • /posts/
    [
        {
        "title": "Hello world",
        "date": "2020-12-12 00:00:00 +0200",
        "url": "/go/python/2020/12/12/hello.json"
        },
        // more posts...
    ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment