Building a Directory with buildNpmPackage
in a Nix Derivation
eleventy
javascript
nix
nodejs
npm
Candidly, I'm very surprised it seems like no one has written this article yet,
but I looked and it seems like no one has. The question I set out to answer
is how to use a Nix derivation to build an npm package where the build product
is not a single "bin"
executable file but rather a directory.
Surely, this is a wildly common use cases in JavaScript, right? People compile TypeScript projects into directories all the time. (I prefer ReScript, but it's much the same.) Surely, not everyone uses a script bundler, right? (Please don't disillusion me!)
But I had more trouble with this than I expected. Fortunately, the Nix community is excellent, and @[email protected] on Mastodon gave me the answer.
For my setup, I'm building a public/ directory using an npm "build"
script
set to npx eleventy
. This builds the static website.
This is my derivative:
mysite.nix
{ buildNpmPackage, lib }:
let
fs = lib.fileset;
sourceFiles = fs.gitTracked ./.;
in
buildNpmPackage rec {
npmDepsHash = "sha256-+4lLBQ+UQ2XT0wwE6jADxG1UNZjLkQCLvvN1SdiUwZY=";
pname = "mysite";
src = fs.toSource {
root = ./.;
fileset = sourceFiles;
};
postInstall = ''
cp -rv public/ $out
'';
version = "0.0.1";
}
The key here of course is the postInstall
script. The folder is there for us
and we just have to go get it.
(For completeness, if you're a beginner wondering how I got the npmDepsHash
,
a good trick is just to leave the string empty so that the error message you
get tells you what the string should be. The rest of this should look at least
somewhat intuitive even if the Nix syntax terrifies you as much as it does me.)
There's no magic in the default.nix, here. Just pass in some packages and reference mysite.nix.
default.nix
let
# nixpkgs-24.11-darwin
# 2025-03-01
nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/archive/26a98b6560fe0526b324d76619ffc55e61b4625e.tar.gz";
pkgs = import nixpkgs { config = {}; overlays = []; };
in
{
mysite = pkgs.callPackage ./mysite.nix { };
}
And that's really all there is to it! Nix is often criticized for not having good documentation, so I figure every example of someone doing something in Nix is bound to help the community a little.
I write to learn, so I welcome your constructive criticism. Report issues on GitLab.