Modules
An NX file is still a module, but imports now target libraries. A library is a directory whose .nx
files contribute declarations recursively. For the full grammar, see
nx-grammar.md.
File Layout
Section titled “File Layout”- Imports appear at the top of the file and pull in declarations from library directories.
- Local declarations use
let,type,action, orcomponent. - A
visualizerdeclaration says how a viewer presents one of those declarations. See Visualizer declarations. - A module may export a root element directly or expose named bindings.
import "./theme"import { Button, Input } from "./ui"import { Stack as Layout.Stack } from "./layout"
let greeting = "Hello"private let <WelcomeMessage/> = <span>Hello World</span>export let accentName = "hello"
<Layout.Stack> <text>{accentName}</text> <WelcomeMessage/> <Button/> <Input/></Layout.Stack>Imports
Section titled “Imports”import "<library>"brings every visible export into scope unqualified.import "<library>" as Namespacekeeps imported symbols underNamespace.import { Name } from "<library>"imports specific declarations without qualification.import { Name as Prefix.Name } from "<library>"adds only a qualification prefix; the final segment must remainName.- Importing the same library path twice in one file is a compile error.
- If two libraries export the same unqualified name, NX reports an error only when that ambiguous name is used.
import "@nx/<name>"imports a standard library in any of the forms above. The path is not relative to the importing file, so it is written the same way everywhere.- Local directory libraries are supported today. Git directory URLs and HTTP zip URLs parse, but currently resolve with a “not yet supported” diagnostic.
Libraries
Section titled “Libraries”- A library is a directory, not a barrel file.
- Every
.nxfile under that directory contributes declarations recursively. - Declarations are internal by default, so helper bindings stay inside the library unless marked
export.
Built-in declarations
Section titled “Built-in declarations”NX’s built-in types are declared in the NX prelude, a module every file imports automatically. Nothing names it and nothing enables it: its exported declarations are simply in scope in every module, in every build — a single file, a workspace, a library, an editor session.
- The prelude lives under the reserved
@nx/root, as the module@nx/prelude.nx. The whole root is reserved: a workspace may not supply a module under it, and a host may not load a library there. - Its names are shadowable. A declaration of your own, or a name from any import you wrote, takes the name silently, exactly as it would over a wildcard import. There is no diagnostic and no ambiguity: a prelude name is bound last, and only where nothing else claimed it.
- Shadowing a built-in disables the syntax that means it. A module that declares its own
Rangecannot use..or..=there, because those operators construct the prelude’sRange; the element form still works, and every other module is unaffected. - A library’s exports are its own declarations. The prelude is never re-exported.
The prelude is one ordinary NX declaration:
export type Range = { T:type start:T end:T endInclusive:boolean}See Ranges for what Range means and
for for counting over one.
Standard libraries
Section titled “Standard libraries”A standard library contains compiler-owned declarations, expressed in NX source or provided
by the runtime, and is in scope only where it is imported. It is named by the reserved root @nx/<name>:
import "@nx/agent"
let assistant = <Agent name="support">Be brief.</Agent>- Nothing has to be installed, loaded or enabled. The import resolves in every build and tool: a
single file, a workspace, a library, an editor session,
nxlang. - Every import form works:
import "@nx/agent",import "@nx/agent" as Ai, andimport { Agent, Tool } from "@nx/agent". - Without the import the library’s names are not in scope, so a file that declares its own
Toolis unaffected. Once imported it behaves as any library does: a name it shares with another import is an error only where the name is used, and importing it twice is a compile error. - A path under
@nx/that names no standard library is an error that lists the ones that exist. A library’s modules are not importable on their own, soimport "@nx/agent/agent.nx"is the same error. - A host can put a standard library in scope for the source it compiles, so authored files need no import line.
| Library | Stability | What it holds |
|---|---|---|
@nx/agent |
unstable | Types for declaring an AI agent, its documents and its tools |
@nx/geometry |
unstable | Shared float64 Point, Size, and Rect values with numeric constraints |
@nx/graphics |
unstable | Standalone drawings and ordinary shape helpers for Rust/TypeScript IR runtimes |
@nx/math |
unstable | Float64 mathematics, including trigonometry, distances, rounding and interpolation |
@nx/visualizer |
unstable | Records for visualizer declarations, which say how a viewer presents a declaration |
An unstable library may change incompatibly in any NX release, including a patch release. A stable one changes incompatibly only in a release whose version marks a breaking change.
Visualizer declarations
Section titled “Visualizer declarations”A module can also hold visualizer declarations, written visualizer Target = Value. Each one tells a
viewer, such as the reading view of a source file, how to present one declaration: which property
is an element’s title, which one identifies it, and what icon marks it. The value is built
from the records of @nx/visualizer:
import "@nx/visualizer"
type Choice = { value:string label:string description?:string }
visualizer Choice = <ElementVisualizer title=label id=value idPosition=end />visualizeris a keyword only as the first token of a module member. A prop, field, binding or function namedvisualizerkeeps working.- A visualizer declaration declares no name and takes no visibility modifier. It applies wherever its module is loaded, without being exported or imported.
- It can sit beside the declaration it describes or in any module that can see it, with the same syntax in both places.
- It runs nothing: it does not reach NX IR, generated code or a declaration schema.
See Visualizer Declarations for what a visualizer declaration can say and how visualizer declarations from several modules combine.
Root Elements
Section titled “Root Elements”- A root element at the end of the file behaves like
main. Tooling can render it immediately or expose it as the module default. - Alternatively, export named bindings and let consumers choose what to render.
Visibility
Section titled “Visibility”| Keyword | Same file | Other library files | Consumers |
|---|---|---|---|
private |
Yes | No | No |
| default | Yes | Yes | No |
export |
Yes | Yes | Yes |
privatekeeps declarations in the current file only.- Omitting a visibility keyword shares declarations across files in the same library or program while hiding them from external consumers.
exportexposes declarations to importing libraries.
See also
Section titled “See also”- Language Tour: Modules & Imports
- Grammar: nx-grammar.md – Module Definition