DocSpec lint playground
A DocSpec is the token-frugal JSON grammar of pdfnative-react: plain data — positional tuples such as ["h1", "Invoice"] under a handful of top-level fields — that agents emit and a CMS can store, and that compiles to exactly the same document as the equivalent JSX. Paste one below (or pick a preset), click Lint, and the page runs validateSpec then lintSpec in your browser; when the report carries no error, Render PDF hands the very same spec to renderSpecToBytes. Grammar and field reference: Agent authoring — the token-frugal DocSpec; where it fits: use cases.
What lint checks. The authoring model, not the bytes. validateSpec is the shape tier — unknown tuple kind, wrong arity, wrong payload type, path-anchored (blocks[3][1]) and it never throws. lintSpec compiles the spec once and applies 41 rules with stable L_* codes in pdfnative-react 1.4.0 (26 errors, 14 warnings, 1 info): twenty-three of them pre-empt an exception the engine raises at build time (the nine L_CHART_* errors — L_CHART_SERIES_COLORS since 1.4.0 — print geometry, the two spot-colour rules L_SPOT_UNDECLARED and L_SPOT_INK_MIX, the six PDF/X coherence rules, the output-intent profile check…), six mirror an engine diagnostic that becomes a throw under layout.strict (L_PDFA_JPX_IMAGE, a JPEG 2000 image under a PDF/A claim, among them), and the rest catch accessibility gaps (alt text, header rows, heading hierarchy, link text, field labels) or output that renders but is wrong (an empty document, a PDF/A or PDF/X claim without embedded fonts, overflow, a colour-bar strip too thin to measure). One rule relaxed in 1.4.0: L_PDFX_TAGGED_CONFLICT only fires for tagged: 'pdfa1b' or 'pdfa3b' beside pdfx — engine 1.9.0 writes PDF/A-2b or PDF/A-2u and PDF/X-4 as one file carrying both claims. Gate on report.ok, which is true when no finding has severity error.
tagged) still needs an external veraPDF run on the bytes, and a PDF/X-4 claim (pdfx) still needs the engine's validatePdfX() report afterwards — try it in the Print & PDF/X playground. No preset here embeds fonts, so the PDF/A, PDF/X and dual-claim presets stop at the linter on purpose: the rules that fire are exactly the ones that would have made those files non-conformant. The img block takes its bytes as a Uint8Array, which JSON cannot carry, so the JPEG 2000 rule (L_PDFA_JPX_IMAGE) has no preset on this page — it is exercised in the React renderer playground.
DocSpec JSON
Lint report
Click “Lint →” to run validateSpec and lintSpec on the spec.
PDF preview
The rule table
Built at load from the package's own LINT_RULES export — id, severity and description come from pdfnative-react, not from this page. Rows highlighted in yellow fired in the last lint run. Branch on the code, never on the message: messages may be reworded in any release, codes may not.
| Rule | Severity | Description |
|---|
The same loop in Node
The page calls the three exports below straight from the CDN build; in a project you install pdfnative-react from npm (React 19 is its peer dependency, pdfnative its engine) and run the identical sequence. The snippet tracks the selected preset.
pdfnative-react 1.4.0 and pdfnative 1.9.0 are imported from the esm.sh CDN through an import map, purely to make a zero-install browser demo; nothing is uploaded and the PDF is produced on your device. No JSX is involved, so there is no transpiler on this page. This CDN tooling does not affect the published packages: the core pdfnative engine stays zero-dependency, and React is a peer dependency of pdfnative-react only.