Do you want to Create a Jupyter-Book Website From Scratch?

Original article was published on Artificial Intelligence on Medium

What do you need to begin

As a minimum, you need these things:

That’s it. Technically, if you look at the jupyter-book documentation, you’ll see that there other things that would be nice to have beforehand, like a configuration file (i.e., _config.yml) and a table of contents file (i.e., toc.yml). However, those files are not strictly necessary to begin your project, so we will restrict ourselves to the bare minimum: some content you want to put on-line.

Creating the book, step-by-step

Now, we will create the book using the command line, step-by-step.

Step 1: Create a directory for the book

Open the terminal and navigate to your Desktop by:

cd Desktop/

Now, let’s create a directory for the project

mkdir my-book-files mkdir my-book-files/notebooks

Copy and paste your Jupyter Notebooks to the my-book-files/notebooks/ folder

Step 2: Create and activate a virtual environment

It is always a good idea to create a virtual environment to isolate your dependencies for each project. This is not strictly required, yet highly recommended. Make sure you are in the Desktop directory in your terminal and move to the project directory:

# move to terminal to the project directorycd my-book-files/

Once there, run this in the terminal to create the virtual environment:

# This line creates a virtual environment called 'venv'python3 -m venv venv # This line activates the virtual environment source venv/bin/activate

Once the virtual environment is activated, packages will be installed in that environment, without interfering with your python system installation.

HEADS UP: if you close the terminal or deactivate venv, make sure to re-activate the virtual environment with source venv/bin/activate before typing any code.

Step 3: install jupyter-book package

The jupyter-book package can be pip-installed like this:

pip install jupyter-book

Now, if you run:

pip list | grep jupyter-book

You should see something like this (version may change) printed to the terminal:

jupyter-book 0.6.4

Step 4: create a jupyter-book template

The whole point of jupyter-book is to provide a template that will make creating your book-site fast and easy. A template for your book can be created by running:

jupyter-book create my-book

If correctly created, the (last part of the) output should look similar to this:

================================================================================Finished creating a new book at ./my-book- Your content is in ./my-book/content - A Table of Contents file is at ./my-book/_data/toc.yml. You should check its contents, make sure it references your content correctly, and ensure it has the correct order.- Your configuration file is at ./my-book/_config.yml. You should check its contents and double-check that the values are correct for your site.Notes=====- Add your own content to your book. You haven't provided any content (--content-folder) so we've added a couple files to get you started.- We've added a CC-BY-SA license for you in ./my-book/content/LICENSE.md This is a reasonable license for most book content, though feel free to change it if you like!================================================================================

Step 5: remove the files in the my-book/contents/ directory

The contents/ folder in the my-book/ folder is the one containing the files and structure that will be used by the jupyter-book package to build your site. As it now, it contains a few demo-files. Let’s remove those files to then replace them with your content.

Assuming that you are in my-book-files/ directory, type this to remove the demo-files:

# remove .ipynb and .md filesrm my-book/content/features/*# remove unnecesary imagesrm -r my-book/content/images/*# remove introrm my-book/content/intro.md

Now, type this to look at the directory contents:

# list directory with subdirectoriesls -lR my-book/content/

And the output should look similar to:

my-book/content/:total 12drwxr-xr-x 2 pablo pablo 4096 Feb 10 17:09 featuresdrwxr-xr-x 2 pablo pablo 4096 Feb 10 17:10 images-rwxr-xr-x 1 pablo pablo 257 Feb 10 16:19 LICENSE.mdmy-book/content/features:total 0my-book/content/images:total 0

This indicates that my-book/content/ contains the feature/ directory, an images/ directory, and a LICENSE.md file. I keep the license file because it is a standard practice to have an open-source license for every project. If that doesn’t work for you, just change the contents of the license as you need.

Step 6: add your contents to the my-book/contents/ directory

Again, assuming you are in the my-book-files/ directory in the terminal and that your content is in the my-book-files/notebooks/. Type this to incorporate your files into the book:

