bookstore :books:

Documentation Status Build Status CircleCI

bookstore :books: provides tooling and workflow recommendations for storing :cd: , scheduling :calendar:, and publishing :book: notebooks.

Note: Supports installation on Python 3.6 and above. Processes notebooks from Python 2 or Python 3.

Automatic Notebook Versioning

Every save of a notebook creates an immutable copy of the notebook on object storage.

To simplify implementation, we currently rely on S3 as the object store, using versioned buckets.

Storage Paths

All notebooks are archived to a single versioned S3 bucket with specific prefixes denoting the lifecycle of the notebook:

  • /workspace - where users edit
  • /published - public notebooks (to an organization)

Each notebook path is a namespace that an external service ties into the schedule. We archive off versions, keeping the path intact (until a user changes them).

Prefix Intent
/workspace/kylek/notebooks/mine.ipynb Notebook in “draft”
/published/kylek/notebooks/mine.ipynb Current published copy

Scheduled notebooks will also be referred to by the notebook key. In addition, we’ll need to be able to surface version IDs as well.

Transitioning to this Storage Plan

Since most people are on a regular filesystem, we’ll start with writing to the /workspace prefix as Archival Storage (writing on save using a post_save_hook for a Jupyter contents manager).


The bookstore publishing endpoint is a serverextension to the classic Jupyter server.

This means if you are developing this you will need to explicitly enable it to use the endpoint.

To do so you run: jupyter serverextension enable --py bookstore.

If you wish to enable it only for your current environment, run: jupyter serverextension enable --py bookstore --sys-prefix.


bookstore requires Python 3.6 or higher.

  1. Clone this repo.
  2. At the repo’s root, enter in the Terminal: python3 -m pip install . (Tip: don’t forget the dot at the end of the command)


# jupyter config
# At ~/.jupyter/ for user installs on macOS
# See for other places to plop this

from bookstore import BookstoreContentsArchiver

c.NotebookApp.contents_manager_class = BookstoreContentsArchiver

# All Bookstore settings are centralized on one config object so you don't have to configure it for each class
c.BookstoreSettings.workspace_prefix = "/workspace/kylek/notebooks"
c.BookstoreSettings.published_prefix = "/published/kylek/notebooks"

c.BookstoreSettings.s3_bucket = "<bucket-name>"

# Note: if bookstore is used from an EC2 instance with the right IAM role, you don't
# have to specify these
c.BookstoreSettings.s3_access_key_id = <AWS Access Key ID / IAM Access Key ID>
c.BookstoreSettings.s3_secret_access_key = <AWS Secret Access Key / IAM Secret Access Key>

Indices and tables