open-design/flake.nix
Marc Chan d5659d82d4
chore(nix): streamline pnpm deps hash maintenance (#2919)
* chore(nix): streamline pnpm deps hash maintenance

Generated-By: looper 0.9.0 (runner=worker, agent=opencode)

* fix(ci): satisfy actionlint in nix hash autofix

Generated-By: looper 0.9.0 (runner=fixer, agent=opencode)

* fix(ci): allow nix hash autofix on fork PRs

Generated-By: looper 0.9.0 (runner=fixer, agent=opencode)

* fix(ci): follow up nix hash review

Generated-By: looper 0.9.0 (runner=fixer, agent=opencode)

* fix(ci): tolerate nix hash bot token failures

Generated-By: looper 0.9.0 (runner=fixer, agent=opencode)
2026-05-26 07:35:38 +00:00

187 lines
5.6 KiB
Nix

{
description = "Open Design local-first design product. Daemon (`od` CLI) + Next.js static web frontend.";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
dream2nix = {
url = "github:nix-community/dream2nix";
inputs.nixpkgs.follows = "nixpkgs";
};
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
self,
nixpkgs,
flake-utils,
dream2nix,
home-manager,
}: let
filterProjectSource = includePaths:
nixpkgs.lib.cleanSourceWith {
src = self;
filter = path: type: let
root = toString self;
pathStr = toString path;
rel = nixpkgs.lib.removePrefix (root + "/") pathStr;
matches = includePath:
rel == includePath
|| nixpkgs.lib.hasPrefix (includePath + "/") rel
|| (type == "directory" && nixpkgs.lib.hasPrefix (rel + "/") includePath);
in
rel == ""
|| builtins.any matches includePaths;
};
perSystem = flake-utils.lib.eachDefaultSystem (system: let
pkgs = import nixpkgs {inherit system;};
nodejs = pkgs.nodejs_24;
# Keep in sync with .github/workflows/ci.yml change_scopes
# nix_validation_required filter.
daemonWorkspacePaths = [
"packages/contracts"
"packages/registry-protocol"
"packages/agui-adapter"
"packages/plugin-runtime"
"packages/sidecar-proto"
"packages/sidecar"
"packages/platform"
"packages/diagnostics"
"apps/daemon"
];
# Keep in sync with .github/workflows/ci.yml change_scopes
# nix_validation_required filter.
webWorkspacePaths = [
"packages/contracts"
"packages/host"
"packages/platform"
"packages/sidecar"
"packages/sidecar-proto"
"apps/web"
];
daemonSrc = filterProjectSource ([
"package.json"
"pnpm-lock.yaml"
"pnpm-workspace.yaml"
"tsconfig.json"
"assets"
"plugins"
"skills"
"design-systems"
"design-templates"
"craft"
"prompt-templates"
]
++ daemonWorkspacePaths);
webSrc = filterProjectSource ([
"package.json"
"pnpm-lock.yaml"
"pnpm-workspace.yaml"
"tsconfig.json"
]
++ webWorkspacePaths);
# nixpkgs ships pnpm 10.33.0; the repo's package.json declares
# `engines.pnpm: ">=10.33.2 <11"` and pnpm refuses to install
# against an older binary. Override the upstream tarball to
# the exact version pinned by `packageManager`. Bump the url
# + hash in lockstep with package.json#packageManager.
#
# When bumping versions, run the following to get a new hash:
#
# ```bash
# nix store prefetch-file --hash-type sha256 \
# https://registry.npmjs.org/pnpm/-/pnpm-${NEW_VERSION}.tgz
# ```
pnpm_10 = pkgs.pnpm_10.overrideAttrs (_old: rec {
version = "10.33.2";
src = pkgs.fetchurl {
url = "https://registry.npmjs.org/pnpm/-/pnpm-${version}.tgz";
hash = "sha256-envPE9f2zrOUbAOXg3PZm+n94cr8MAC9/tTE95EWdhA=";
};
});
daemon = pkgs.callPackage ./nix/package-daemon.nix {
inherit dream2nix nixpkgs system nodejs pnpm_10;
src = daemonSrc;
workspacePaths = daemonWorkspacePaths;
};
web = pkgs.callPackage ./nix/package-web.nix {
inherit dream2nix nixpkgs system nodejs pnpm_10;
src = webSrc;
workspacePaths = webWorkspacePaths;
};
in {
packages = {
inherit daemon web;
default = daemon;
};
# Wrap `od` with `--no-open` for `nix run`: the daemon package
# builds the daemon workspace only, not `apps/web/out/`, so the
# browser would otherwise auto-open onto an empty static dir.
#
# Set OD_DATA_DIR to a writable location when unset. The Nix store
# is read-only at runtime, so the daemon cannot write to its default
# `<projectRoot>/.od` location under `nix run`.
apps.default = {
type = "app";
program = "${pkgs.writeShellScript "od-nix-run" ''
export OD_DATA_DIR="''${OD_DATA_DIR:-$HOME/.od}"
exec ${daemon}/bin/od --no-open "$@"
''}";
meta.description = "Open Design local daemon (`od`)";
};
devShells.default = pkgs.mkShell {
packages = [
nodejs
pnpm_10
];
shellHook = ''
echo "🎨 Open Design dev shell loaded!"
echo ""
echo "Language runtimes:"
echo " - 🐢 Node.js: $(node --version 2>/dev/null || echo 'not found')"
echo " - 📦 pnpm: $(pnpm --version 2>/dev/null || echo 'not found')"
echo ""
echo "Quick start:"
echo " - 🚀 pnpm install"
echo " - 🚀 pnpm tools-dev # local lifecycle entry point"
echo ""
'';
};
checks = {
daemon = daemon;
web = web;
};
formatter = pkgs.nixpkgs-fmt;
});
moduleCommon = import ./nix/module-common.nix;
in
perSystem
// {
homeManagerModules = rec {
open-design = import ./nix/home-manager.nix {
inherit moduleCommon;
flake = self;
};
default = open-design;
};
nixosModules = rec {
open-design = import ./nix/nixos.nix {
inherit moduleCommon;
flake = self;
};
default = open-design;
};
};
}