Message Boards Message Boards

Self-hosting notebooks using WolframNotebookEmbedder and Docusaurus

Introduction

The Wolfram Community site allows users to add an interactive notebook to their post, which seems to me to be using the WolframNotebookEmbedder library in the back-end. Similarly, various books published by Wolfram Media such as the Wolfram physics project allow for indexed interactive (notably "Copy to clipboard" functionality) notebooks with a nice sidebar. This is particularly nice for books/teaching when one would like to organize content in chapters/sub-chapters.

What follows is a short tutorial on how one can self-host one such 'documentation' website using the WolframNotebookEmbedder and Docusaurus, a powerful documentation site generator which uses React.

By the end of this tutorial, you should be able to self-host sites like this one here:

enter image description here

Note the (nested) sidebar on the left, and navigation links to previous/next pages.

Github Repository

We'll host our notebooks using Github pages, since it's free and simple to set up. If you're not familiar with git, see instructions here on how to set up a new github repository. In what follows, you'll see references to gvarnavi/self-hosting-wl-notebooks which you should replace with <your-github-username>/<your-repository-name>.

Note: the are other free self-hosting options, some of the ones supported by Docusaurus are listed here.

Cloud Notebooks

Let's create a local directory inside our repository with some dummy notebooks we'll be using for content. I made three notebooks called 1.static-content.nb , 2.dynamic-content.nb, and 3.external-content.nb inside a dummy-content/ directory, which you can see here. The naming, location, and content is not very important - we just need notebooks accessible on the public cloud. I copied the local directory to the cloud using the following snippet

CopyDirectory[
  "/home/george/Documents/git-repos/self-hosting-wl-notebooks/dummy-content", 
CloudObject["dummy-content",Permissions->"Public"]];

Docusaurus

I'll be building this on a unix machine, but you should be able to follow installation instructions here for other platforms.

  • Requirements: Node.js >= 12.13.0 and Yarn >= 1.5

  • Initialize a Docusaurus site with the classic theme template, and change directory into the new website directory

    npm init docusaurus@latest website classic
    cd website
    
  • Add wolfram-notebook-embedder library as a dependency

    yarn upgrade @docusaurus/core@latest @docusaurus/preset-classic@latest
    yarn add wolfram-notebook-embedder
    

At this point, you can peruse the default site that Docusaurus makes by runing yarn start and navigating to http://localhost:3000/ on your browser. The default site ships with a landing page and blog-functionality, we'll strip away a lot of these features to only keep the documentation (but they are of-course easy to add).

  • Remove blog, landing page, and template docs

    rm -rf ./blog/
    rm ./src/components/* ./src/pages/*
    rm -rf ./docs/*
    
  • Add the following file to a new file called ./docs/landing-page.md. The important thing here is to set slug: / in the front-matter.

  • Edit the docusaurus.config.js file to something like this configuration file. The important settings are:

    # under presets
    blog: false,
    docs: {routeBasePath: '/',}
    
    # under themeConfig, items
    docId:"landing-page"
    

and that you change my github repo settings with yours.

  • At this point, you should hopefully be able to run yarn start and see something similar to this landing page

Docusaurus has a lot of features, and an excellent documentation so I would suggest perusing that.

Wolfram Notebook Embedder

Docusaurus has built-in support for MDX, which allows you to embed Javascipt inside markdown files and render them as React components. We'll make use of this to embed our notebooks from the cloud!

First, we need to create a WolframEmbedder component. Copy the following into a file called ./src/components/WolframEmbedder.js

    import React from 'react';
    import * as WolframNotebookEmbedder from 'wolfram-notebook-embedder';

    class NotebookEmbed extends React.Component {

      componentDidMount() {
        this.embedding=WolframNotebookEmbedder.embed(
            this.props.url, 
            this.el,
            {
               allowInteract:true,
               showRenderProgress: true

            }
        );
      }

      componentWillUnmount() {
        this.embedding.then(nb => nb.detach());
      }

      render() {
        return <div className="NotebookEmbed" ref={el => this.el = el} />;
      }
    }

    export default NotebookEmbed;

This will create a reusable React component we can call with a single argument specifying the cloud notebook's url.

We can then make additional documentation pages which mix markdown and calls to the WolframNotebookEmbedder, e.g. like so:

---
id: static-content
sidebar_position: 1
title: Static Content
hide_title: true
---

import NotebookEmbed from '@site/src/components//WolframEmbedder.js'

## Static Content

<NotebookEmbed url='https://www.wolframcloud.com/obj/gvarnavi/dummy-content/1.static-content.nb'/>

Where I'm embedding the 1.static-content.nb notebook found here.

The example site here has the following directory structure under docs

docs
├── content
│   ├── _category_.json
│   ├── dynamic-content.mdx
│   └── static-content.mdx
├── external-content.mdx
└── landing-page.md

Note the ending .mdx for files which include calls to the WolframNotebookEmbedder. You can see the contents of all the files here.

Deployment

If everything works as expected locally, it's very easy to deploy your site to github pages.

  • First, build production-quality static files by running

    yarn run build
    
  • If this works, and your github repo settings in the config file are set correctly you can simply run:

    GIT_USER=<GITHUB_USERNAME> yarn deploy
    

and then head to your repo's Page settings to see it's hopefully deployed! (e.g. for my configurations the settings would be here https://github.com/gvarnavi/self-hosting-wl-notebooks/settings/pages, note this page should not be accessible to you).

Thoughts

This seemed like a relatively straight-forward way to self-host wolfram notebooks in a flexible framework which provides many documentation features, specifically the ease of markdown and React components - hopefully it's useful to some!

3 Replies
Posted 2 years ago

Hi George,

This is very nice! Thanks for sharing. +1.

You can use the Permissions -> "Public" option to CloudObject to avoid having to save/restore $Permissions. Or use Block to scope the change

Block[{$Permissions = "Public"},
...
]
POSTED BY: Rohit Namjoshi

Thanks! Edited posted to reflect this.

enter image description here -- you have earned Featured Contributor Badge enter image description here Your exceptional post has been selected for our editorial column Staff Picks http://wolfr.am/StaffPicks and Your Profile is now distinguished by a Featured Contributor Badge and is displayed on the Featured Contributor Board. Thank you!

POSTED BY: Moderation Team
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract