Skip to content

nxrobins/viewspec

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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 demos and interactive playground

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:

  1. Exactly-once provenance. Every data binding is routed exactly once. Nothing dropped. Nothing duplicated. Nothing hallucinated.

  2. Semantic grouping. Data is grouped by meaning, not by visual adjacency.

  3. Strict ordering. The original data order is preserved as a mathematical guarantee.

Install

pip install viewspec

Requires Python 3.11+.

Demos

Six interactive demos 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 cost at runtime — deterministic Python, ~3ms per compile
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
Enterprise Contact Custom

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 lines
  • kpi_dashboard.py — KPI dashboard with style tokens
  • comparison_view.py — Side-by-side comparison
  • emit_html.py — Load a compiled AST and emit HTML

License

MIT

About

ViewSpec: Universal UI from semantic data.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages