Skip to main content

Forms & Validation

Schema-driven forms that auto-generate from Zod schemas.

Package: @repo/form Built on: SuperForms, Zod

Basic Usage

<script lang="ts">
import { createUserForm } from '$lib/domains/users/database/users.remote'
import { userInsertSchema } from '$lib/domains/users/utils/schemas'
import { TypedForm } from '@repo/form'
</script>

<TypedForm.Remote form={createUserForm} schema={userInsertSchema} />

Custom Field Layout

Use TypedForm.RemoteField for custom layouts:

<TypedForm.Remote form={createInvitationForm} schema={invitationInsertSchema}>
{#snippet children({ fields })}
<TypedForm.RemoteField field={fields.name} />
<TypedForm.RemoteField field={fields.email} />
<TypedForm.RemoteField field={fields.roles} optionItems={roles} />
{/snippet}
</TypedForm.Remote>

Field Customization with zaf()

Customize field rendering in schemas:

import { TypedForm, zaf } from '@repo/form'

const schema = z.object({
name: zaf(z.string(), {
label: 'Full Name',
placeholder: 'John Doe',
}),
message: zaf(z.string().optional(), {
component: TypedForm.TextareaInput,
}),
})

Server-Side Form Definition

// users.remote.ts
import { form } from '$app/server'
import { userInsertSchema } from '$lib/domains/users/utils/schemas'

export const createUserForm = form(userInsertSchema, async (data) => {
const { db, usersTable } = await getTenantDb()
await db.insert(usersTable).values(data)
redirect(303, '/users')
})

Pre-Population (Edit Forms)

Set initial values before rendering:

<script lang="ts">
import { updateUserForm, getUserQuery } from '$lib/domains/users/database/users.remote'
import { userInsertSchema } from '$lib/domains/users/utils/schemas'

const { params } = $props()
updateUserForm.fields.set(await getUserQuery({ id: params.id }))
</script>

<TypedForm.Remote form={updateUserForm} schema={userInsertSchema} />

Full Documentation

See @repo/form for complete API reference.