{ depot, pkgs, lib, ... }:
let
  bins = depot.nix.getBins pkgs.lowdown [ "lowdown" ]
    // depot.nix.getBins pkgs.cdb [ "cdbget" "cdbmake" "cdbdump" ]
    // depot.nix.getBins pkgs.coreutils [ "mv" "cat" "printf" "test" ]
    // depot.nix.getBins pkgs.s6-networking [ "s6-tcpserver" ]
    // depot.nix.getBins pkgs.time [ "time" ]
  ;
  # /
  # TODO: use
  toplevel = [
    {
      route = [ "notes" ];
      name = "Notes";
      page = { cssFile }: router cssFile;
    }
    {
      route = [ "projects" ];
      name = "Projects";
      # page = projects;
    }
  ];
  # /notes/*
  notes = [
    {
      route = [ "notes" "an-idealized-conflang" ];
      name = "An Idealized Configuration Language";
      page = { cssFile }: markdownToHtml {
        name = "an-idealized-conflang";
        markdown = ./notes/an-idealized-conflang.md;
        inherit cssFile;
      };
    }
    {
      route = [ "notes" "rust-string-conversions" ];
      name = "Converting between different String types in Rust";
      page = { cssFile }: markdownToHtml {
        name = "rust-string-conversions";
        markdown = ./notes/rust-string-conversions.md;
        inherit cssFile;
      };
    }
    {
      route = [ "notes" "preventing-oom" ];
      name = "Preventing out-of-memory (OOM) errors on Linux";
      page = { cssFile }: markdownToHtml {
        name = "preventing-oom";
        markdown = ./notes/preventing-oom.md;
        inherit cssFile;
      };
    }
  ];
  projects = [
    {
      name = "lorri";
      description = "nix-shell replacement for projects";
      link = "https://github.com/nix-community/lorri";
    }
    {
      name = "netencode";
      description = ''A human-readble nested data exchange format inspired by netstrings and bencode.'';
      link = depotCgitLink { relativePath = "users/Profpatsch/netencode/README.md"; };
    }
    {
      name = "yarn2nix";
      description = ''nix dependency generator for the yarn Javascript package manager'';
      link = "https://github.com/Profpatsch/yarn2nix";
    }
  ];
  posts = [
    {
      date = "2017-05-04";
      title = "Ligature Emulation in Emacs";
      subtitle = "It’s not pretty, but the results are";
      description = "How to set up ligatures using prettify-symbols-mode and the Hasklig/FiraCode fonts.";
      page = { cssFile }: markdownToHtml {
        name = "2017-05-04-ligature-emluation-in-emacs";
        markdown = ./posts/2017-05-04-ligature-emulation-in-emacs.md;
        inherit cssFile;
      };
      route = [ "posts" "2017-05-04-ligature-emluation-in-emacs" ];
      tags = [ "emacs" ];
    }
  ];
  # convert a markdown file to html via lowdown
  markdownToHtml =
    { name
    , # the file to convert
      markdown
    , # css file to add to the final result, as { route }
      cssFile
    }:
    depot.nix.runExecline "${name}.html" { } ([
      "importas"
      "out"
      "out"
      (depot.users.Profpatsch.lib.debugExec "")
      bins.lowdown
      "-s"
      "-Thtml"
    ] ++
    (lib.optional (cssFile != null) ([ "-M" "css=${mkRoute cssFile.route}" ]))
    ++ [
      "-o"
      "$out"
      markdown
    ]);
  # takes a { route … } attrset and converts the route lists to an absolute path
  fullRoute = attrs: lib.pipe attrs [
    (map (x@{ route, ... }: x // { route = mkRoute route; }))
  ];
  # a cdb from route to a netencoded version of data for each route
  router = cssFile: lib.pipe (notes ++ posts) [
    (map (r: with depot.users.Profpatsch.lens;
    lib.pipe r [
      (over (field "route") mkRoute)
      (over (field "page") (_ { inherit cssFile; }))
    ]))
    (map (x: {
      name = x.route;
      value = depot.users.Profpatsch.netencode.gen.dwim x;
    }))
    lib.listToAttrs
    (cdbMake "router")
  ];
  # Create a link to the given source file/directory, given the relative path in the depot repo.
  # Checks that the file exists at evaluation time.
  depotCgitLink =
    {
      # relative path from the depot root (without leading /).
      relativePath
    }:
      assert
      (lib.assertMsg
        (builtins.pathExists (depot.path.origSrc + ("/" + relativePath)))
        "depotCgitLink: path /${relativePath} does not exist in depot, and depot.path was ${toString depot.path}");
      "https://code.tvl.fyi/tree/${relativePath}";
  # look up a route by path ($1)
  router-lookup = cssFile: depot.nix.writeExecline "router-lookup" { readNArgs = 1; } [
    cdbLookup
    (router cssFile)
    "$1"
  ];
  runExeclineStdout = name: args: cmd: depot.nix.runExecline name args ([
    "importas"
    "-ui"
    "out"
    "out"
    "redirfd"
    "-w"
    "1"
    "$out"
  ] ++ cmd);
  notes-index-html =
    let o = fullRoute notes;
    in ''