mdbook via nix!

Nix as a development environment is truely fantastic. Perfectly reproduceable, and gone are are the "run this script" setup steps.

This webpage is generated by mdbook, but even further so the environment is a nix flake, so the setup is really trivial.


This is the flake.nix which makes it all happen:

  description = "";
  nixConfig.bash-prompt = "\[nix-badflyer-shell\]$ ";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs";
    flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
        pkgs = nixpkgs.legacyPackages.${system};
        inputs = [

        builder = pkgs.stdenv.mkDerivation {
          name = "badflyer";
          src = ./.;
          buildInputs = inputs;
          buildPhase = ''
            mdbook build
          installPhase = ''
            mkdir $out
            cp -R book/* $out

      in {
        devShell = pkgs.mkShell {
          buildInputs = inputs;

        packages.default = builder;
        defaultPackage = builder;
        checks.default = builder;

The build workflow is as simple as:

git add -all && nix build

The development workflow is as simple as:

nix develop
mdbook serve


This is a github pages site. Unfortunatly the free github runners don't have any nix support. So how does it get deployed? The Magic is in git subtree split, which allow you to commit a folder into the root of a different branch.

# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the workflow will run
  # Triggers the workflow on push or pull request events but only for the "main" branch
    branches: [ "main" ]
    branches: [ "main" ]

  # Allows you to run this workflow manually from the Actions tab

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
  # This workflow contains a single job called "build"
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v3

      # Runs a single command using the runners shell
      - name: Install mdbook
        run: |
          mkdir bin
          # Download mdbook
          curl -sSL | tar -xz --directory=bin
          # build the site
          bin/mdbook build
          # Specific to github, make sure the cname file ends up in the deployment. For the custom domain name.
          cp CNAME book/CNAME

      # Runs a set of commands using the runners shell
      - name: Deployment
        run: |
          git config --global ""
          git config --global "Continuous Integration"
          # Force add the book folder (this is the output of mdbook build)
          git add book -f
          # Commit (this will go onto master, but it's fine, we're throwing it away.)
          git commit -m "Updating"
          # Commit the 'book' folde onto the branch gh-pages
          git subtree split -P book -b gh-pages
          # Force push gh-pages
          git push --force origin gh-pages