ViewSpec
Universal UI from semantic data.
ViewSpec is a declarative language for describing what data means. The compiler figures out how it looks. Every pixel has a birth certificate.
🌐 viewspec.dev — Live hosted compiler playground, demos, and pricing
from viewspec import ViewSpecBuilder, compile
from viewspec.emitters.html_tailwind import HtmlTailwindEmitter
builder = ViewSpecBuilder("invoice")
table = builder.add_table("items", region="main", group_id="rows")
table.add_row(label="Design System Audit", value="$4,200")
table.add_row(label="Component Library", value="$8,500")
table.add_row(label="API Integration", value="$3,100")
ast = compile(builder.build_bundle())
HtmlTailwindEmitter().emit(ast, "output/")
# That's it. Full UI. Full provenance. No CSS.
What ViewSpec Does
Before ViewSpec: You manually bridge the gap between data and UI. Every component, every prop, every layout decision — hand-wired by a developer.
After ViewSpec: You declare what the data means. The compiler determines the visual structure. Rendering is a pluggable backend.
Data → ViewSpec (semantic intent) → Compiler → CompositionIR → Emitter
├── HTML/Tailwind (shipped)
├── Canvas/Pretext
├── PDF
├── Native mobile
└── Your custom emitter
Three Invariants
ViewSpec enforces three mathematical guarantees:
-
Exactly-once provenance. Every data binding is routed exactly once. Nothing dropped. Nothing duplicated. Nothing hallucinated.
-
Semantic grouping. Data is grouped by meaning, not by visual adjacency.
-
Strict ordering. The original data order is preserved as a mathematical guarantee.
Install
pip install viewspec
Requires Python 3.11+.
Hosted Playground
The home page at viewspec.dev runs a live hosted compile against https://api.viewspec.dev/v1/compile. It uses anonymous free-tier requests by default and shows the request, response, measured compile_ms, active derivation tokens, and provenance chain.
Agent and crawler entrypoints are published with the static site:
https://viewspec.dev/llms.txt— concise LLM-facing product maphttps://viewspec.dev/llms-full.txt— expanded AI context and canonical factshttps://viewspec.dev/agent-system-prompt.txt— system prompt for agents that emitIntentBundleJSONhttps://viewspec.dev/agent-intent-bundle.schema.json— JSON schema for agent-authored compiler inputhttps://viewspec.dev/openapi.json— hosted compiler OpenAPI descriptionhttps://viewspec.dev/sitemap.xml— canonical page sitemap
Runtime landing-page config is read from window.VIEWSPEC_LANDING_CONFIG:
| Key | Purpose |
|---|---|
apiUrl |
Hosted compiler endpoint. Defaults to https://api.viewspec.dev/v1/compile. |
fallbackApiUrls |
Optional fallback compiler endpoints for landing-page availability during custom-domain cutovers. |
endpointStaggerMs |
Delay before starting fallback endpoint requests. Defaults to 120. |
endpointFailureTtlMs |
How long the browser session keeps a failed endpoint out of the hot path. Defaults to 300000. |
publicApiKey |
Optional browser-safe public/demo key. window.PUBLIC_LANDING_API_KEY is also accepted. Omit it to use anonymous free-tier demo traffic. |
proStripeUrl |
Pro checkout link. Defaults to the live Stripe payment link. |
scaleStripeUrl |
Scale checkout link. Defaults to the live Stripe payment link. |
signupUrl |
Free CTA or pricing URL. Defaults to https://viewspec.dev/#pricing. |
requestTimeoutMs |
Hosted compile timeout. Defaults to 6000. |
Keep secret API keys server-side; only browser-safe public/demo keys belong in static landing-page config.
Demos
The hosted playground plus six reference demos are available at viewspec.dev:
| Demo | What it shows |
|---|---|
| Same Data, Three Motifs | One dataset → table, dashboard, or comparison. Change one parameter. |
| Provenance Inspector | Hover any element. Trace DOM → IR → binding → address → raw data. |
| Live Builder | Browse ViewSpec JSON, IR tree, and rendered output in sync. |
| The Invariants | Watch the compiler enforce — and refuse — each guarantee. |
| 15 Lines → Full UI | An invoice table builds itself from 15 lines of Python. |
| Style Derivation | Same structure, different feel. Toggle four visual presets. |
Text rendering powered by Pretext canvas surfaces.
Core Concepts
Semantic Substrate
The raw data graph. Nodes with typed attributes, slots, and edges. This is WHAT the data is — no visual intent.
builder = ViewSpecBuilder("my_view")
builder.add_node("user_1", "person", attrs={"name": "Alice", "role": "Engineer"})
builder.add_node("user_2", "person", attrs={"name": "Bob", "role": "Designer"})
ViewSpec
The declarative intent layer. Regions (WHERE data can go), bindings (WHICH data goes WHERE), motifs (HOW it should be structured), and styles (how it should FEEL).
table = builder.add_table("team", region="main", group_id="members")
table.add_row(label="Alice", value="Engineer")
table.add_row(label="Bob", value="Designer")
CompositionIR
The compiler's output. A strict hierarchical tree of 12 UI primitives (root, stack, grid, cluster, surface, text, label, value, badge, image_slot, rule, svg) with full provenance tracking. Every IR node knows which semantic addresses and intent refs produced it.
Emitters
Pluggable renderers that turn CompositionIR into concrete output. Subclass EmitterPlugin:
from viewspec.emitters.base import EmitterPlugin
class MyEmitter(EmitterPlugin):
def emit(self, ast_bundle, output_dir):
# Walk ast_bundle.result.root.root and produce output
...
The included HTML/Tailwind emitter produces standalone HTML with full Tailwind styling, provenance data attributes on every DOM element, action event dispatch, and a JSON provenance manifest.
Motif Types
| Builder | Motif | Use case |
|---|---|---|
add_table() |
table |
Tabular data with label-value rows |
add_dashboard() |
dashboard |
KPI cards with label-value pairs |
add_outline() |
outline |
Hierarchical outlines and trees |
add_comparison() |
comparison |
Side-by-side comparisons |
Each builder returns a chained sub-builder. Compose them freely within a single ViewSpec.
Compilation
Reference Compiler (free, offline)
Handles the four standard motifs locally. No API, no network, no LLM. Deterministic.
ast = compile(builder.build_bundle())
Hosted Compiler (api.viewspec.dev)
For complex layouts, novel data shapes, and advanced derivation. The hosted compiler was evolved (not hand-written) using reinforcement learning:
- 13/13 on a static validation suite
- 50/50 on novel, randomized out-of-distribution layouts (one-shot)
- Level 2 derivation tokens — data-aware emphasis, narrative routing, palette energy
- Zero LLM calls at runtime — deterministic Python compile path; the live playground reports measured
compile_msfor each request
from viewspec import compile_auto
# Try local first, fall back to hosted for unsupported motifs
ast = compile_auto(builder.build_bundle())
| Tier | Price | Hosted Calls/Day |
|---|---|---|
| Free | $0 | 500 |
| Pro | $39/mo | 25,000 |
| Scale | $99/mo | 250,000 |
Wire Format
Protocol Buffers for language-agnostic serialization. The same ViewSpec can be constructed in Python, Rust, Go, TypeScript, or any language with protobuf support.
bundle = builder.build_bundle()
json_data = bundle.to_json() # JSON round-trip
proto_bytes = bundle.to_proto().SerializeToString() # Protobuf round-trip
Examples
See examples/:
invoice_table.py— Build a table in 15 lineskpi_dashboard.py— KPI dashboard with style tokenscomparison_view.py— Side-by-side comparisonemit_html.py— Load a compiled AST and emit HTML
License
MIT
Release files for viewspec 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| viewspec-0.2.0.tar.gz | 162.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| viewspec-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 198.2 kB
Release files / viewspec-0.2.0.tar.gz
| Download URL | viewspec-0.2.0.tar.gz |
|---|---|
| Size | 162.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2270dfd88f9d9056edae9bb2febfb353bfa700865629f468dbc61b5fb7e93a8b
|
|
BLAKE2b-256 checksum How to use checksums |
01f3b1a366ec841ad44a252992ec16818f73d9b32ccd9f14d159cc6bd35e3300
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / viewspec-0.2.0-py3-none-any.whl
| Download URL | viewspec-0.2.0-py3-none-any.whl |
|---|---|
| Size | 35.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cf56bb9a5f242173125b2e838b97a3389adf2ccef03bce12ee4f781f5e32fd61
|
|
BLAKE2b-256 checksum How to use checksums |
ee60dd3e88f3d30f061b23c4cddd07ddcd3ac4c6edd6b7dbc14cb8cde44fb8ca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|