{
  lib,
  stdenvNoCC,
  fetchFromGitHub,
  fetchurl,
  symlinkJoin,
  makeBinaryWrapper,

  pkg-config,
  openssl,
  cargo-leptos,
  dart-sass,
  rustPlatform,
  wasm-bindgen-cli_0_2_100,
  binaryen,
  inkscape,

  mkShell,
  clangStdenv,
  rust-analyzer,
  rustc,
  rustfmt,
  leptosfmt,
  cargo,
  clippy,

  writers,
  ast-grep,
  nix-prefetch-github,
}:
let
  cargoMetadata = lib.pipe ./Cargo.toml [
    builtins.readFile
    builtins.fromTOML
  ];

  sass-dependencies = {
    bulma = stdenvNoCC.mkDerivation (drv: {
      pname = "bulma";
      version = "1.0.4";

      src = fetchFromGitHub {
        owner = "jgthms";
        repo = "bulma";
        rev = drv.version;
        hash = "sha256-hlejqBI6ayzhm15IymrzhTevkl3xffMfdTasZ2CmAas=";
      };

      installPhase = ''
        mkdir -p $out/node_modules/bulma/
        cp -r ./sass $out/node_modules/bulma/
      '';
    });

    fontsource-scss = stdenvNoCC.mkDerivation {
      pname = "fontsource-scss";
      version = "0.2.2";

      src = fetchurl {
        url = "https://registry.npmjs.org/@fontsource-utils/scss/-/scss-0.2.2.tgz";
        hash = "sha256-2BkCBhh01kZfMHhjHMMLDtUeesi7Uy7eMoeM1BAqX38=";
      };

      installPhase = ''
        mkdir -p $out/node_modules/@fontsource-utils/scss/
        cp -r . $out/node_modules/@fontsource-utils/scss/
      '';
    };

    fontsource-nunito = stdenvNoCC.mkDerivation {
      pname = "fontsource-nunito";
      version = "5.2.7";

      src = fetchurl {
        url = "https://registry.npmjs.org/@fontsource-variable/nunito/-/nunito-5.2.7.tgz";
        hash = "sha256-xSt1sDpVL/hVYzffKTgN/t7uLI3JadDWtTfWow2jiPM=";
      };

      outputs = [
        "out"
        "assets"
      ];

      installPhase = ''
        mkdir -p $out/node_modules/@fontsource-variable/nunito/
        cp -r . $out/node_modules/@fontsource-variable/nunito/

        mkdir -p $assets/@fontsource-variable/
        cp -r files/ $assets/@fontsource-variable/nunito
      '';
    };

    fontsource-arimo = stdenvNoCC.mkDerivation {
      pname = "fontsource-nunito";
      version = "5.2.8";

      src = fetchurl {
        url = "https://registry.npmjs.org/@fontsource-variable/arimo/-/arimo-5.2.8.tgz";
        hash = "sha256-jD1IGqy02j4bqMRAwbCgiIz/h97WPrTSd3eZ09nptHA=";
      };

      outputs = [
        "out"
        "assets"
      ];

      installPhase = ''
        mkdir -p $out/node_modules/@fontsource-variable/arimo/
        cp -r . $out/node_modules/@fontsource-variable/arimo/

        mkdir -p $assets/@fontsource-variable/
        cp -r files/ $assets/@fontsource-variable/arimo
      '';
    };
  };

  other-dependencies = {
    hack-font = stdenvNoCC.mkDerivation (drv: {
      pname = "hack-font";
      version = "3.003";

      src = fetchFromGitHub {
        owner = "source-foundry";
        repo = "Hack";
        rev = "v${drv.version}";
        hash = "sha256-qGDtBvKecdfsleUBfXFezllz9Op679a030Qcj/oBs1o=";
      };

      dontBuild = true;

      installPhase = ''
        mkdir -p $out
        cp -r build/web/fonts $out/hack-font/
      '';
    });
  };

  icons = stdenvNoCC.mkDerivation {
    pname = "tlaternet-icons";
    version = "1.0";

    src = ./public/icon.svg;

    dontUnpack = true;

    nativeBuildInputs = [ inkscape ];

    buildPhase = ''
      inkscape -w 48 -h 48 $src --export-filename=favicon-48.png
    '';

    installPhase = ''
      mkdir -p $out
      cp $src $out/icon.svg
      cp favicon-48.png $out/
    '';
  };

  assets = symlinkJoin {
    name = "assets-${cargoMetadata.package.name}";
    paths = [
      sass-dependencies.fontsource-arimo.assets
      sass-dependencies.fontsource-nunito.assets
      other-dependencies.hack-font
      icons
    ];
  };

  # Hack to allow importing sass *without* resorting to using `npm`
  # and dealing with the insanity that is `package.json` files.
  #
  # dart-sass *in theory* supports completely arbitrary logic for
  # package importing via the `pkg:` url prefix, but unfortunately
  # currently the only implementation of it that is available in the
  # upstream binary *requires* using a `node_modules` file in the
  # repository root. See here:
  # https://sass-lang.com/documentation/at-rules/use/#node-js-package-importer
  #
  # This wouldn't be so bad if it supported an environment variable or
  # command line arg to specify what the repo root should be, but it
  # doesn't; so instead we use the load-path to specify a package
  # import root.
  #
  # As a consequence, we cannot use the `pkg:` prefix, so package
  # imports are indistinguishable from relative path imports. This
  # isn't the end of the world, but:
  #
  # TODO(tlater): See if we can talk to upstream about an
  # implementation better suited for use with nix, perhaps in
  # dart-sass (add an env variable?) or in cargo-leptos (add a config
  # option that can also be set with an env variable, and use the sass
  # protocol instead of the raw exe?).
  dart-sass-with-packages =
    let
      packages = symlinkJoin {
        name = "sass-packages";
        paths = lib.attrValues sass-dependencies;
        stripPrefix = "/node_modules";
      };
    in
    symlinkJoin {
      inherit (dart-sass) version;
      pname = "dart-sass-with-packages";

      paths = [ dart-sass ];
      nativeBuildInputs = [ makeBinaryWrapper ];

      postBuild = ''
        wrapProgram $out/bin/sass \
          --add-flag --load-path=${packages}
      '';
    };
