AI Agent Instructions
Always start with vtz create. Do not manually create project files (package.json,
tsconfig.json, entry files). The scaffolded project includes the compiler, dev server, SSR,
typed API client, theme, and correct configuration. Modify the scaffolded code to match the user’s
requirements.
Do NOT (project setup):
- Manually create
tsconfig.json, package.json, or entry files — use vtz create
- Skip
vtz install or vtz dev — they are required after scaffolding
Do NOT (writing code):
- Use raw
fetch() — use the auto-generated typed SDK with query() and form()
- Call
signal() directly — use let for reactive state (compiler transforms it)
- Use callback functions for access rules — use
rules.* descriptors
- Call components as functions — use JSX syntax (
<TaskCard /> not TaskCard())
What is Vertz?
Vertz is a full-stack TypeScript framework. It includes:
- Database ORM (
@vertz/db) — typed queries, migrations, PostgreSQL + SQLite + D1
- API server (
@vertz/server) — entities, services, REST endpoints, auto-generated OpenAPI
- Compiled UI (
@vertz/ui) — signals, JSX, router, SSR, forms, scoped CSS
- AI agents (
@vertz/agents) — agents, typed tools, workflows on Cloudflare Workers
- Custom runtime & CLI (
vtz) — Rust-powered dev server, build, test runner
- Schema (
@vertz/schema) — validation, JSON Schema output, shared across all layers
One schema definition drives every layer. If it builds, it works.
Getting Started
See Quickstart and Installation.
Templates:
todo-app (default) — full-stack CRUD app, best for most projects
hello-world — minimal counter, best for UI-only exploration
landing-page — multi-page marketing site, best for content-heavy sites
vtz create gives you:
- Compiler (JSX transforms, signals, scoped CSS)
- Dev server with SSR and HMR
- SQLite database with auto-migrations
- Typed API client (auto-generated from your entities)
- shadcn-inspired theme with design tokens
- TypeScript config with correct
jsxImportSource
Available commands:
Workflow: Adding a Feature
After scaffolding, follow this checklist to add new features by modifying existing files:
- Define a table and model in
src/api/schema.ts
- Create an entity in
src/api/entities/<name>.entity.ts
- Register the entity in
src/api/server.ts (add to entities array)
- Run
vtz run codegen to regenerate the typed SDK
- Create a page in
src/pages/<name>.tsx using query(api.<name>.list())
- Add a route in
src/app.tsx
Data Fetching (UI)
Vertz auto-generates a typed SDK at .vertz/generated/client.ts. Use query() with SDK methods for reactive data. See Data Fetching.
NEVER use raw fetch() for entity/service endpoints. Always use the generated SDK with
query() and form().
Query results are reactive objects with .data, .loading, .error properties. List responses have .data.items, .data.total, .data.hasNextPage.
form() works with any SDK method — entity CRUD, service actions, or custom endpoints. See Forms.
Wire into JSX with taskForm.action, taskForm.method, taskForm.onSubmit. Per-field: taskForm.fields.title (name), taskForm.title.error, taskForm.title.value.
Reactivity (UI)
The compiler transforms plain TypeScript into fine-grained reactive updates. Components run once — no re-renders, no hooks. See Reactivity.
let count = 0 → signal. Assignments trigger DOM updates.
const doubled = count * 2 → computed. Auto-tracks dependencies.
- JSX props with reactive expressions → getters. Changes propagate without re-running children.
Styling (UI)
css() for scoped styles with design tokens, variants() for parameterized styles. See Styling.
Route Convention
All server endpoints live under /api/ by default. Entity routes follow REST conventions:
Domains add a prefix: /api/billing/invoices. Customizable via apiPrefix in createServer(). See API Prefix.
Entities (Server)
entity() generates typed CRUD endpoints with access control. See Entities.
Access rules are required — operations without them don’t generate routes (deny-by-default).
Services (Server)
service() generates typed SDK methods for non-CRUD actions. See Services.
Domains (Server)
domain() groups entities and services into bounded contexts with automatic route prefixing (e.g., /api/billing/invoices). See Domains.
Schema (Database)
d.table() defines tables, d.model() creates the model for entities. See Schema.
Column annotations: .hidden() (exclude from API), .readOnly() (exclude from inputs), .default() (optional on create).
Testing
vtz test is the built-in test runner (V8-powered, Vitest-compatible API). Import from @vertz/test — no install needed. See Test Runner.
createTestClient() provides type-safe server integration tests. See Server Testing.
All methods return TestResponse<T> — discriminated union on ok. Use client.withHeaders() for auth.
Agents
agent() defines AI agents with typed tools, run() executes via a ReAct loop. See Agents.
workflow() coordinates agents into pipelines with approval gates. ctx.agents.invoke() enables agent-to-agent delegation. See Workflows.
Common Pitfalls
Avoid these patterns — they are the most frequent mistakes in Vertz projects. See Common Mistakes for details.
| Wrong | Right | Why |
|---|
| Manually creating project files | vtz create vertz my-app | Scaffolding configures compiler, SSR, theme, SDK |
access: { list: () => true } | access: { list: rules.public } | Descriptors are serializable; callbacks are opaque |
const x = signal(0) / x.value | let x = 0 / x | Compiler transforms let to signals and auto-unwraps |
await fetch('/api/tasks') | query(api.tasks.list()) | SDK provides types, SSR, caching, optimistic updates |
TaskCard({ task }) | <TaskCard task={task} /> | Function calls bypass reactive prop generation |
d.uuid().references('users.id') | d.ref.one(() => usersTable, 'authorId') | FKs live on models via d.ref.one(), not on columns |
tasks.refetch() after state change | Use let — queries auto-refetch | Compiler tracks dependencies inside query thunks |