Skip to main content
After running xspec build, each NAME.mdx specification file is compiled into a typed TypeScript module that you can import directly into your source code. These generated modules expose a structured graph of your requirements as opaque, fully typed tokens — giving you editor autocomplete, hover documentation, and go-to-definition on every requirement node.

Basic import syntax

Import a compiled spec module using a specifier that mirrors the source .mdx path with the extension replaced by .xspec:
Two bindings are permitted:
  • Default export — the root node of the spec. All child sections are accessible as typed properties on this object.
  • Named text export — a function for retrieving a node’s requirement text at runtime (covered in detail on the Markers & text() page).
Both bindings can be aliased and are independently optional. You may import one without the other.
The specifier must be a relative path ending in .xspec. It must not point to the generated implementation files directly — importing ./AUTH.xspec.ts, ./AUTH.xspec.impl.js, or similar underlying filenames is not supported and will be treated as an error by the xspec toolchain.

Type-only imports

If you only need to reference the spec’s types — for example in a typeof expression or a type annotation — you can use a type-only import:
Type-only imports are fully supported. Because they carry no value-level binding, xspec records no edges for them. They are useful when you want type safety without affecting the dependency graph.

Invalid import forms

The following import patterns are not permitted and will be flagged as build errors:
Only static import declarations using .xspec specifiers are valid.

Accessing nodes

The default export is the root node of the spec. Child sections defined by <S> headings in the source MDX are exposed as readonly typed properties, forming a path that mirrors your document’s heading hierarchy. Use dot notation for identifier-safe segment names:
Use bracket notation with string literals for segments that are not valid JavaScript identifiers:
Dot and bracket accesses can be freely mixed:
Accessing a path that does not exist in the spec, or misspelling a segment name, produces a TypeScript type error at the point of access. The spec structure is fully reflected in the generated types, so your editor’s type checker enforces correctness without any runtime validation.
Nodes carry no text as values — you cannot read requirement content directly from a node expression. Use text(node) to retrieve the requirement text as a string at runtime.

Hover documentation and go-to-definition

Every node has a JSDoc comment attached to its type that contains the requirement’s own text (truncated to 1000 characters). When you hover over a node expression in a compatible editor such as VS Code, you will see the requirement text inline — without leaving your implementation file. Go-to-definition on a node jumps directly to the corresponding <S> section in the .mdx source file, via the declaration map emitted alongside the generated types. This works out of the box with any editor that supports TypeScript’s language server and source maps.