Creating a blog with notebooks


Blogging with notebooks can offer a dramatic quality of life improvement over writing in Markdown, especially for blog posts that contain code. Previously, there were no static site generators that supported Jupyter Notebooks as a first-class authoring medium. This previously led us to create fastpages (now deprecated), which extended Jekyll to enable blogging directly with Jupyter.

Enter Quarto

However, there now exists Quarto, a wonderful publishing system with rich support for authoring via Jupyter Notebooks.

Some helpful resources on getting started with Quarto:

You don’t need nbdev to blog with notebooks

You do not need to use nbdev to create a blog with notebooks. However, you may wish to:

  • Incorporate a blog in your nbdev project’s website
  • Use some nbdev functionality in your blog (testing, exporting etc)

We will discuss these subjects in this article.

Migrating from fastpages

If you previously had a fastpages site, we offer some utilities to help migrate you to Quarto. The migration is not holistic: you will likely have to manually correct some things that we are not able to automate.


  1. Install Quarto

  2. Create a new repo or directory to migrate your blog to

  3. In this new repo, create a quarto blog and install required extensions with the following terminal commands. This will create a minimal project structure for you:

quarto create-project --type website:blog .
quarto install extension quarto-ext/video
  1. Your new repo will have a posts/ directory. This is where you will copy all of your notebook and markdown posts from fastpages. For example, let’s say your fastpages blog repo is in a sibling directory located at ../blog/, you would copy all the relevant posts like this:

Make sure you are in root of your quarto directory before executing the below commands. Furthermore, change the commands as appropriate depending on the location of your fastpages repo relative to your current directory.

