vercel/next.js: two workspaces, one config
Next.js is a pnpm workspace and a Cargo workspace in one repository, and each ecosystem's tools read only their own manifests. One config checks both, and on the May tree it found two published npm packages with no license. This config was written to test alint; Next.js doesn't use alint.
What alint found
- id: nextjs-package-has-license-field
kind: for_each_dir
select: "packages/*"
when_iter: 'iter.has_file("package.json")'
require:
- kind: json_path_matches
paths: "{path}/package.json"
path: "$.license"
matches: '^MIT$'
level: warning⚠︎ warning nextjs-package-has-license-field
Three packages have no license field. Two of them, @next/ and next-rspack, are published to npm; the third, next-swc, is private.
- id: nextjs-crate-license-set
kind: toml_path_matches
paths: ["crates/*/Cargo.toml" , "turbopack/crates/*/Cargo.toml" ]
path: "$.package.license"
matches: '^(MIT|MPL-2\.0|Apache-2\.0)$'
level: infoℹ︎ info nextjs-crate-license-set
Four of the 63 crates declare no license. Three set publish = false, and the fourth, the error-code SWC plugin, is left out of the workspace. The JavaScript tools don't read Cargo manifests, and Cargo doesn't read npm packages.
The bundled GitHub Actions rules (alint 0.16.1, on the workflows as of 7 May 2026) flag 95 action references not pinned to a commit, and 21 workflows that declare no permissions.
The config
The pnpm workspace lists 7 package patterns and the root Cargo 13 members; the 19 packages under packages/ share one canary version, which lerna publishes. The config checks the fields every npm package and crate should carry, the Node and Rust toolchain pins, the husky hooks and lerna's publish settings. The linters and four check scripts run from command_ rules. A fifth runs scripts/, which fails: the error manifest it reads was deleted in 2023.
- id: nextjs-package-version-pinned-to-major
kind: for_each_dir
select: "packages/*"
when_iter: 'iter.has_file("package.json")'
require:
- kind: json_path_matches
paths: "{path}/package.json"
path: "$.version"
matches: '^16\.\d+\.\d+(-(canary|alpha|beta|rc)\.\d+)?$'
level: warningThe packages share one version, which lerna publishes from the canary branch. Every package has to be on the current major.
What stays outside alint
What analyzes code or reads git history stays with the Next.js tools:
- ESLint, tsc, ast-grep and alex, which analyze code or wording, and Clippy, which needs the Rust compiler; alint only runs them;
- the example and precompiled checks, which regenerate files and diff them, and the release and backport checks, which read git history;
- the server-externals check, whose docs side is a Markdown table alint can't extract values from reliably;
- matching each package directory to its package name, such as
packages/andfont @next/, which has no rule kind yet.font