Canary

The agent-native
framework.stack.ecosystem.compiler.runtime.devtool.

One schema derives your database, API, and UI. Fully typed end-to-end. Built for agents to write, humans to ship.

Ask your agent:
"Build a full-stack to-do app using docs.vertz.dev"
Read the Docs →
import { query, form } from 'vertz/ui';
import { api } from './generated/client';

export function TodoList() {
  const todos = query(api.todos.list());
  const todoForm = form(api.todos.create, {
    onSuccess: () => todos.refetch(),
  });

  return (
    <form onSubmit={todoForm.onSubmit}>
      <input name="title" placeholder="What needs to be done?" />
      <button type="submit">Add</button>
      {todos.data.map((t) => (
        <li key={t.id}>{t.title}</li>
      ))}
    </form>
  );
}
  • Design the schema
  • Generate the API
  • Build the UI
  • Ship to production
2 remaining

Features

Not another framework wrapper.

Every feature exists because the compiler knows your entire stack — schema, API, and UI — at build time.

01

Your UI decides the query.

Reference task.title in a component — the compiler traces the access and generates a SELECT with only that column. Add task.dueDate to the template, the query adapts. Remove it, the column drops. No field lists to maintain. No GraphQL fragments. The compiler knows what your UI needs.

Your component accesses title and status
const tasks = query(todoApi.list());
return (
<ul>
{tasks.data.map((t) => (
<li key={t.id}>{t.title} — {t.status}</li>
))}
</ul>
)
Generated: SELECT "id", "title", "status" FROM "todo"
Never SELECT * — only what the UI actually uses.

02

Rename a field. Everything breaks — at compile time.

One schema defines the shape. One type chain flows from database column to API route to form input. Rename title to name — TypeScript finds every broken reference across your entire stack before you run a single test.

const todos = d.table('todos', {
id: d.uuid().primary(),
- title: d.text(),
+ name: d.text(),
done: d.boolean().default(false),
});
api.todos.create({ title: 'Buy milk' });
Property 'title' does not exist. Did you mean 'name'?
<li>{t.title}</li>
Property 'title' does not exist on type 'Todo'.

03

Your schema is the documentation.

Every entity gets REST endpoints and a fully documented OpenAPI spec. No decorators. No separate spec file. No drift between code and docs. Define the entity, get CRUD operations with complete request/response schemas at /api/openapi.

export const todos = entity('todos', {
model: todosModel,
access: {
list: rules.authenticated(),
create: rules.authenticated(),
delete: rules.entitlement('todo:delete'),
},
});
Auto-generated REST + OpenAPI:
GET /api/todos POST /api/todos
GET /api/todos/:id PUT /api/todos/:id
GET /api/openapi ← full OpenAPI spec

04

Generate. Publish. Let agents consume.

One command generates a typed client SDK from your API. Publish to npm for third-party developers. Feed it to an LLM agent. Every endpoint typed, every response validated, every breaking change caught at compile time — for your consumers too.

$ vertz codegen
Your consumers get fully typed access:
import { createClient } from '@myapp/sdk';
const api = createClient({ baseUrl: 'https://...' });
const todos = await api.todos.list();
^? { id: string; title: string; done: boolean }[]
await api.todos.create({ title: 'Ship it' });
^? CreateTodoInput — fully typed

05

One pattern per task. Agents get it right the first time.

Every API has one canonical pattern. No framework trivia, no hidden conventions. Add one line to the schema — database, API, SDK, validation, and forms all update. An LLM agent writes correct code on the first try because there's only one way to do it.

Agent prompt: "Add a due date to todos"
Schema — the only code the agent writes:
dueDate: d.date().optional(),
Vertz derives everything else:
✓ Database migration
✓ API endpoint updates
✓ OpenAPI spec update
✓ SDK type update
✓ Form validation rules
One line of schema → full-stack feature.

06

The compiler does the work. Not the browser.

let count = 0 becomes a reactive signal. const double = count * 2 becomes a computed value. The compiler transforms at build time — not the browser at runtime. No virtual DOM, no diffing, no framework overhead. Just direct DOM updates.

You write this:
export function Counter() {
let count = 0;
const double = count * 2;
return (
<button onClick={() => count++}>
{count} × 2 = {double}
</button>
);
}
Compiler: let → signal(), const → computed()
Runtime: direct DOM updates. Zero overhead.

Why Vertz

One schema, every layer

Define your data once. The compiler derives your database, API, client SDK, and form validation. Change a field — it updates everywhere.

One way to do things

No choice paralysis. No tribal knowledge. Every API has one canonical pattern. Your team and your AI agent write the same code — correctly, on the first try.

Production-ready by default

Auth, validation, error handling, OpenAPI docs, deployment — built in, not bolted on. You add business logic. Vertz handles the rest.

The stack

One framework. Not fifteen npm installs.

Every layer works together because they were built together.

vertz/schema
Runtime-safe type definitions
replaces Zod
vertz/db
Typed queries & migrations
replaces Drizzle / Prisma
vertz/server
Entity-based CRUD + OpenAPI
replaces Express + tRPC
vertz/compiler
Static analysis + SDK codegen
replaces Manual glue code
vertz/ui
Signals, query(), form(), css()
replaces React + Tailwind
vertz/ui-primitives
Accessible components
replaces Radix / Base UI
vertz/theme-shadcn
Pre-built styled components
replaces shadcn/ui
vertz/ui-server
SSR, streaming, HMR dev server
replaces Next.js + Vite
vertz/testing
API & UI test utilities on vtz
replaces Vitest + Testing Library
vertz/cloudflare
Edge deployment
replaces Dockerfile + infra
vertz/icons
Tree-shakeable Lucide icons
replaces lucide-react

Get started in 30 seconds.

SQLite database, REST API, and UI — all running locally. No Docker. No config files. Edit any layer and see it update instantly.

$ curl -fsSL vertz.dev/vtz/install | sh
$ vtz create my-app
$ cd my-app
$ vtz dev
✓ SQLite database ready
✓ API server on http://localhost:3000/api
✓ UI on http://localhost:3000

What about...

Is it production-ready?

Pre-v1 and moving fast. Cloudflare Workers deployment works today. We break APIs intentionally to find the best design — and we ship every improvement as a patch.

Can I use existing libraries?

Yes. Standard TypeScript, npm-compatible. Use any library you want alongside Vertz.

What if I only want the UI?

Use vertz/ui standalone. The full stack is optional — each layer works independently.

What about React / Next.js?

Vertz isn't a React wrapper. It's a different model: signals instead of VDOM, compile-time instead of runtime. If you're happy with React, stay. If you're tired of the ceremony, try Vertz.

We spent years stitching together ORMs, API frameworks, validation libraries, and UI toolkits — and watching them drift apart. We built Vertz so the next team doesn't have to.

Vinicius Dacal

Vinicius Dacal

Co-founder

15+ years building at scale. Senior Engineer at Scrunch. Previously Staff Engineer at Voiceflow. Led Angular-to-React migrations, built GraphQL servers, shipped NestJS backends — and got tired of fighting the frameworks.

@vinicius_dacal
Matheus Poleza

Matheus Poleza

Co-founder

10+ years full-stack. Seed to Series C startups. Microservices, AI integration, performance at scale — now channeling it all into one stack that does it right.

@matheeuspoleza
Community

Build this with us.

Join the Discord. Talk to the founders, preview breaking changes, and help shape the APIs before v1.

Join Discord →