cp -r ../blog/_notebooks/* posts
cp -r ../blog/_posts/* posts
  1. Copy all images associated with your posts into the posts/ directory. We have to get our images from several places (due to the way Jekyll and fastpages work):
cp ../blog/images/* posts
cp -r ../blog/images/copied_from_nb/* posts/
  1. Make your posts Quarto compatible with the following command:
nbdev_migrate --path posts

nbdev_migrate does the following things:

For notebooks

  • Migrates markdown front matter to raw cell front matter as described here.
  • nbdev v1 directives are automatically converted to Quarto directives. Note that we convert everything to Quarto directives (nbdev-specific directives are not relevant for this context)
  • Markdown shortcut for embedding youtube videos and callouts are automatically converted to work with Quarto.

For markdown and notebooks

  • Automatically creates link aliases so that old links will not break. Jekyll automatically generates URLs differently than Quarto, so this ensures that the Jekyll way is aliased.
  • Automatically corrects image paths
  • Makes front matter compatible with Quarto by changing field names and values where necessary
  1. Update the following files:
  • ./.gitignore: we suggest adding_site/ as well as dot files .*
  • ./about.qmd: Add some information about yourself.
  • ./profile.jpg: optionally change the profile picture.
  1. Preview your site with the command quarto preview, and make any necessary adjustments and fix for broken links or Jekyll shortcodes (things with {% ... %}) that need to be converted to Quarto. Search the the Quarto documentation if you need help locating specific Quarto features.

Configuration options: fastpages vs. Quarto

fastpages (which is based on Jekyll) and Quarto offer different options and configurations for individual posts and at a site level. The tables below enumerate some of the most important features of fastpages and how they map to Quarto. Each link in the last column is specific to the relevant feature.

Post-level options

Jekyll Front Matter Quarto Notes
toc: false Same There are more options in the Quarto docs
badges: true n/a No support yet
comments: true see notes Quarto docs
categories: [fastpages, jupyter] Same Quarto docs
image: images/some_folder/your_image.png Same Quarto docs
hide: false draft: true Quarto docs
search_exclude: true see notes Quarto docs
title Same  
description Same  
sticky_rank Not supported Quarto docs

Site-level options

Jekyll site config Quarto Notes
title see notes Quarto docs
description see notes Quarto docs
github_repo see notes Quarto docs
url n/a Don’t need this
baseurl n/a Don’t need this
twitter_username search page in notes for “twitter” Quarto docs
use_math see notes  Quarto docs
google_analytics website: google-analytics: “UA-XXXXXXXX” Quarto docs
show_image n/a Quarto docs
show_tags see title-block-categories of page in notes Quarto docs
pagination website: page-navigation: true Quarto docs
annotations comments: hypothesis: … Quarto docs

Publishing your blog


This section is for stand-alone blogs that are not part of a nbdev documentation site. If you want to create a blog within a nbdev documentation site, see this section.

You can publish your site with the quarto publish command. See the docs for more details.

GitHub Pages

If using GitHub Pages, commit your files to GitHub before publish your site. No GitHub Actions are needed, you can use quarto publish instead. If you want to automate your workflow with GitHub Actions, you can follow these instructions

Creating a blog within a nbdev project

In addition to a stand-alone blog that you might build with Quarto, you might want to include a blogging site in your nbdev project. This website has a blog as well! The easiest way to implement a blog is to emulate the directory structure of this folder. The general steps are:

  1. Create a blog/ directory in your notebooks folder.
  2. Create a index.qmd file in the root of the blog/ directory. Here is an example.

The frontmatter the index.qmd file signals to Quarto that you intend to create a blog. For example, here is our front matter:

title: nbdev Blog
subtitle: News, tips, and commentary about all things nbdev
  sort: "date desc"
  contents: "posts"
  sort-ui: false
  filter-ui: false
  categories: true
  feed: true
page-layout: full

The listing: field specifies how you want to structure your blog. Feel free to copy ours as-is, but we encourage you to consult the documentation for additional options.

  1. Create a link to your blog on your site’s navbar so people can find it: To add a link to your blog on your site’s navbar, you must edit the navbar section of _quarto.yml to include a link to your blog’s listing page, which is blog/index.qmd in our example. For nbdev, the relevant part of our _quarto.yml file looks like this:
The yaml snippet shown below is an abbreviated version of nbdev’s _quarto.yml file.
      - text: "Blog"
        href: blog/index.qmd

You can read more about the navbar in the Quarto docs.

  1. Create a folder for each blog post: This is not strictly required, but we recommend this as a way to keep your blog posts and related assets (pictures, videos etc) organized.

  2. Create your first blog post: You can emulate our example or create your own. In each folder, create a index.qmd or index.ipynb file. You can also put images and related assets in the same folder.

Folder structure

Below is an overview of the general folder structure for a blog within a nbdev site:

├── index.qmd
└── posts
    ├── 2022-07-28-nbdev2
    │   ├── cover.png
    │   ├── index.qmd
    │   ├── ...
    └── 2022-08-25-jupyter-git
        ├── friendly-conflict.png
        ├── index.qmd
        └── ...
  • nbs/blog: this is the folder inside your notebook folder that contains the blog.
  • index.qmd: this is at the root of your blog folder and is the listings page for your blog.
  • posts/: this a subdirectory for each blog post.
  • YYYY-MM-DD-.../index.{qmd,ipynb}: this is where you author the content of each individual blog post.

Special considerations for nbdev blogs

In contrast to standalone Quarto blogs, when you embed a blog in a nbdev website there are the following differences:

  • You can use all nbdev directives in addition to Quarto ones. All nbdev features will be available in your nbdev blog in the same way they work for other pages.
  • Your site will automatically deploy with GitHub Actions or whatever deployment mechanism you have for your nbdev site, so you do not have to use quarto publish.

Using nbdev features in blogs outside nbdev projects


This section is for stand-alone blogs that are not part of a nbdev documentation site. If you create a blog within a nbdev documentation site, all nbdev features will automatically work.

If you create a standalone blog with Quarto, a limited number of nbdev features can still assist you. For example, we recommend installing Jupyter git hooks. A list of nbdev features available to you are listed in this article.


  1. Do I need to migrate from fastpages?

    No you do not. However we will not be actively supporting fastpages going forward.

  2. Will migrating from fastpages to Quarto take lots of manual effort?

    You will have to do some manual work to make sure everything looks and works the same, including converting Jekyll shortcodes to equivalent Quarto commands. However, we have automated the biggest aspects for you. Please see Migrating from fastpages for instructions.

  3. I cannot find something in Quarto that does what #collapse_output did in fastpages

    Correct, this is a feature that isn’t supported in Quarto yet.

  4. Why am I seeing {% twitter ...%} and {% fn_detail ... %} and other {%...%} commands in my Quarto blog posts?

    These are Jekyll shortcodes that you will have to manually migrate to Quarto. For example with the twitter embeds, you can insert the appropriate HTML as recommended by Twitter. For footnotes, you can see these docs. For other items, you should search the Quarto docs for how to enable your desired result.

  5. I created a new blog post and used #| hide but the cell is still showing. What is wrong?

    You must use Quarto directives, not nbdev-specific ones. See the difference between the two in these docs. This is because you are blogging with Quarto, not nbdev. The exception to this is you have a blog site in your nbdev project – in that case, nbdev-specific directives will work.

  6. How do I enable comments on my blog posts?

    In general, Quarto offers all of the same features and much more than fastpages did, including comments. If you search the Quarto docs for comments, you will see a page for enabling comments.

  7. How do I sort and hide posts? What about the publishing date since that’s not in the filename?

    See the Quarto docs on creating a blog as well as listing pages.

  8. How do I customize my site?

    See the Quarto docs

  9. How do I do set up RSS Feeds and add particular features to my site?

    See the Quarto docs

  10. What does nbdev have to do with Quarto?.

    For just blogging, nothing! You can use Quarto for blogging without worrying about nbdev. In the past, we maintained a nbdev related project called fastpages, and are recommending that people migrate to Quarto if possible. Furthermore, nbdev is built on top of Quarto which means much of the functionality is similar. Finally, you can incorporate blogs into a nbdev project site, which we discuss in this section.

  11. For stand alone blogs, why are you directing us to Quarto, can I just use nbdev?

    nbdev is built on top of Quarto. For the purposes of blogging, adding nbdev is of little additional benefit if all you want to do is to blog. We decided to keep things simple and let people use Quarto directly instead of trying to abstract aspects of Quarto for blogging. Furthermore, having some knowledge of Quarto can be very helpful in using nbdev!. Lastly, you can still use some nbdev features in your blog, which are listed in this article.