cp -a notebook/* my-book/content/features/

This will recursively copy the contents of your notebook/ directory into the my-book/content/features/ directory.

Note about images: if you have images linked to your notebooks, this is what you need to do:

• Make sure that the images are linked to your notebook by a relative path linked to the images/ folder. The file structure should look like this:
• my-book-files/notebooks/notebook-with-the-linked-image.ipynb my-book-files/images/image-linked-to-notebook.png
• Now, if you have images, type this to pass the images into the book images folder:
• cp -a images/* my-book/content/images/And you are done.

• If you have some sort of introduction to your notebooks, let’s say, an intro.md file, you just need to repeat the process of copying the file to the my-book/content/ directory:
• cp intro.md my-book/content/

Assuming that you have a notebooks/ directory, an images/ directory, and an about.md file, your my-book/content/ directory should look like this now:

# list directory with subdirectoriesls -lR my-book/content/# output printed to the terminalmy-book/content/:total 12-rw-r--r-- 1 pablo pablo 0 Feb 10 17:37 intro.mddrwxr-xr-x 2 pablo pablo 4096 Feb 10 17:24 featuresdrwxr-xr-x 2 pablo pablo 4096 Feb 10 17:37 images-rwxr-xr-x 1 pablo pablo 257 Feb 10 16:19 LICENSE.mdmy-book/content/features:total 124-rw-r--r-- 1 pablo pablo 34958 Feb 7 10:24 01-notebook.ipynb-rw-r--r-- 1 pablo pablo 10221 Feb 7 10:54 02-notebook.ipynb-rw-r--r-- 1 pablo pablo 74105 Feb 7 10:24 03-notebook.ipynbmy-book/content/images:total 0-rw-r--r-- 1 pablo pablo 0 Feb 10 17:37 image1.png-rw-r--r-- 1 pablo pablo 0 Feb 10 17:37 image2.png

Now that you have your contents in place, you need a table of contents to match that. The table of contents is the my-book/_data in the toc.yml file. You have two options for this: to modify the existing toc.yml file to match the contents or to create a new one from scratch. The existing one has too much info to absorb, so I’ll create a new one to explain each component. Feel free to use tour favorite text editor to edit the file

# create an empty toc.yml file touch toc.yml# open the file in nano / or use whatever you likenano toc.yml

From the jupyter-book documentation, we know that each toc.yml has the following schema:

# - title: mytitle # Title of chapter or section# url: /myurl # URL of section relative to the /content/ folder.# sections: # Contains a list of more entries that make up the chapter's sections# not_numbered: true # if the section shouldn't have a number in the sidebar# (e.g. Introduction or appendices)# expand_sections: true # if you'd like the sections of this chapter to always# be expanded in the sidebar.# external: true # Whether the URL is an external link or points to content in the book## Below are some special values that trigger specific behavior:# - search: true # Will provide a link to a search page# - divider: true # Will insert a divider in the sidebar# - header: My Header # Will insert a header with no link in the sidebar

Next, let’s populate the file with a few elements. Remember that the path to the files are relative to the contents/ directory

• each .md and .ipynb file has to have some content in it. Also remember to add a top header (with # My title), since it will be used as the title to the section on the website.
• Remember to omit the file extension ( .md and .ipynb ) when passing the URL
# add the top header - header: My Jupyter Book# add the 'about.md' section at the top - url: /intro not_numbered: true# ad a divider: a divider is just a black line separating sections. It is just aesthetics.- divider: true# add a second header- header: Contents# add the first notebook- url: /features/01-notebook not_numbered: true# add the second notebook- url: /features/02-notebook not_numbered: true# add the third notebook- url: /features/03-notebook not_numbered: true# another divider- divider: true# add the LICENSE - url: /LICENSE not_numbered: true

Now, let’s remove the old toc.yml file and past the new one:

rm my-book/_data/toc.yml cp toc.yml my-book/_data/

Step 8: add a requirements.txt file

Chances are that you are using some python package for your analysis. If so, you’ll need to create a requirements.txt file containing the package names and versions for your project:

# create an empty toc.yml file touch requirements.txt# open the file in nanonano requirements.txt

Then, populate your requirements.txt with your dependencies. For instance, in my case they look like this:

altair==4.0.1numpy==1.18.1matplotlib==3.1.2pandas==0.25.2jupyterlab==1.2.5keras==2.3.1vega_datasets

Note that if you just want the latest version of the package to be used, you can omit the ==version-number part (as in the vega_datasets), and just pass the package name. This is not recommended because future releases of the package may break your code functionality. The best is just to figure out the exact package versions you are using. One way is to type pip list (assuming you are using pip) or conda list (if you are using conda) in the terminal, in the directory and environment where you ran your code.

Now, let’s remove the old requirements.txt file and past the new one:

rm my-book/requirements.txtcp requirements.txt my-book/

Step 9: create a GitHub account and a repository for the project

If you have a GitHub account already, you may be tempted to use your existing account to deploy your project. This may not be a good idea because that may interfere with your ability to use your GitHub account to deploy something more personal in the future, like a resume page or a blog. Also, if you are using GitHub pages already, deploying the site without messing up with your existing website may be tricky. Therefore, it is highly recommended to create a GitHub account for the project. You’ll need an email account not associated with an existing GitHub account. With that, you can go to https://github.com/ and follow the Sing Up instructions.

Once you are ready with your new account, create a new empty repository for the project. This is, no README, no LICENSE, no .gitignore. Just empty. Normally, GitHub should prompt you to create a new repo when you verify your email account. If you created one, you can use that one for the next steps. Otherwise, follow steps 1 through 6 in the instructions here https://help.github.com/en/github/getting-started-with-github/create-a-repo

You can name your repo as you like, but let’s assume that you name it my-book-site/. Now we need to connect the on-line repo with your machine. This time, make sure you are in your local my-book/ directory, and follow these instructions:

# navigate to the book directorycd my-book# initialize trackinggit init

The terminal should print back a message like this

Initialized empty Git repository in /home/YOUR-USERNAME/Desktop/my-book-files/my-book/.git/

Next, stage the files to be committed

# stage the files to be commitedgit add -A

Now you need to commit the files that will be pushed to GitHub. Depending on your git configuration, the terminal may prompt you to enter your user.email and user.name. Use your newly created GitHub email and username for this, omitting the --global option (if you set up this globally, it may generate problems for you later on).

# commit the files to be pushedgit commit -m "First commit"# assuming it ask your for "*** Please tell me who you are"git config user.email "your.ney.email@gmail.com"git config user.name "your-new-github-username"# repeat the commit if necessarygit commit -m "First commit"

Next, connect your new GitHub repo with your local directory. You can get the URL of your repo in the repo home-page bellow “Quick setup — if you’ve done this kind of thing before

# here, replace <your-github-username> with your real username # also replace <my-book-site> with the name you gave to your repogit remote add origin https://github.com/your-github-username/my-book-site.git

Finally, you need to push your local files to the GitHub repo. Notice that git should prompt you to enter your username and password. Use your newly created ones for the project:

# push the filesgit push origin master# If git prompts you:Username for 'https://github.com': your-github-usernamePassword for 'https://my-first-jupyter-book@github.com': your-password

Step 10: create a _config.yml configuration file

The last file we need to add is the _config.yml file. Again, one option is just to edit the exiting _config.yml file in the my-book/ directory. I’ll fill in this step-by-step, again, just for the sake of explaining in detail what are you doing here:

# if you were at the my-book/ directory, go back to the my-book-files/ directorycd ..# create a new _config.yml filetouch _config.yml# open it in your favorite edito, I'll use nanonano _config.yml

This may look long and complicated, but it is not. You just need to copy-paste everything to your _config.yml and change a couple of lines that I’ll flag for you with capitals as #@@@ CHANGE THIS - number @@@#. To make sure you don’t miss any, I numbered the changes from 1 to 9.

####################### Jekyll site settings######################title: my-first-jupyter-book #@@@ CHANGE THIS -1 @@@#author: Pablo Caceres #@@@ CHANGE THIS -2 @@@#email: my.first.jupyter.book@gmail.com #@@@ CHANGE THIS -3 @@@#description: >- # this means to ignore newlines until "baseurl:" My brand new book #@@@ CHANGE THIS - 4 @@@## the name of your GitHub Repo. # If there is no subpath for your site, use an empty string "" baseurl: "/my-book-site" #@@@ CHANGE THIS -5 @@@## the base hostname & protocol for your site. # Since we are deloying on GitHub pages, the URL has the format:# "https://your-github-username.github.io/" # In my case is:url: "https://my-first-jupyter-book.github.io/" #@@@ CHANGE THIS - 6 @@@######################### Jupyter Book settings######################## Main page settings# Optional: you can replace with <https://github.com/my-first-jupyter-book/my-book-site> your repo URLfooter_text : View source repository at <a href="https://github.com/my-first-jupyter-book/my-book-site"></a> #@@@ CHANGE THIS - 7 @@@## Sidebar settingsshow_sidebar : true # Show the sidebar. Only set to false if your only wish to host a single page.collapse_inactive_chapters: true # Whether to collapse the inactive chapters in the sidebarcollapse_inactive_sections: true # Whether to collapse the sub-sections within a non-active section in the sidebar#textbook_logo : images/logo/logo.png # A logo to be displayed at the top of your textbook sidebar. Should be square#textbook_logo_link : https://jupyterbook.org/intro.html # A link for the logo.sidebar_footer_text : 'Powered by <a href="https://jupyterbook.org">Jupyter Book</a>'number_toc_chapters : true # Whether to add numbers to chapterse in your Table of Contents. If true, you can control this at the Chapter level in _data/toc.yml# Search settingssearch_max_words_in_content : 100 # In the search function, use at most this many words (too many words will make search slow)# Controlling page informationpage_titles : infer # Either None, infer, or tocpage_authors : None # Either None or inferfilename_title_split_character : '_' # If inferring titles based on filename, splt on this character.# Math settingsnumber_equations : false # Whether to automatically number all block equations with MathJax######################### Interact link settings######################### General interact settingsuse_jupyterlab : false # If 'true', interact links will use JupyterLab as the interface# Jupyterhub link settingsuse_jupyterhub_button : false # If 'true', display a button that will direct users to a JupyterHub (that you provide)jupyterhub_url : "" # The URL for your JupyterHub. If no URL, use ""jupyterhub_interact_text : "Interact" # The text that interact buttons will contain.# Binder link settingsuse_binder_button : true # If 'true', add a binder button for interactive linksbinderhub_url : https://mybinder.org # The URL for your BinderHub. If no URL, use ""binder_repo_base : https://github.com/my-first-jupyter-book/my-book-site #@@@ CHANGE THIS @@@ -8 # # The site on which the textbook repository is hostedbinder_repo_org : my-first-jupyter-book #@@@ CHANGE THIS @@@ - 9# # Your GitHub usernamebinder_repo_name : my-book-site # The project repo namebinder_repo_branch : master # The branch on which your textbook is hosted.binderhub_interact_text : "Interact via Binder" # The text that interact buttons will contain.# Thebelab settingsuse_thebelab_button : true # If 'true', display a button to allow in-page running code cells with Thebelabthebelab_button_text : "Thebelab" # The text to display inside the Thebelab initialization buttoncodemirror_theme : "abcdef" # Theme for codemirror cells, for options see https://codemirror.net/doc/manual.html#config# nbinteract settingsuse_show_widgets_button : true # If 'true', display a button to allow in-page running code cells with nbinteract# Download settingsuse_download_button : true # If 'true', display a button to download a zip file for the notebookdownload_button_text : "Download" # The text that download buttons will containdownload_page_header : "Made with Jupyter Book" # A header that will be displayed at the top of and PDF-printed page######################################################################################## Jupyter book settings you probably don't need to changecontent_folder_name : "content" # The folder where your raw content (notebooks/markdown files) are locatedimages_url : "/assets/images" # Path to static image filescss_url : "/assets/css" # Path to static CSS filesjs_url : "/assets/js" # Path to JS filescustom_static_url : "/assets/custom" # Path to user's custom CSS/JS files######################################################################################## Jekyll build settings (only modify if you know what you're doing)# Site settingsdefaults: - scope: path: "" values: layout: "default" toc: true toc_label: " On this page" toc_icon: "list-ul" excerpt: ''favicon_path: "images/logo/favicon.ico"# Markdown Processingmarkdown: kramdownkramdown: input: GFM syntax_highlighter: rougesass: style: compressedcollections: build: output: true permalink: /:path.html# Exclude from processing.# The following items will not be processed, by default. Create a custom list# to override the default setting.exclude: - scripts/ - Gemfile - Gemfile.lock - node_modules - vendor/bundle/ - vendor/cache/ - vendor/gems/ - vendor/ruby/plugins: - jekyll-redirect-from - jekyll-scholar# Jupyter Book version - DO NOT CHANGE THIS. It is generated when a new book is createdjupyter_book_version: "0.6.4"

Once you are done with the 9 changes, replace the old _config.yml with the new one:

rm my-book/_config.ymlcp _config.yml my-book/

Step 11: build the html files to deploy with jupyter-book

Everything is in place now. The last step before deploying your site is to build the html files like this:

jupyter-book build my-book/

If successful, the terminal should print something like:

================================================================================Generated 5 new filesSkipped 0 already-built filesYour Jupyter Book is now in _build/.Demo your Jupyter book with make serve or push to GitHub!================================================================================

Step 12: push the site contents to GitHub and deploy as GitHub pages

You can test your site locally by navigating into your book and running make serve. You need Ruby and a bunch of tools (gems) installed to do that, so I won’t get into that now. Let’s push and deploy on GitHub pages.

First, add, commit, and push the changes to GitHub:

git add -Agit commit -m "my first jupyter book"git push origin master

Now, go to the repo Setting as shown in the picture below