forbidden
The from units must not import the to units, directly or through any chain
of imports.
Example
[contracts.client-safety]
type = "forbidden"
name = "Client components never reach server-only code"
from = [{ path = "web/src/**", directive = "use client" }]
to = ["npm:sharp", "node:*", "npm:server-only"]
guidance = "Keep server-only modules out of client bundles."
upload.tsx reaches npm:sharp through lib/images.ts: one violation, shown with its chain.No file under web/src that starts with "use client" may reach sharp, a
Node builtin or server-only. Each client file is a unit of its own, so a
violation names it and shows the chain, such as
web/src/components/upload.tsx → web/src/lib/images.ts → npm:sharp.
Server components and route handlers are unaffected, since they have no
"use client".
Each pair of units is one violation, with every chain between them, shortest first: as in import-linter, once a chain is found its imports are set aside, and the search runs again until no chain is left.
Options
| Option | Default | |
|---|---|---|
from | required | Selectors. |
to | required | Selectors, which may be external packages and builtins. |
allow_indirect_imports | false | Only direct imports count. |
Common options
Like every contract type, forbidden also takes:
| Option | Default | |
|---|---|---|
type | required | The contract type, such as "layers". |
name | the id | The title shown in the output. |
severity | "error" | "warn" reports a broken contract without failing the check, for rolling a contract out gradually. |
exclude_kinds | [analysis] exclude_kinds | The import kinds to leave out, e.g. ["type"]. |
reexports | [analysis] reexports | "transparent" sees an import of names from a [pass-through module](../concepts.md#pass-through modules) as imports of the modules that define them, as bundlers load them; "opaque" as an import of the pass-through module. Not for encapsulation. |
ignore_imports | [] | "<selector> -> <selector>" entries: the direct imports between them are left out of the contract. |
unmatched_ignore_imports | "error" | Whether an ignore_imports entry that matches no import breaks the contract ("error"), is a warning ("warn") or is fine ("none"). |
guidance | none | Text shown under each violation, such as how to fix it. |