0x-lang
v0.1.29
Published
0x — AI-First Programming Language Compiler
Maintainers
Readme
What is this?
0x is a tiny language for building apps. You describe what you want, and the compiler outputs production-ready React, Vue, Svelte, Express backends, React Native mobile apps, or Terraform infrastructure.
page Counter:
state count: int = 0
fn increment():
count += 1
layout col gap=16 padding=24 center:
text "Counter" size=2xl bold
text "{count}" size=4xl color=cyan
button "+1" style=primary -> increment()That's a complete component. Run 0x build counter.ai --target react and you get a working React component with useState, event handlers, and full styling. Same source also compiles to Vue 3, Svelte 5, and React Native.
Why? Most code is boilerplate — imports, hook calls, JSX wrappers, style objects, closing tags, Express middleware, Terraform blocks. 0x skips all of that. You write what matters, the compiler handles the rest.
The numbers
| Component | 0x | React | You save | |:---|:---:|:---:|:---:| | Counter | 18 lines | 96 lines | 81% | | Todo App | 24 lines | 136 lines | 82% | | Dashboard | 37 lines | ~185 lines | 80% | | Chat App | 31 lines | ~155 lines | 80% | | E-commerce | 44 lines | ~210 lines | 79% |
Compared against production TypeScript React with full inline styling, types, and component structure.
Quick Start
npm install -g 0x-langCreate a file called hello.ai:
page Hello:
state name: str = "World"
layout col gap=16 padding=24 center:
text "Hello, {name}!" size=3xl bold
input name placeholder="Your name"Compile it:
# Frontend
0x build hello.ai --target react
0x build hello.ai --target vue
0x build hello.ai --target svelte
# Mobile
0x build app.ai --target react-native
# Backend
0x build server.ai --target backend
# Infrastructure
0x build infra.ai --target terraform
# Or multiple at once
0x build hello.ai --target react,vue,svelteScaffold a project
0x init my-app
cd my-app
0x build src/counter.ai --target reactWatch mode
0x dev counter.ai --target reactFile changes auto-recompile.
Examples
Todo App — 24 lines
page Todo:
type Item = {id: int, text: str, done: bool}
state items: list[Item] = []
state input: str = ""
derived remaining = items.filter(i => !i.done).length
fn add():
if input.trim() != "":
items.push({id: Date.now(), text: input, done: false})
input = ""
fn remove(id: int):
items = items.filter(i => i.id != id)
layout col gap=16 padding=24 maxWidth=600 margin=auto:
text "Todo ({remaining} remaining)" size=2xl bold
layout row gap=8:
input input placeholder="What needs to be done?"
button "Add" style=primary -> add()
for item in items:
layout row gap=8 center:
toggle item.done
text item.text strike={item.done}
button "Delete" style=danger size=sm -> remove(item.id)
if items.length == 0:
text "Nothing to do" color=#999 centerTypes, filtering, conditional rendering, two-way binding — all handled. Compiles to 136 lines of production React.
Dashboard with API calls — 37 lines
page Dashboard:
type Metric = {label: str, value: float, change: float}
state metrics: list[Metric] = []
state period: str = "week"
state loading: bool = true
api getMetrics = GET "/api/metrics"
on mount:
metrics = await getMetrics(period: period)
loading = false
watch period:
loading = true
metrics = await getMetrics(period: period)
loading = false
layout col gap=24 padding=32:
layout row between center:
text "Dashboard" size=3xl bold
select period options=["day", "week", "month", "year"]
if loading:
text "Loading..." center
else:
layout grid cols=3 gap=16:
for metric in metrics:
component MetricCard(metric)
component MetricCard:
prop metric: Metric
derived isPositive = metric.change >= 0
derived changeColor = isPositive ? "green" : "red"
layout col gap=8 padding=24 radius=12 shadow=md bg=white:
text metric.label size=sm color=#666
text "{metric.value}" size=2xl bold
text "{isPositive ? '↑' : '↓'} {metric.change}%" size=sm color={changeColor}Async data fetching, loading states, watchers, grid layouts, reusable child components.
Chat App — 31 lines
page Chat:
type Message = {id: int, text: str, sender: str, time: datetime}
state messages: list[Message] = []
state input: str = ""
state username: str = "Me"
fn send():
if input.trim() != "":
messages.push({id: Date.now(), text: input, sender: username, time: now()})
input = ""
layout col height=100vh:
layout row center padding=16 bg=#075e54:
text "Chat" size=lg bold color=white
layout col gap=8 padding=16 scroll=y grow=1:
for msg in messages:
layout row {msg.sender == username ? "end" : "start"}:
layout col padding=12 radius=12 maxWidth="70%" bg={msg.sender == username ? "#dcf8c6" : "white"} shadow=sm:
text msg.text
text msg.time.format("HH:mm") size=xs color=#999 end
layout row gap=8 padding=16 bg=#f0f0f0:
input input placeholder="Type a message..." grow=1
button "Send" style=primary -> send()E-commerce — 44 lines
page Shop:
type Product = {id: int, name: str, price: float, image: str}
type CartItem = {product: Product, qty: int}
state products: list[Product] = []
state cart: list[CartItem] = []
state search: str = ""
state loading: bool = true
derived filteredProducts = products.filter(p => p.name.includes(search))
derived cartTotal = cart.reduce((sum, item) => sum + item.product.price * item.qty, 0)
derived cartCount = cart.reduce((sum, item) => sum + item.qty, 0)
api getProducts = GET "/api/products"
on mount:
products = await getProducts()
loading = false
fn addToCart(product: Product):
existing = cart.find(item => item.product.id == product.id)
if existing:
existing.qty += 1
else:
cart.push({product: product, qty: 1})
fn removeFromCart(productId: int):
cart = cart.filter(item => item.product.id != productId)
layout col gap=24 padding=32:
layout row between center:
text "Shop" size=3xl bold
layout row gap=8 center:
text "Cart ({cartCount})" size=lg
text "${cartTotal}" size=lg bold color=#e74c3c
input search placeholder="Search products..."
if loading:
text "Loading..." center
else:
layout grid cols=3 gap=16:
for product in filteredProducts:
layout col gap=8 padding=16 radius=12 shadow=md bg=white:
image product.image width="100%" height=200
text product.name size=lg bold
text "${product.price}" size=md color=#e74c3c
button "Add to Cart" style=primary -> addToCart(product)Backend API — Express server
page API:
model User:
field name: str
field email: str
field role: str = "user"
auth:
secret: JWT_SECRET
endpoint: /auth
route GET /api/users:
users = await db.find("users")
respond 200 users
route POST /api/users:
user = await db.create("users", body)
respond 201 user
env:
DATABASE_URL: "postgres://localhost/mydb"
JWT_SECRET: secretCompiles to a full Express.js server with JWT auth, CORS, error handling, and CRUD routes.
React Native Mobile App
page MobileCounter:
state count: int = 0
fn increment():
count += 1
layout col gap=16 padding=24 center:
text "Counter" size=2xl bold
text "{count}" size=4xl color=cyan
button "+1" style=primary -> increment()Same 0x syntax compiles to React Native with View, Text, TouchableOpacity, and StyleSheet.
Infrastructure — Terraform
page Infra:
deploy myApp:
provider: aws
region: us-east-1
instance: t3.medium
storage assets:
provider: s3
bucket: my-app-assets
versioning: true
domain mysite:
provider: route53
name: "myapp.com"Compiles to Terraform HCL with provider blocks, resource definitions, and variable declarations.
Blog App — 64 lines
page Blog:
state posts: list[Post] = []
state loading: bool = true
data posts from fetch("/api/posts")
layout col gap=24 padding=32:
nav "BlogApp" links=["Home", "Write", "About"]
hero "My Blog" subtitle="Thoughts and tutorials"
for post in posts:
component PostCard(post)Full CRUD blog with data fetching, auth, routing, and reusable components.
CRM Dashboard — 80 lines
page CRM:
data customers from fetch("/api/customers")
state search: str = ""
derived filtered = customers.filter(c => c.name.includes(search))
layout col gap=24 padding=32:
text "CRM Dashboard" size=3xl bold
input search placeholder="Search customers..."
layout grid cols=3 gap=16:
stat "Total" value={customers.length}
stat "Active" value={customers.filter(c => c.active).length}
stat "Revenue" value="$12,500"
table filtered columns=["name", "email", "status", "revenue"]CRM with search, stats, filterable table, and modal forms.
SaaS Landing — 77 lines, Kanban Board — 77 lines, Admin Panel — 91 lines
See all 10 examples in examples/.
IDE / Editor Support
0x includes a built-in Language Server Protocol (LSP) server for IDE integration.
VSCode Extension
Install the 0x VSCode extension for:
- Syntax highlighting — all 73+ keywords color-coded
- Autocomplete — context-aware keyword and identifier completion
- Hover info — documentation for keywords, types for variables
- Go to definition — jump to state, fn, prop declarations
- Document outline — page, component, state, fn in the sidebar
- Real-time diagnostics — parse and validation errors as you type
Other Editors
The LSP server works with any editor that supports LSP:
# Start the LSP server
0x-lsp --stdioConfigure your editor's LSP client to connect to 0x-lsp --stdio for .ai files.
Language Reference
Top-level declarations
page PageName: # Page component (has routing)
component ComponentName: # Reusable component
app AppName: # App rootState
state count: int = 0 # Reactive state
state items: list[Item] = [] # Typed list
derived total = price * quantity # Auto-computed
prop title: str = "Default" # External propTypes
type Item = {id: int, text: str, done: bool}
type User = {name: str, email: str, age: optional[int]}Built-in: int, float, str, bool, list[T], optional[T], datetime, object
Functions
fn increment():
count += 1
fn add(text: str):
items.push({id: Date.now(), text: text, done: false})
async fn fetchData():
data = await api.getData()Layout
layout col gap=16 padding=24: # Vertical (flexbox column)
layout row gap=8 center: # Horizontal (flexbox row)
layout grid cols=3 gap=16: # CSS GridProps: gap, padding, margin, center, between, end, wrap, grow, maxWidth, bg, radius, shadow, scroll
UI Elements
text "Hello" size=2xl bold color=#333 # Text
text "{variable}" size=lg # Dynamic text
button "Click" style=primary -> action() # Button with handler
button "Set" -> count = 0 # Inline mutation
input binding placeholder="Type..." # Two-way binding
toggle binding # Toggle switch
select binding options=["a", "b", "c"] # Dropdown
image src width=100 height=100 # Image
link "Click here" href="/path" # LinkStyling
text "Big" size=2xl bold color=blue # Inline props
button "Go" style=primary size=lg rounded=full # Presets
style card: # Named style block
padding: 24
radius: 12
shadow: md
bg: white
layout col .card: # Apply named style
text "Inside a card"Sizes: xs, sm, md, lg, xl, 2xl, 3xl, 4xl
Button styles: primary, secondary, danger, outline, ghost
CSS Classes & Passthrough Props
layout col class="container mx-auto p-4":
text "Title" class="text-xl font-bold text-blue-600"
button "Save" -> save() class="btn btn-primary"
input name class="form-input" aria-label="Name" data-testid="name-input"class="..."addsclassName(React) orclass(Vue/Svelte) to any element- Works with Tailwind CSS, Bootstrap, or any CSS framework
- Unknown props (
data-*,aria-*,role, etc.) pass through as HTML attributes
Raw Block (Framework Escape Hatch)
raw:
<CustomComponent onSpecialEvent={handler} />
raw { <div dangerouslySetInnerHTML={{__html: content}} /> }raw:inserts code directly into JSX/template output (NOT the script section)- Different from
js:which goes into the script/hook section - Use for third-party components or framework-specific code
Component Children
component Dialog(title="Settings"):
layout col:
text "Content"
button "Close" -> close()
component Card(item) # Self-closing (no children)- When a
componentcall ends with:, indented children are wrapped inside the component - Without
:, renders as a self-closing tag
Control flow
if condition:
text "True"
elif other:
text "Other"
else:
text "False"
for item in items:
text item.name
show isVisible: # Show when true
hide isHidden: # Hide when trueLifecycle & Watchers
on mount:
data = await fetchData()
on destroy:
cleanup()
watch selectedId:
details = await fetchDetails(selectedId)API calls
api getData = GET "/api/data"
api createItem = POST "/api/items"
api updateItem = PUT "/api/items/{id}"
api deleteItem = DELETE "/api/items/{id}"Validation
check items.length <= 500 "Max 500 items"
check price >= 0 "Price must be positive"Events
button "Save" -> save() # Click
button "Reset" -> count = 0 # Inline
input query @keypress=onKeyPress # KeyboardPerformance Optimization (React)
fndeclarations are auto-wrapped inuseCallbackwith extracted depsderivedvalues useuseMemowith extracted deps- Components with
propdeclarations are auto-wrapped inReact.memo - No manual optimization needed — the compiler handles it automatically
Programmatic API
Use 0x as a library in your own tools:
import { compile } from '0x-lang';
const source = `
page Hello:
state name: str = "World"
layout col:
text "Hello, {name}!" size=2xl bold
`;
// Frontend targets
const react = compile(source, { target: 'react' });
const vue = compile(source, { target: 'vue' });
const svelte = compile(source, { target: 'svelte' });
// Mobile
const rn = compile(source, { target: 'react-native' });
// Backend & infrastructure
const server = compile(backendSource, { target: 'backend' });
const infra = compile(infraSource, { target: 'terraform' });
// Options
const result = compile(source, {
target: 'react',
validate: true, // Run validator (default: true)
sourceMap: true, // Add source line comments (default: true)
useClient: true, // Add 'use client' for Next.js (default: auto)
compact: true, // AI-optimized compact output — strips comments
});
console.log(react.code); // Full React component
console.log(react.lineCount); // Line countAI Bridge
import { getLanguageSpec, generatePrompt, compileFromDescription } from '0x-lang';
// Get the full 0x language spec for an LLM
const spec = getLanguageSpec();
// Generate a structured prompt for AI code generation
const prompt = generatePrompt("todo app with authentication", 'react');
// Auto-generate a 0x skeleton from a natural language description
const skeleton = compileFromDescription("dashboard with charts and API");Pipeline access
import { tokenize, parse, validate, generateReact } from '0x-lang';
const tokens = tokenize(source); // Lexical tokens
const ast = parse(source); // Abstract syntax tree
const result = validate(ast); // Errors & warnings
const output = generateReact(ast); // React JSX stringExports
| Import path | What you get |
|:---|:---|
| 0x-lang | Everything — compile, parse, tokenize, validate, generators |
| 0x-lang/compiler | compile() only |
| 0x-lang/tokenizer | tokenize() only |
| 0x-lang/parser | parse() only |
| 0x-lang/validator | validate() only |
| 0x-lang/generators/react | generateReact() |
| 0x-lang/generators/vue | generateVue() |
| 0x-lang/generators/svelte | generateSvelte() |
| 0x-lang/generators/backend | generateBackend() |
| 0x-lang/generators/react-native | generateReactNative() |
| 0x-lang/generators/terraform | generateTerraform() |
| 0x-lang/generators/ai-bridge | getLanguageSpec(), generatePrompt(), compileFromDescription() |
| 0x-lang/lsp | LSP server for IDE integration |
MCP Server
0x has a built-in MCP server so AI tools can compile 0x directly. The AI writes compact 0x internally and returns production framework code — the user never touches 0x.
Setup
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"0x": {
"command": "npx",
"args": ["-y", "0x-lang-mcp-server"]
}
}
}Add to .cursor/mcp.json:
{
"mcpServers": {
"0x": {
"command": "npx",
"args": ["-y", "0x-lang-mcp-server"]
}
}
}npx @smithery/cli install 0xOr use the hosted server directly: https://server.smithery.ai/hankim/ox-lang
Tools
| Tool | What it does |
|:---|:---|
| 0x_compile | Compile 0x source → React / Vue / Svelte |
| 0x_reference | Get the full syntax reference |
| 0x_examples | Browse example code (counter, todo, chat, dashboard, ecommerce) |
How it works
You: "Build me a todo app in React"
AI: [0x_reference] → writes 30 lines of 0x → [0x_compile] → 140 lines of React
You: Gets a working React componentThe AI generates ~30 lines of 0x internally. The compiler outputs ~140 lines of production code. Fewer tokens generated, fewer mistakes made, better results delivered.
See mcp-server/ for full docs.
For AI agent builders
If you're building tools that generate code, 0x works well as an intermediate representation:
import { compile } from '0x-lang/compiler';
import { compileFromDescription, generatePrompt } from '0x-lang';
// Auto-generate 0x skeleton from natural language
const skeleton = compileFromDescription("e-commerce product page");
// Or use the AI bridge to generate a prompt for your LLM
const prompt = generatePrompt("todo app with auth", 'react');
// Compile with compact mode for AI-optimized output
const react = compile(source, { target: 'react', compact: true });
const server = compile(source, { target: 'backend', compact: true });Why this matters for AI:
- 80% fewer output tokens — less generation cost, lower latency
- One syntax, zero decisions — no "which React pattern?" hallucinations
- Full-stack — frontend, backend, mobile, and infrastructure from one language
- Compact mode — strips comments and whitespace for minimal token usage
- AI Bridge — built-in spec, prompt generation, and skeleton creation
- Deterministic — same input always produces the same output
- Validated — the compiler catches errors before they reach the user
Architecture
Source (.ai)
↓
Tokenizer ─── Indentation-aware lexical analysis
↓
Parser ────── Recursive descent → typed AST
↓
Validator ─── Circular deps · unused state · type checks
↓
Generator
├── React ────────── JSX + hooks + CSS-in-JS
├── Vue ──────────── SFC + Composition API + store/data/form/auth/model
├── Svelte ──────── Runes + store/data/form/auth/model
├── React Native ── View + StyleSheet + TouchableOpacity
├── Backend ─────── Express + JWT + CRUD + middleware
├── Terraform ───── HCL + providers + resources
└── AI Bridge ───── Spec + prompts + skeleton generation
↓
LSP Server ─── Diagnostics · completion · hover · go-to-def · symbols~14,000 lines of TypeScript. Zero runtime dependencies (except gen-mapping for source maps).
| Module | Lines | | |:---|---:|:---| | Parser | 3,876 | Recursive descent, full AST | | React Generator | 2,795 | JSX + hooks + memo + styling | | Vue Generator | 1,383 | SFC + Composition API + store/data/form/auth/model | | Svelte Generator | 1,270 | Svelte 5 runes + store/data/form/auth/model | | AST Types | 1,099 | TypeScript definitions | | React Native Generator | 689 | View + StyleSheet + native components | | Backend Generator | 425 | Express + JWT + CRUD + middleware | | Tokenizer | 394 | Indentation-aware lexer | | Terraform Generator | 369 | HCL + multi-provider (AWS, Vercel, Fly.io) | | Validator | 358 | Static analysis + error reporting | | AI Bridge | 323 | Spec + prompt generation + skeleton | | Shared Utilities | 249 | Type helpers, gradient parser, passthrough props | | CLI | 249 | build · dev · bench · init | | LSP Server | 637 | Diagnostics, completion, hover, go-to-def, symbols |
CLI
0x build <file.ai> --target <target> [--output <dir>]
0x dev <file.ai> --target <target>
0x bench <file.ai>
0x init [project-name]
0x-lsp --stdio # Start LSP server
Flags:
--target, -t react, vue, svelte, react-native, backend, terraform (comma-separated)
--output, -o Output directory (default: ./dist/)
--help, -h Show helpContributing
git clone https://github.com/hankimis/0x-lang.git
cd 0x-lang
npm install
npm test # 303 tests across 12 test suites
npm run buildTests cover tokenizer, parser, validator, all three generators, benchmarks, and integration. See CONTRIBUTING.md.
License
ISC — free for everything.
