Add flake.nix exposing lib.mkWebapp #97

Closed
opened 2026-06-09 23:05:17 +00:00 by padreug · 0 comments
Owner

Background

The brand kit architecture (#95 / #96) deferred the flake.nix piece. This issue tracks adding it.

Once lib.mkWebapp { brandDir, app, ... } is exposed, aiolabs/server-deploy/hosts/<host>/services/webapp.nix can switch from its current build path to:

services.webapp.apps = {
  main   = inputs.webapp.lib.mkWebapp { inherit pkgs; brandDir = ./../branding; };
  events = inputs.webapp.lib.mkWebapp { inherit pkgs; brandDir = ./../branding; app = "events"; };
  wallet = inputs.webapp.lib.mkWebapp { inherit pkgs; brandDir = ./../branding; app = "wallet"; };
};

This is the consumer side of aiolabs/server-deploy#8 (Phase 2).

Scope

  • Add flake.nix at the webapp repo root with nixpkgs + flake-utils inputs.
  • Export lib.mkWebapp = pkgs: { brandDir ? ./branding/default, app ? "main", ... }: <derivation>.
  • Build derivation runs pnpm install --frozen-lockfile + pnpm build (or pnpm build:<app>), with BRAND_DIR exported from the passed brandDir and BRAND_APP from app.
  • Expose packages.${system}.default = lib.mkWebapp { ... } for nix build sanity (unparameterized aiolabs default).
  • Add nix flake check to CI (or document the manual check).

Known sticking points

pnpm under nix. buildNpmPackage is npm-specific. Options:

  • Use pkgs.stdenv.mkDerivation + pnpm.configHook (pnpm 8+ with corepack)
  • Use pnpm.fetchDeps { pname; version; src; hash; } for a deps derivation, then cp -r ${deps} node_modules in the main build
  • Use a community helper like mkPnpmPackage or the nixpkgs pnpm module
  • The webapp specifies pnpm in its packageManager field — verify the nix builder honors it

sharp / libvips in the sandbox. @vite-pwa/assets-generator uses sharp (native libvips bindings). Historically a nix pain point because sharp downloads precompiled binaries at install time, which doesn't fly in nix's offline sandbox.

Modern sharp (≥ 0.33) has better nix support: it can be built against system libvips. May need NPM_CONFIG_SHARP_LIBVIPS_INCLUDE_DIR + pkgs.vips in buildInputs.

If sharp can't be made to work cleanly under the sandbox, fallback: run the generator outside the derivation (Hydra-side prebuild step that writes to a fixed output, then the nix derivation consumes that). Less elegant but workable.

Vite's image optimizer plugin also uses native code (sharp transitively). Same concerns apply.

Acceptance

  • nix build .#default from the webapp repo produces a usable dist/ derivation.
  • nix build .#default --override-input pkgs github:NixOS/nixpkgs/<commit> works (consumer can pin their own nixpkgs).
  • inputs.webapp.lib.mkWebapp { inherit pkgs; brandDir = ./some-brand; } from a downstream flake builds with that brand's logo + manifest.
  • nix flake check passes.
  • Documented in branding/README.md (replace the placeholder note) and a short section in CLAUDE.md.

Cross-references

  • aiolabs/webapp#95 — brand kit architecture (parent design)
  • aiolabs/webapp#96 — Phase 1 webapp PR (lands brand kit minus flake.nix)
  • aiolabs/server-deploy#8 — Phase 2 host migration (consumer; blocked on this issue until then it can either wait or build the webapp via the existing path)
## Background The brand kit architecture (#95 / #96) deferred the `flake.nix` piece. This issue tracks adding it. Once `lib.mkWebapp { brandDir, app, ... }` is exposed, `aiolabs/server-deploy/hosts/<host>/services/webapp.nix` can switch from its current build path to: ```nix services.webapp.apps = { main = inputs.webapp.lib.mkWebapp { inherit pkgs; brandDir = ./../branding; }; events = inputs.webapp.lib.mkWebapp { inherit pkgs; brandDir = ./../branding; app = "events"; }; wallet = inputs.webapp.lib.mkWebapp { inherit pkgs; brandDir = ./../branding; app = "wallet"; }; }; ``` This is the consumer side of [aiolabs/server-deploy#8](https://git.atitlan.io/aiolabs/server-deploy/issues/8) (Phase 2). ## Scope - [ ] Add `flake.nix` at the webapp repo root with `nixpkgs` + `flake-utils` inputs. - [ ] Export `lib.mkWebapp = pkgs: { brandDir ? ./branding/default, app ? "main", ... }: <derivation>`. - [ ] Build derivation runs `pnpm install --frozen-lockfile` + `pnpm build` (or `pnpm build:<app>`), with `BRAND_DIR` exported from the passed `brandDir` and `BRAND_APP` from `app`. - [ ] Expose `packages.${system}.default = lib.mkWebapp { ... }` for `nix build` sanity (unparameterized aiolabs default). - [ ] Add `nix flake check` to CI (or document the manual check). ## Known sticking points **pnpm under nix.** `buildNpmPackage` is npm-specific. Options: - Use `pkgs.stdenv.mkDerivation` + `pnpm.configHook` (pnpm 8+ with corepack) - Use `pnpm.fetchDeps { pname; version; src; hash; }` for a deps derivation, then `cp -r ${deps} node_modules` in the main build - Use a community helper like [`mkPnpmPackage`](https://github.com/serokell/nix-npm-buildpackage) or the nixpkgs pnpm module - The webapp specifies `pnpm` in its `packageManager` field — verify the nix builder honors it **sharp / libvips in the sandbox.** `@vite-pwa/assets-generator` uses `sharp` (native libvips bindings). Historically a nix pain point because sharp downloads precompiled binaries at install time, which doesn't fly in nix's offline sandbox. Modern sharp (≥ 0.33) has better nix support: it can be built against system libvips. May need `NPM_CONFIG_SHARP_LIBVIPS_INCLUDE_DIR` + `pkgs.vips` in `buildInputs`. If sharp can't be made to work cleanly under the sandbox, fallback: run the generator outside the derivation (Hydra-side prebuild step that writes to a fixed output, then the nix derivation consumes that). Less elegant but workable. **Vite's image optimizer plugin** also uses native code (sharp transitively). Same concerns apply. ## Acceptance - `nix build .#default` from the webapp repo produces a usable `dist/` derivation. - `nix build .#default --override-input pkgs github:NixOS/nixpkgs/<commit>` works (consumer can pin their own nixpkgs). - `inputs.webapp.lib.mkWebapp { inherit pkgs; brandDir = ./some-brand; }` from a downstream flake builds with that brand's logo + manifest. - `nix flake check` passes. - Documented in `branding/README.md` (replace the placeholder note) and a short section in `CLAUDE.md`. ## Cross-references - aiolabs/webapp#95 — brand kit architecture (parent design) - aiolabs/webapp#96 — Phase 1 webapp PR (lands brand kit minus flake.nix) - aiolabs/server-deploy#8 — Phase 2 host migration (consumer; blocked on this issue until then it can either wait or build the webapp via the existing path)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/webapp#97
No description provided.