How `native check` Performs Markup Validation and Reports File:Line:Column Errors in Native SDK Apps
native check scans the src/ directory for .native markup files, validates them via markup_cli.checkFiles, and emits precise file:line:column diagnostics that let developers jump straight to the source of any error—without ever building the app.
As implemented in vercel-labs/native, the native check command provides fast, build-free validation for Native SDK applications. Its markup validation pipeline checks TypeScript cores, .native files, and the app.zon manifest while surfacing every issue with exact file, line, and column coordinates.
The native check Markup Validation Pipeline
In tools/native-sdk/main.zig, the native check entry point orchestrates a six-stage pipeline that validates the whole app without producing a build.
Locate the App Manifest
First, native check looks for an app.zon file in the current directory—or the directory you pass—to confirm it is inside a Native SDK app. If the file is missing, the command aborts immediately with a MissingManifest error.
Run the TypeScript Core Checker
If the app uses a TypeScript core, native check runs the @native-sdk/core subset checker before any markup validation. This ensures TypeScript diagnostics are collected and reported alongside markup issues.
Collect Markup Files
The command invokes collectMarkupFiles, defined in tools/native-sdk/markup.zig, to recursively walk src/ and gather every file whose extension matches a markup file—specifically .native. The function returns a list of absolute paths that are fed into the validator.
Validate Markup Files
The collected paths are passed to markup_cli.checkFiles. The validator returns a CheckOutcome structure containing the count of failures, warnings, and whether the model-contract was checked. This stage is where markup syntax and semantics are evaluated against the app's contract.
Validate the Manifest
After markup checks, app.zon is parsed and validated using tooling.manifest.validateFile from src/tooling/manifest.zig. Any manifest problems are printed, and if validation fails, the command exits with an error.
Report Results and Strict Mode
Finally, native check prints a one-line summary such as:
checked 3 markup files against the model contract, app.zon
If you pass the --strict flag, warnings are promoted to errors, causing the command to fail even when only warnings are present.
File:Line:Column Error Format in Markup Diagnostics
When the markup compiler finds a problem, it prints diagnostics in a file:line:column format that editors and terminals can parse directly. According to the vercel-labs/native README:
"
native checkvalidates every view … with file:line:column errors that teach."
The underlying diagnostics are generated by src/primitives/canvas/ui_markup.zig. Inside the markup compiler, the printDiagnostic logic attaches source locations to each node and formats them as file:line:column when emitting errors.
A typical CLI output looks like this:
# Example error output
src/app.native:12:5: unknown tag "buttonn" (did you mean "button"?)
This pinpoint output eliminates guesswork and allows IDEs to jump directly to the offending line and column.
Running native check from the Command Line
You invoke the validator from inside an app directory. The following examples show the standard and strict modes:
# Validate TS core, markup, and app.zon
native check
# Promote warnings to errors
native check --strict
Because validation runs without a build step, the feedback loop is nearly instantaneous.
Key Source Files Behind native check
Understanding the architecture is easier when you know which files handle each responsibility:
tools/native-sdk/main.zig— The CLI entry point that orchestrates the core checker, markup validation, and manifest verification.tools/native-sdk/markup.zig— ImplementscollectMarkupFilesand theCheckOutcomestructure; invokes the markup validator viacheckFiles.src/primitives/canvas/ui_markup.zig— The markup compiler that parses.nativefiles and emits diagnostics with file:line:column source locations throughprintDiagnostic.src/tooling/manifest.zig— Parses and validatesapp.zon, providing manifest-level diagnostics.
Summary
native checkvalidates an entire Native SDK app without building it.- The pipeline runs the TS core checker, collects
.nativefiles fromsrc/, validates markup viamarkup_cli.checkFiles, and verifiesapp.zonthroughtooling.manifest.validateFile. - Failures and warnings are aggregated in a
CheckOutcome, and results are summarized on the command line. - Diagnostics use a precise file:line:column format generated by
src/primitives/canvas/ui_markup.zig, enabling direct navigation to errors. - The
--strictflag elevates warnings to errors for more stringent CI/CD gates.
Frequently Asked Questions
What does native check validate besides markup?
native check validates three layers: the TypeScript core (if the app uses one), every .native markup file under src/, and the app.zon manifest. Any failure in these layers causes the command to exit with an error.
How does native check locate markup files to validate?
It calls collectMarkupFiles in tools/native-sdk/markup.zig, which recursively walks src/ and selects every file with a .native extension. These absolute paths are then passed to the markup validator.
What happens when --strict is passed to native check?
When --strict is used, all warnings collected in the CheckOutcome are promoted to errors. This guarantees that even minor markup or manifest issues will fail the command, which is useful for enforcing quality gates in continuous integration.
Where are the file:line:column diagnostics generated?
The diagnostics are generated inside src/primitives/canvas/ui_markup.zig by the markup compiler. Its printDiagnostic logic maps each AST node back to its source location and formats the output as file:line:column so that editors and terminals can resolve the exact point of failure.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →