This website contains a variety of interactive content like my energy usage calculator which I can create easily and host for free. In this post I explain how the it all works.

Observable notebooks

I use Observable Notebooks as the authoring environment for interactive content. This is my favourite programming environment because it allows me to maximise the time I spend on the fun part of programming.

This allows readers to not only view the code behind each page (including this one!), but also to live-edit it and fork it. On the Observable Notebooks homepage, you can see that the ability to reuse, re-mix and iterate leads to an amazing amount of creativity.

I then use gatsby.js to build my notebooks into a website.

The idea is that you end up with the best of all worlds: A fun, simple authoring environment with unlimited power for interactivity, which can be hosted for free on a static web host like Github pages.

What follows are a few notes about how I got everything working. If you’d rather jump straight into the code, you can find a minimal, working template here, and the code for my blog is here.

Gastby.js as a site generator

Gatsby js is a modern website generator that uses the React framework. Javascript modules can be installed as dependencies, and used within pages on your website.

This is a good fit because each Observable notebook can be compiled and downloaded as a JavaScript module - see here - and so can be installed and made available as a part of a Gatsby site.

Rendering notebooks in gatsby

I use a React component to display each Observable notebook within a div - see here for the implementation.

I then have an page component that serves as a default layout for each page on my website which contains a notebook.

Each notebook is a standard gatsby page which imports the Observable notebook, and then passes it to the page component. Here’s an example. output_order allows the author to control which cells are displayed and in what order.

For a long time I experimented with the idea of loading all notebooks from a json file, and then using createPage (e.g. like this to create the pages, rather than needing a separate jsx page for each notebook. The json would look like this:

[
    {   "page_path": "page1",
        "observable_note_name": "gatsby-test"
    },
    {
        "page_path": "page2",
        "observable_note_name": "gatsby-test-2",
        "output_order": ["cell1", "cell2"]
    }
]

I now don’t think this is possible, because of the way webpack works. See here.

Continuous deployment

I use Github actions for continuous deployment. Specifically, any commits merged into dev trigger a workflow which builds the site, and pushes it to master, thus making it available as a github page.

You can see the action here. Note you will need to generate a secret containing a Github PAT and add it to your repo’s secrets. The enables the workflow to commit code back to your repo.

Authoring workflow

Once all this is set up, the authoring process is very simple:

Step 1 - author your notebook and get the link

Write an observable notebook, and publish it. Click the ‘download code’ button to get a link to the javascript module. In the case of this post, the link to the code is https://api.observablehq.com/@robinl/interactive-blogging-with-observable-notebooks-and-gatsb.tgz?v=3.

Step 2 - yarn add the notebook to gatsby

yarn add https://api.observablehq.com/@robinl/interactive-blogging-with-observable-notebooks-and-gatsb.tgz?v=3

Step 3 - create a new page

import define from "@robinl/interactive-blogging-with-observable-notebooks-and-gatsb"
import ObservablePage from "../components/obs_page"

export default ({ data }) => (
    ObservablePage(define)
)

That’s it!

To update a page is even easier - you just retrieve the version number of the notebook from ‘history’ page with the Observable notebook, and manually update the yarn.lock file with the new version number. See here for an example.

You can find an example of all the code you need to add a page here, which is the pull request that created the page you’re reading right now!

mdx

Another good option within the gatsby ecosystem for authoring interactive pages is mdx. This is an excellent choice if you want to, for instance, write a blog post in markdown like this but add a vega lite chart.

You can find an example of a component that renders mdx here, an mdx page that includes a vega lite chart here and a pull request that adds code syntax highlighting for these pages here.