A Next.js app via the js toolchain: build, test, and lint.
A Next.js app via the js toolchain: build, test, and lint.
Project layout
Pipeline
"""Next.js example pipeline."""from __future__ import annotationsimport harmont as hm@hm.pipeline( "ci", env={"CI": "true"}, default_image="ubuntu:24.04", triggers=[hm.push(branch="main")],)def ci() -> tuple[hm.Step, ...]: project = hm.js.project(path=".") return (project.run("build"), project.run("test"), project.run("lint"))import { pipeline, push, type PipelineDefinition } from "@harmont/hm";import { js } from "@harmont/hm/toolchains";const project = js.project({ path: "." });const pipelines: PipelineDefinition[] = [ { slug: "ci", triggers: [push({ branch: "main" })], pipeline: pipeline([project.run("build"), project.run("test"), project.run("lint")], { env: { CI: "true" }, defaultImage: "ubuntu:24.04", }), },];export default pipelines;Run it
hm run ciBefore your first run: pin your package manager
create-next-app installs your dependencies with a specific pnpm version and
writes a supply-chain policy (minimumReleaseAge, the 24-hour package-age gate)
next to the lockfile. The trouble starts when the build runs a different,
newer pnpm than the one that scaffolded the project: pnpm 11.1+ re-validates
the committed lockfile against that policy before installing, and a brand-new app
pins the freshest Next.js, React, and type packages — all published in the last
day — so the install fails before fetching anything:
✗ Lockfile failed supply-chain policy check
[ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION] 5 lockfile entries failed verification:
caniuse-lite@1.0.30001799 was published ... within the minimumReleaseAge cutoffThe fix is to build with the same pnpm that scaffolded the project, so CI
resolves exactly what you ran locally. create-next-app prints that version on
its last line:
Done in 5.4s using pnpm v10.33.0Add a matching packageManager field to package.json:
{
"packageManager": "pnpm@10.33.0"
}The js toolchain reads this field and pins the build's pnpm to it (via
corepack), so CI installs with the same package manager as your machine. The
build becomes reproducible and your lockfile's supply-chain policy stays
intact — no need to weaken it.
Use the exact version from your own create-next-app output — it may differ from
10.33.0. Pinning packageManager is good hygiene for any JS project on Harmont:
it's what makes your local install and your CI install byte-for-byte the same.
Stuck?
Pipelines for real apps hit real edges. If something doesn't build the way you expect, ask in the Harmont Discord — we answer fast.