# Generate Zod schemas for your SvelteKit models from a field list

Stop hand-writing a Zod schema for every form and endpoint. One vela command turns a field list into a typed schema that drops straight into Superforms, remote functions and server code.

Pattern: [Generate a schema](https://velastack.dev/patterns/generate-schema) · Docs: https://docs.velastack.dev/generate/schema

Every SvelteKit form action, remote function and API route needs the same thing before it touches data: a schema that says what a valid request looks like. In a plain SvelteKit project that means opening `src/lib/schemas/`, writing a `z.object()` by hand, and keeping it in sync with the database column it validates. The `vela generate schema` generator does the writing from a one-line description of the model.

## Prerequisites

Any SvelteKit project. The generator needs no vela setup, no backend and no component kit, so a fresh one is enough:

```sh
$ npx sv create my-app && cd my-app
```

Run vela with `npx vela`, or add it to the project with `npm install -D vela`. If the project has no `zod` yet, the command installs it alongside the schema.

A project made with `npx vela create my-app`, or upgraded with `npx vela bless`, already has Zod and Superforms, which the first example under "Use it" relies on. [Coming from vanilla SvelteKit](https://docs.velastack.dev/bless) explains what `bless` adds and what it leaves alone.

## Run the command

A schema is a model name followed by fields. Each field is `name:type`, and a trailing `!` makes it required:

```sh
$ vela generate schema login email:email! password:text!
```

## What was generated

One file. The model name becomes the file name and the export name:

**src/lib/schemas/login.ts**

```ts
import { z } from "zod";

export const loginSchema = z.object({
  email: z.email(),
  password: z.string().nonempty(),
});
```

The highlighted lines are the two fields you described. `email:email!` became `z.email()`, and `password:text!` became a non-empty string. Every field type in the [generator syntax](https://velastack.dev/tutorials/sveltekit-generator-field-syntax) has a Zod equivalent, so `age:number` gives you `z.number()`, `role:select(admin:Admin,member:Member)` gives you an enum, and a field without `!` is wrapped in `.optional()`.

## Use it

The schema is plain Zod, so it works anywhere Zod does. In a form action with Superforms:

**src/routes/login/+page.server.ts**

```ts
import { superValidate } from 'sveltekit-superforms';
import { zod4 } from 'sveltekit-superforms/adapters';
import { loginSchema } from '$lib/schemas/login';

export const load = async () => ({ form: await superValidate(zod4(loginSchema)) });
```

Or on its own, in a `+server.ts` endpoint:

**src/routes/api/login/+server.ts**

```ts
import { json } from '@sveltejs/kit';
import { loginSchema } from '$lib/schemas/login';

export const POST = async ({ request }) => {
	const body = loginSchema.parse(await request.json());
	return json({ ok: true, email: body.email });
};
```

> **Tip:**
> If you also want the form page and the action that uses this schema, run [`vela generate form`](https://velastack.dev/tutorials/sveltekit-form-validation-zod-superforms) instead. It generates the same schema plus the page, the handler and a server test.

## Change your mind

Generated files are ordinary source, so you can edit the schema by hand. If you would rather start over, remove it with the matching destroy command:

```sh
$ vela destroy schema login
```

## Going further

- [Generate a form from the same field list](https://velastack.dev/tutorials/sveltekit-form-validation-zod-superforms)
- [Define the database collection too](https://velastack.dev/tutorials/sveltekit-database-model-from-cli)
- [Pattern page: Schema](https://velastack.dev/patterns/generate-schema)
- [Docs: vela generate schema](https://docs.velastack.dev/generate/schema)