in
rustPlatform.buildRustPackage (drv: {
  inherit (cargoMetadata.package) version;
  pname = cargoMetadata.package.name;
  cargoLock.lockFile = drv.src + /Cargo.lock;

  src = lib.fileset.toSource {
    root = ./.;
    fileset = lib.fileset.fromSource (lib.sources.cleanSource ./.);
  };

  nativeBuildInputs = [
    cargo-leptos
    rustc.llvmPackages.lld
    dart-sass-with-packages
    makeBinaryWrapper
    pkg-config
    wasm-bindgen-cli_0_2_100
    binaryen
  ];

  buildInputs = [ openssl ];

  LEPTOS_ASSETS_DIR = assets.outPath;

  buildPhase = ''
    runHook preBuild
    cargo leptos build --release
    runHook postBuild
  '';

  installPhase = ''
    runHook preInstall

    mkdir -p $out/bin $out/share
    cp target/release/tlaternet-webserver $out/bin
    cp -r target/site $out/share
    wrapProgram $out/bin/tlaternet-webserver \
      --set LEPTOS_SITE_ROOT $out/share/site \
      --set LEPTOS_ASSETS_DIR ${assets.outPath}

    runHook postInstall
  '';

  meta.mainProgram = "tlaternet-webserver";

  passthru = {
    dependencies = sass-dependencies;

    devShell = mkShell.override { stdenv = clangStdenv; } {
      packages = [
        pkg-config
        openssl
        cargo-leptos
        dart-sass-with-packages
        # lld is exposed as ld by the clangStdenv, adding it
        # explicitly with bintools makes it work
        rustc.llvmPackages.lld

        rust-analyzer
        rustc
        rustfmt
        leptosfmt
        cargo
        clippy
      ];

      LEPTOS_ASSETS_DIR = assets.outPath;
    };

    updateScript = writers.writeNuBin "update-${cargoMetadata.package.name}" {
      makeWrapperArgs = [
        "--prefix"
        "PATH"
        ":"
        (lib.makeBinPath [
          ast-grep
          nix-prefetch-github
          cargo
        ])
      ];
    } ./update.nu;
  };
})
