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.ai
2state count: number = 0
3
4column items-center gap-4 p-8
5 title "Count: {count}"
6 row gap-2
7 button primary "+"
8 @click count = count + 1
9 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.ai
2import User from types/user
3
4fetch users: User[] from /api/users
5
6column gap-4 p-6
7 title "Users"
8
9 if users.loading
10 text muted "Loading..."
11
12 for user in users.data
13 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.

// input.ai source files.riven/cache/mirror of project, transpiledconsumer packages@riven/vite · @riven/cli01 · language layer — pure compiler · string → IR · zero deps · browser-safe@riven/coreLexer → Parser → AST → IR · resolve-ir, layouts (pure)02 · project layer — project I/O + Stack contract@riven/orchestratorwalk → discover → componentMap · loadConfig · compile(root, stack) → cache03 · adapter · .ai → .tsx@riven/react03 · adapter · .ai → .ts@riven/fastify03 · future adapters@riven/vue · hono · …↳ IR↳ Stack.emit / Stack.hostFiles
§ 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.