# Form

The basic building block of any website or application is the form. If you don't need a database backend, you can use the form generator to create a simple form. Ideal for contact or feedback forms where the data isn't persisted.

### Syntax

```
$ vela generate form [model] [fields...]
```

```
$ vela generate form contact name:text! email:email! message:editor
```

This will create a form at `/contact` and a Zod schema definition for form validation. The files created are:

```
src/routes/(public)/contact/+page.svelte
src/routes/(public)/contact/+page.server.ts
src/routes/(public)/contact/server.test.ts
src/lib/schemas/contact.ts
```

In a project with shadcn-svelte, any components the form needs are installed automatically. `sveltekit-superforms` and `zod` are installed too if the project doesn't have them. The [server test](/test/server) is only written when the project has the `vela test:server` harness (`supertest` installed).

Success is shown as a flash message when the project has `sveltekit-flash-message`. Without it, the action returns the message with superforms' `message()` instead.

### Options

- `--remote` - Generate the form with SvelteKit remote functions instead of sveltekit-superforms
- `--route <route>` - Place the form at a custom route. Defaults to the model name under `(app)` when auth is enabled, or `(public)` when it isn't. A project with neither group gets it directly under `src/routes`.
- `--ui <shadcn|plain>` - Generate shadcn-svelte components or plain HTML elements. Defaults to `shadcn` when the project has shadcn-svelte, `plain` otherwise.
- `--ai <description>` - Design the form with AI from a natural-language description

### Route

`--route` places the form anywhere in the route tree, including inside dynamic segments. The schema still lands in `src/lib/schemas`.

```
$ vela generate form project name:text! description:editor --route "(app)/[team_id]/projects/new"
```

Creates:

```
src/routes/(app)/[team_id]/projects/new/+page.svelte
src/routes/(app)/[team_id]/projects/new/+page.server.ts
src/routes/(app)/[team_id]/projects/new/server.test.ts
src/lib/schemas/project.ts
```

Keep the route you used — [`vela destroy form`](/destroy/form) needs the same `--route` to find the files again.

### Plain HTML

`--ui` defaults to `shadcn` when the project has a `components.json` and the `shadcn-svelte` or `bits-ui` package. Otherwise the form uses plain HTML elements with no classes, and no components are installed. `--ui plain` does the same in a project that has shadcn-svelte; `--ui shadcn` in a project without it is an error — set it up with `npx sv add tailwindcss`, then `npx shadcn-svelte@latest init`, or run [`vela bless`](/bless) for the full upgrade.

In a project from `sv create`, which has no route groups and no test harness:

```
$ vela generate form contact name:text! email:email! message:editor
```

Creates:

```
src/routes/contact/+page.svelte
src/routes/contact/+page.server.ts
src/lib/schemas/contact.ts
```

Each field's wrapper has a `data-field` attribute with the field name, and `data-invalid` while the field has errors. Error messages have `data-error`. Use these to style every generated form from one stylesheet. Without `sveltekit-flash-message`, the success message is shown above the form.

### Remote functions

`--remote` generates the form with SvelteKit remote functions: a `form.remote.ts` takes the place of `+page.server.ts`, and remote functions are turned on in your SvelteKit config. `--route` and `--ui` work the same way.

```
$ vela generate form --remote contact name:text! email:email! message:editor
```

Creates:

```
src/routes/(public)/contact/+page.svelte
src/routes/(public)/contact/form.remote.ts
src/routes/(public)/contact/server.test.ts
src/lib/schemas/contact.ts
```

### Examples

```
$ vela generate form profile avatar:file bio:editor website:url
```

```
$ vela generate form feedback rating:select(1,2,3,4,5) comment:editor
```

### AI

> Pro

`--ai` designs the form from a natural-language description, in two stages: first the schema, then the layout. Pass a description _instead of_ a model name and fields, not as well as — passing both is an error.

```
$ vela generate form --ai "a feedback form with a 1-5 star rating"
```

Requires an account and a linked project — run [`vela login`](/account/login) and [`vela link`](/link) first.