> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vertz.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Common Mistakes

> Anti-patterns to avoid when building with Vertz

These are the most common mistakes we see in Vertz projects — especially when AI agents or developers are getting started. Each one has a clear fix.

## Skipping `vtz create`

The fastest and most reliable way to start a Vertz project is `vtz create`. It scaffolds a working full-stack app with the compiler, dev server, SSR, typed API client, and theme — all configured correctly.

```bash theme={null}
# Wrong — manually creating files from scratch
mkdir my-app && cd my-app
# ... creating package.json, tsconfig.json, entry files by hand

# Right — scaffold and customize
vtz create vertz my-app
cd my-app && vtz install && vtz dev
```

**Why it matters:** Vertz requires specific compiler configuration, JSX import source settings, dev server setup, and file conventions. Manual setup is error-prone and misses features like SSR, HMR, scoped CSS extraction, and the typed API client. Start with `vtz create` and modify the scaffolded code.

## Using `signal()` instead of `let`

The Vertz compiler transforms `let` declarations into signals automatically and auto-unwraps `.value` in JSX. Using `signal()` directly bypasses these optimizations.

```tsx theme={null}
// Wrong — manual signal, requires .value everywhere
import { signal } from '@vertz/ui';
const count = signal(0);
return <span>{count.value}</span>;

// Right — compiler handles reactivity
let count = 0;
return <span>{count}</span>;
```

**Why it matters:** When you use `let`, the compiler tracks dependencies automatically — queries re-fetch, DOM updates, and effects re-run without manual `.value` reads. With `signal()`, you must manage everything yourself.

## Using `() => true` instead of `rules.public`

Entity access rules should use declarative `rules.*` descriptors, not callback functions.

```ts theme={null}
// Wrong — opaque function, can't be serialized or inspected
access: {
  list: () => true,
  create: () => true,
}

// Right — declarative descriptor
import { entity, rules } from '@vertz/server';

access: {
  list: rules.public,
  create: rules.authenticated(),
}
```

**Why it matters:** `rules.*` descriptors are plain objects that the framework can serialize for the client SDK, display in generated OpenAPI docs, and potentially compile to database-level policies. Callback functions are opaque.

See [Entities](/guides/server/entities) for the full access control API.

## Using raw `fetch()` instead of the generated SDK

Vertz auto-generates a typed SDK from your entity and service definitions. Always use it.

```tsx theme={null}
// Wrong — bypasses type safety, SSR, caching, and optimistic updates
const res = await fetch('/api/tasks');
const data = await res.json();

// Right — fully typed, SSR-integrated, cached
import { query } from '@vertz/ui';
import { api } from '../client';

const tasks = query(api.tasks.list());
```

**Why it matters:** The generated SDK provides type safety (request and response types checked at compile time), SSR integration (queries run on the server during SSR), automatic cache invalidation (mutations refetch related queries), and optimistic updates.

See [Data Fetching](/guides/ui/data-fetching) for the full guide.

## Manual `refetch()` instead of reactive queries

When queries read reactive state inside their thunk, they automatically re-fetch when that state changes. Manual `refetch()` calls are usually unnecessary.

```tsx theme={null}
// Wrong — manual state tracking and refetch
const filter = signal('all');
const tasks = query(() => api.tasks.list({ status: filter.value }));
// Later: tasks.refetch() after filter changes

// Right — compiler auto-tracks dependencies
let filter = 'all';
const tasks = query(() => api.tasks.list({ status: filter }));
// Changing filter automatically re-fetches
```

See [Data Fetching](/guides/ui/data-fetching#reactive-dependencies) for how dependency tracking works.

## Calling components as functions

Always use JSX syntax for components. Calling them as functions bypasses the compiler's reactive prop generation.

```tsx theme={null}
// Wrong — no reactive props
const card = TaskCard({ task, onClick: handleClick });

// Right — compiler generates getters for reactive props
<TaskCard task={task} onClick={handleClick} />;
```

## Annotating component return types

Let TypeScript infer return types from JSX. Annotating `: HTMLElement` is a lossy upcast.

```tsx theme={null}
// Wrong
export function TaskCard({ task }: Props): HTMLElement {

// Right
export function TaskCard({ task }: Props) {
```

## Running SQLite scripts with `node` instead of `vtz`

The `vtz` runtime includes a built-in SQLite driver powered by Rust — no extra dependencies needed. Running scripts that use `@vertz/db` with SQLite under plain `node` will fail because Node.js doesn't have the native driver.

```bash theme={null}
# Wrong — plain Node doesn't have the built-in SQLite driver
node ./scripts/ensure-db.ts

# Right — vtz includes a native SQLite driver
vtz run ensure-db
```

**Why it matters:** The `vtz` runtime embeds SQLite via Rust, so any script run through `vtz` (including `vtz run <script>`, `vtz dev`, and `vtz test`) has SQLite available with zero extra dependencies. Running the same script with `node` bypasses the runtime entirely.

If you need to run database scripts outside of `vtz`, use PostgreSQL instead of SQLite, or install `better-sqlite3` as a fallback.

## Using `.references()` on columns for foreign keys

Foreign keys are declared via `d.ref.one()` on models, not `.references()` on columns.

```ts theme={null}
// Wrong — this is a pattern from other ORMs, not Vertz
const postsTable = d.table('posts', {
  authorId: d.uuid().references('users.id'), // Does not exist
});

// Right — use d.ref.one() on the model
const postsModel = d.model(postsTable, {
  author: d.ref.one(() => usersTable, 'authorId'),
});
```

See [Schema](/guides/db/schema#relations) for the full relations API.
