Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Bob Nystrom started this. He wrote his excellent Game Programming Patterns book completely in the open. He showed us that it's possible to offer great content for free and at the same time become a fancy published author. Then he had the audacity of following it up with (possibly an even better book!) Crafting Interpreters. The nerve!

I just took the open source tooling from Bob's upstream project and started my own book, The Self-Improving Developer, which is based on my blog about intermediate software engineering topics.

You can find the site here:


Bob's upstream project is double-licensed. It uses MIT for the tooling and CC BY-NC-ND 4.0 for the "content files" (the text files, the SCSS styling, and so on).

This project stripped all of those content files and left only the tooling and the scaffold. If you want that, go to the just tooling branch. That code is fully MIT-licensed. You can start your own book.

After that commit, I started to add my own content, which is CC BY-NC-SA 4.0.



  • POSIX environment
  • Dart SDK installed

Run the following once.

$ make get

This downloads all the packages used by the scripts in /tools.



The Markdown and snippets of source code are woven together into the final HTML using a hand-written static site generator that started out as a single tiny Python script for my first book and somehow grew into something approximating a real program.

The generated HTML is committed in the repo under site/. It is built from a combination of Markdown for prose, which lives in book/, and snippets of code that are weaved in from the Java and C implementations in java/ and c/. (All of those funny looking comments in the source code are how it knows which snippet goes where.)

The script that does all the magic is tool/bin/build.dart. You can run that directly, or run:

$ make book

That generates the entire site in one batch. If you are incrementally working on it, you'll want to run the development server:

$ make serve

This runs a little HTTP server on localhost rooted at the site/ directory. Any time you request a page, it regenerates any files whose sources have been changed, including Markdown files, interpreter source files, templates, and assets. Just let that keep running, edit files locally, and refresh your browser to see the changes.

Chapter ordering

You specify which chapters get published and in what order by modifying the tool/lib/src/book_contents.dart file.

Repository Layout

  • asset/ – Sass files and mustache templates used to generate the site.
  • book/ - Markdown files for the text of each chapter.
  • build/ - Intermediate files and other build output (except for the site itself) go here. Not committed to Git.
  • site/ – The final generated site. The contents of this directory directly mirror the output of build.dart. Most content here is generated by this script, but fonts, images, and JS only live here. Everything is committed, even the generated content.
  • tool/ – Dart package containing the build, test, and other scripts.

Useful hints


The site is deployed on Firebase Hosting.

make deploy

Building web scripts

There are some scripts written in Dart that make the web reading experience a bit better. To build one, do something like this:

dart2js asset/scripts/index.dart -o site/index.dart.js -m -O4 --csp

Converting from HTML to Markdown

To convert from HTML to Markdown using pandoc, do this:

pandoc -i some_file.html -o book/ 

On a Mac and with some HTML in your clipboard:

pbpaste | pandoc -f html -t gfm --shift-heading-level-by=-1 -o book/