Remote Forms
For forms that submit to server actions using form from $app/server.
Define the Remote Function
// user.remote.ts
import { form } from '$app/server'
import { z } from 'zod/v4'
export const userSchema = z.object({
name: z.string(),
email: z.string().email()
})
export const createUserForm = form(userSchema, async (data) => {
await db.insert(users).values(data)
redirect(303, '/users')
})
Basic Usage
<script lang="ts">
import { TypedForm } from '@repo/form'
import { createUserForm, userSchema } from './user.remote'
</script>
<TypedForm.Remote form={createUserForm} schema={userSchema} />
Pre-populate for Edit
Fetch data and set it on the form before rendering.
<script lang="ts">
import { TypedForm } from '@repo/form'
import { updateUserForm, getUserQuery, userSchema } from './user.remote'
const { params } = $props()
const user = await getUserQuery({ id: params.id })
updateUserForm.fields.set(user)
</script>
<TypedForm.Remote form={updateUserForm} schema={userSchema} />
No-Args Form
For forms without input validation (e.g., delete buttons).
// user.remote.ts
export const deleteUserForm = form(async () => {
const { id } = await getValidatedParams(z.object({ id: z.string() }))
await db.delete(users).where(eq(users.id, id))
redirect(303, '/users')
})
<TypedForm.Remote form={deleteUserForm}>
{#snippet button({ submitting })}
<Button variant="destructive" disabled={submitting}>Delete</Button>
{/snippet}
</TypedForm.Remote>