Universal UI from semantic data. Describe what your data means — the compiler figures out how it looks.
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file viewspec-0.2.0.tar.gz.
File metadata
- Download URL: viewspec-0.2.0.tar.gz
- Upload date:
- Size: 162.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2270dfd88f9d9056edae9bb2febfb353bfa700865629f468dbc61b5fb7e93a8b
|
|
| MD5 |
9f0ea3e4c7eca48b4053badc43009b2f
|
|
| BLAKE2b-256 |
01f3b1a366ec841ad44a252992ec16818f73d9b32ccd9f14d159cc6bd35e3300
|
File details
Details for the file viewspec-0.2.0-py3-none-any.whl.
File metadata
- Download URL: viewspec-0.2.0-py3-none-any.whl
- Upload date:
- Size: 35.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cf56bb9a5f242173125b2e838b97a3389adf2ccef03bce12ee4f781f5e32fd61
|
|
| MD5 |
5a28daf8eb3ba5abf91db632b4de9178
|
|
| BLAKE2b-256 |
ee60dd3e88f3d30f061b23c4cddd07ddcd3ac4c6edd6b7dbc14cb8cde44fb8ca
|