AI-FIRST · FULLSTACK · DECLARATIVE
Write less.
Ship more.
A semantic, compact, AI-first fullstack language. One .ai file compiles to production-ready React + Fastify.
Authored by AI. Read by humans. ~50% fewer tokens than TSX+Tailwind.
$ npx riven create-app
read the spec →0 deps in core~50% token reduction1.4k lines of compiler
components/counter.ai14 lines
1# components/counter.ai2state count: number = 034column items-center gap-4 p-85 title "Count: {count}"6 row gap-27 button primary "+"8 @click count = count + 19 button "-"10 @click count = count - 1
↳ compiles to · counter.tsx · 28 lines · tailwind● ready
§ 01why this exists
One language. Three constituencies.
// for ai authors
Token-efficient by design
button primary "Save" (4 tokens) replaces <button className="bg-primary text-primary-foreground">Save</button> (~12 tokens BPE). Deterministic syntax — one way to do each thing, fewer choices, fewer hallucinations.
~50%
fewer tokens vs TSX+Tailwind
// for humans
Readable in PRs
Meant to be reviewed and edited. Type-safe end-to-end with zero manual annotations cross-stack. Real React + Fastify underneath — debuggable, no proprietary runtime, no magic.
100%
inferred types across boundary
// for projects
A peer of Next.js
Not a wrapper. Owns its router, SSR pipeline, build orchestration. React is just the renderer — adapter architecture means Vue, Svelte, Solid, Hono plug in without touching user code.
6+
future stack adapters
§ 02the whole stack
Page. Route. Types. Validation. Navigation.
click to switch
1# app/users/index.ai2import User from types/user34fetch users: User[] from /api/users56column gap-4 p-67 title "Users"89 if users.loading10 text muted "Loading..."1112 for user in users.data13 card title={user.name}14 text muted {user.email}15 button primary "View"16 @click go /users/{user.id}
↳ the compiler:
- resolves fetch users from /api/users to the matching route at compile time
- inherits the return type (User[]) cross-stack — no manual annotation
- inlines the route call during SSR, falls through to fetch() after hydration
- wires Fastify route handlers with JSON Schema from @email / @min(2)
§ 03architecture
Three honest layers. One responsibility each.
§ 04token efficiency
The same page. 71% fewer tokens.
users.ai78 tokens · 16 lines
# app/users/index.ai
import User from types/user
fetch users: User[] from /api/users
column gap-4 p-6
title "Users"
if users.loading
text muted "Loading..."
for user in users.data
card title={user.name}
text muted {user.email}
button primary "View"
@click go /users/{user.id}
users.tsx + tailwind267 tokens · 36 lines
import { useState, useEffect } from "react";
import { z } from "zod";
import type { User } from "@/types/user";
export default function Users() {
const [users, setUsers] = useState<User[] | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch("/api/users")
.then(r => r.json())
.then(d => { setUsers(d); setLoading(false); });
}, []);
return (
<div className="flex flex-col gap-4 p-6">
<h1 className="text-2xl font-semibold">Users</h1>
{loading && (
<p className="text-muted-foreground">Loading...</p>
)}
{users?.map(u => (
<div className="rounded-lg border p-4" key={u.id}>
<h3 className="font-medium">{u.name}</h3>
<p className="text-sm text-muted-foreground">
{u.email}
</p>
<button
className="bg-primary text-primary-foreground
rounded px-3 py-1.5 text-sm"
onClick={() => router.push(`/users/${u.id}`)}
>View</button>
</div>
))}
</div>
);
}monthly api spend · 10k pages/day
$1,840 → $890
avg generation time
18s → 9s
parse error rate
~4% → <0.5%
§ 05roadmap
Each phase ships a demoable milestone.
00
v0.1
Compiler basics · lexer, parser, IR, layout primitives, Tailwind macros, React emit, CLI build
▶ wip
01
v0.2
Reactivity · signals, state, @event, if/for, slots
▢ planned
02
v0.3
Routing · file-based, _layout, [param], go, link
▢ planned
03
v0.4
Backend · Fastify adapter, route, body, auth stub
▢ planned
04
v0.5
★ Cross-stack IPC · fetch ↔ route auto-wiring, type inference
▢ planned
05
v0.6
SSR · react-dom/server, inline route calls, hydration, streaming
▢ planned
06
v0.7
DX · LSP, sourcemaps, HMR <200ms, VSCode extension
▢ planned
07
v0.8
Forms & Auth · form aggregation, real JWT, validators
▢ planned
08
v0.9
Docs site (in Riven), example apps, riven create-app
▢ planned
09
v1.0
AI Adapter (@riven/ai-prompt), stable API
★ milestone
10
v1.x
Vue · Svelte · Solid · Hono · Elysia adapters · WebSockets
◌ future
11
v2.0
Server-logic DSL · service (Drizzle), policy, workflow
◌ future
12
v3.0
Mobile target · React Native + Lynx adapter
◌ future
§ 06quick start
Three commands. Fullstack app.
~ / my-app · zsh
# install
$ npx riven create-app my-app
$ cd my-app && pnpm install
# run dev server
$ pnpm dev
▸ frontend http://localhost:5173
▸ backend http://localhost:3001
▸ hmr 12ms
# build for production
$ pnpm build
✓ dist/server/index.js · Fastify + SSR
✓ dist/client/ · hydrated bundles + static HTML
✓ compiled 24 .ai files in 412ms
$ ▌
§ 07language reference
The whole grammar fits on one screen.
Layout
row · column · stack · grid · box
Text
title "..." · text "..." · label "..."
Inputs
input · textarea · select · checkbox · radio
Component def
file under components/ · prop name: T = default
State
state count: number = 0
Computed
computed double = count * 2
Async data
fetch users: User[] from /api/users
Effects
effect · mount
Actions
action submit(values: object) ...
DOM events
@click · @change · @key-down ...
Function props
named on* · typed as action
Two-way bind
bind email inside an input
Control flow
if cond / else · for x, i in xs
Routes
route GET · route POST · body: {...} · returns T
Auth
auth required · auth optional
Errors
error 401 "Invalid"
Navigation
go /path · link "/users" "View"
Validation
body: { email: string @email, password: string @min(8) }
Types
type User { id: string; name: string }
Imports
implicit by convention; import X from path for types / server/*
Comments
# line
Operators
not · and · or · == · != · < · <= · > · >= · + - * /
BEGIN ─────────────────────
$ npx riven create-app
Free, MIT-licensed, no telemetry. v0.1 ships when the compiler does. Star the repo to follow along.