The host-agnostic engine behind Spytial. Integrate spatial diagramming into your language.
spytial-core is the browser-side engine that turns relational data + a YAML spec of spatial constraints into a rendered diagram. It is not a tool for end users — it is the piece you embed when you want Spytial in a new host (a language, an IDE, a notebook, a debugger).
If you want to render Python objects, use sPyTial. If you want to render Rust values, use Caraspace. If you want to render Pyret values, use Spyret. If you want to add a new host to that list — read on.
The full guide is published from site/ and rendered with Docsify.
The structure mirrors the integrator's job:
- Overview — What is spytial-core? · The Integration Pipeline · Quick Start
- Integrating Spytial Into a Language — New Language Integration · Custom Data Instances
- Data — JSON Data Format · Built-in Adapters
- The YAML Spec Language — YAML Reference · Constraints · Directives · Selector Syntax
- Sequences of States — Sequence Layouts
- API Reference — Exported API
- Cookbook — Examples
To browse the guide locally:
npm run serve # python3 -m http.server 8080
# open http://localhost:8080/site/NPM:
npm install spytial-coreCDN:
<script src="https://cdn.jsdelivr.net/npm/spytial-core/dist/browser/spytial-core-complete.global.js"></script>That is the only script tag you need. The bundle carries its own d3 v4 and WebCola, and it will not replace a window.d3 your page already has.
For reproducibility, pin a version (e.g. spytial-core@5.3.0).
import {
JSONDataInstance,
parseLayoutSpec,
SGraphQueryEvaluator,
LayoutInstance,
} from 'spytial-core';
const instance = new JSONDataInstance(jsonPayload);
const spec = parseLayoutSpec(yamlSpec);
const evaluator = new SGraphQueryEvaluator();
evaluator.initialize({ sourceData: instance });
const generatedLayout = new LayoutInstance(spec, evaluator).generateLayout(instance);
document.querySelector('webcola-cnd-graph').renderLayout(generatedLayout.layout);That's the entire core pipeline. Where jsonPayload and yamlSpec come from is the host integrator's job — see the Quick Start for a self-contained HTML example, and New Language Integration for the principled framing.
| Layer | Highlights |
|---|---|
| Data instances | JSONDataInstance, AlloyDataInstance, DotDataInstance, PyretDataInstance, TlaDataInstance, plus the IDataInstance interface for custom adapters. |
| Spec language | YAML constraints (orientation, align, cyclic, group, size, hideAtom) and directives (atomStyle, edgeStyle, icon, attribute, tag, inferredEdge, flag, …). |
| Selector engine | SGraphQueryEvaluator (Forge-style relational expressions) plus optional Forge / SQL evaluators. |
| Layout solver | LayoutInstance + QualitativeConstraintValidator — qualitative spatial constraints with IIS reporting. |
| Renderers | <webcola-cnd-graph> (visual), <spytial-explorer> (a11y + spatial REPL; opt-in via spytial-core/explorer since 4.0.0), AccessibleTranslator (semantic HTML / alt-text). |
| Sequence support | Pairwise policies (stability, changeEmphasis, randomPositioning, …) for inter-frame continuity. Custom policies via registerSequencePolicy. |
| Selector synthesis | Generate CnD selectors from positive/negative atom or pair examples. |
| React components | CndLayoutInterface, ErrorMessageContainer — via spytial-core/react (npm) or the components CDN bundle; kept out of the default entry since 4.0.0. To author a data instance, use the <structured-input-graph> custom element rather than a React component. |
Full export surface: API Reference.
If your integration generates specs, don't scrape the Markdown. Every release ships a machine-readable description of the spec language — attached to the GitHub release, included in the npm package, and pinnable per tag over jsDelivr:
| Artifact | What it is |
|---|---|
docs/spytial-language.json |
Every constraint and directive: fields, requiredness, legal values, engine defaults, and each deprecated form with the rewrite that replaces it. |
docs/spytial-spec.schema.json |
JSON Schema (draft 2020-12) for validating a spec document. Stricter than the parser, which silently ignores what it does not recognize. |
docs/YAML_SPECIFICATION.md |
The prose reference, for humans. |
https://cdn.jsdelivr.net/gh/sidprasad/spytial-core@<tag-or-sha>/docs/spytial-language.json
The language is versioned by the date it last changed:
const manifest = await fetch(url).then(r => r.json());
manifest.languageVersion; // e.g. "2026-07-28" — when the language last moved
manifest.spytialCoreVersion; // e.g. "4.2.0" — the release that produced this file
manifest.deprecations; // every deprecated form, with the rewrite that replaces itA date, not a semver: the language is a vocabulary, not an API surface with a compatibility contract to encode, and the date answers the one question a code generator has — is what I generated against still current? If it hasn't moved since the manifest you built against, nothing you emit needs revisiting. A deprecated form keeps parsing and keeps its meaning for as long as the manifest lists it. Removal is signalled by languageVersion moving, not by the package major — a removed form leaves the manifest and becomes a parse error, so check languageVersion before assuming an older spec still parses.
From TypeScript the same data is available without a fetch:
import { getLanguageManifest, LANGUAGE_VERSION } from 'spytial-core';The manifest is regenerated and re-verified against the parser in CI (npm run test:language), so a form it describes is a form the engine actually implements.
- Fork the repository
- Create your feature branch (
git checkout -b feature/...) - Run
npm run build:allandnpm run test:run - Open a Pull Request
The dev-loop reference is in docs/DEV_GUIDE.md.
MIT