tanstack-form
Handles form state management and Zod schema validation within Svelte 5 applications.
Install
mkdir -p .claude/skills/tanstack-form && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/1563" && unzip -o skill.zip -d .claude/skills/tanstack-form && rm skill.zipInstalls to .claude/skills/tanstack-form
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Use this skill when building or modifying forms with TanStack Form and Zod validation. Covers createForm, field-level validation, error handling, and mapping ProblemDetails API errors to form fields. Apply when adding new forms, implementing validation logic, or handling form submission in the Svelte frontend.Key capabilities
- →Manage form state using TanStack Form
- →Implement field-level validation with Zod schemas
- →Map API ProblemDetails errors to form fields
- →Handle form submission states and async operations
- →Integrate forms within Svelte components
How it works
It uses TanStack Form to manage state and Zod for validation, providing patterns to map backend error responses directly to UI fields.
Inputs & outputs
When to use tanstack-form
- →Creating complex forms
- →Validating user input with Zod
- →Managing form state in Svelte
- →Implementing form error handling
About this skill
TanStack Form
Documentation: tanstack.com/form. Use official docs when the local pattern is not enough.
Use TanStack Form (@tanstack/svelte-form) with Zod for form state management.
Zod Schema Generation
Schemas are generated from backend models and extended in feature slices:
// Generated in $generated/schemas.ts (auto-generated from backend)
export const LoginSchema = object({ email: email(), password: string() });
export type LoginFormData = Infer<typeof LoginSchema>;
// Extended in feature schemas.ts
// From src/lib/features/auth/schemas.ts
import { ChangePasswordModelSchema } from "$generated/schemas";
export const ChangePasswordSchema = ChangePasswordModelSchema.extend({
confirm_password: string().min(6).max(100),
}).refine((data) => data.password === data.confirm_password, {
message: "Passwords do not match",
path: ["confirm_password"],
});
export type ChangePasswordFormData = Infer<typeof ChangePasswordSchema>;
// Re-export generated schemas
export { LoginSchema, type LoginFormData } from "$generated/schemas";
Basic Form Pattern
From src/Exceptionless.Web/ClientApp/src/routes/(auth)/login/+page.svelte:
<script lang="ts">
import { createForm } from '@tanstack/svelte-form';
import * as Field from '$comp/ui/field';
import { Input } from '$comp/ui/input';
import { Button } from '$comp/ui/button';
import { type LoginFormData, LoginSchema } from '$features/auth/schemas';
import { ariaInvalid, mapFieldErrors, problemDetailsToFormErrors } from '$shared/validation';
const form = createForm(() => ({
defaultValues: {
email: '',
password: ''
} as LoginFormData,
validators: {
onSubmit: LoginSchema,
onSubmitAsync: async ({ value }) => {
const response = await login(value.email, value.password);
if (response.ok) {
await goto('/');
return null;
}
return problemDetailsToFormErrors(response.problem);
}
}
}));
</script>
<form onsubmit={(e) => { e.preventDefault(); form.handleSubmit(); }}>
<form.Field name="email">
{#snippet children(field)}
<Field.Field data-invalid={ariaInvalid(field)}>
<Field.Label for={field.name}>Email</Field.Label>
<Input
id={field.name}
type="email"
value={field.state.value}
onblur={field.handleBlur}
oninput={(e) => field.handleChange(e.currentTarget.value)}
aria-invalid={ariaInvalid(field)}
/>
<Field.Error errors={mapFieldErrors(field.state.meta.errors)} />
</Field.Field>
{/snippet}
</form.Field>
<form.Subscribe selector={(state) => state.isSubmitting}>
{#snippet children(isSubmitting)}
<Button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Logging in...' : 'Log In'}
</Button>
{/snippet}
</form.Subscribe>
</form>
Server Error Handling
Convert ProblemDetails to form errors:
onSubmitAsync: async ({ value }) => {
const response = await login(value.email, value.password);
if (response.ok) return null;
return problemDetailsToFormErrors(response.problem);
};
Form in Dialog Pattern
Close dialog only after successful submission:
let open = $state(false);
const form = createForm(() => ({
defaultValues: { name: '' },
validators: {
onSubmit: mySchema,
onSubmitAsync: async ({ value }) => {
try {
await createMutation.mutateAsync(value);
open = false;
return null;
} catch (error: unknown) {
if (error instanceof ProblemDetails) {
return problemDetailsToFormErrors(error);
}
return { form: 'An unexpected error occurred' };
}
}
}
}));
References
See shadcn-svelte for Field component patterns.
When not to use it
- →When building forms outside of a Svelte 5 environment
- →When not using TanStack Form for state management
Prerequisites
Limitations
- →Relies on specific project structures for schema generation
- →Requires integration with existing UI component libraries
How it compares
It provides a standardized pattern for mapping complex API error structures to form fields, which is typically handled manually.
Compared to similar skills
tanstack-form side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| tanstack-form (this skill) | 16 | 2mo | No flags | Intermediate |
| svelte-ui-design | 23 | 9mo | No flags | Intermediate |
| tanstack-query | 7 | 2mo | No flags | Intermediate |
| svelte | 3 | 2mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by exceptionless
View all by exceptionless →You might also like
svelte-ui-design
XIYO
ALWAYS use this skill for ANY Svelte component styling, design, or UI work. Svelte 5 UI design system using Tailwind CSS 4, Skeleton Labs design tokens/presets/Tailwind Components, and Bits UI headless components. Covers class composition, color systems, interactive components, forms, overlays, and all visual design.
tanstack-query
exceptionless
Data fetching and caching with TanStack Query in Svelte. Query patterns, mutations, cache invalidation, WebSocket-driven updates, and optimistic updates. Keywords: createQuery, createMutation, TanStack Query, query keys, cache invalidation, optimistic updates, refetch, stale time, @exceptionless/fetchclient, WebSocket
svelte
EpicenterHQ
Svelte 5 patterns including TanStack Query mutations, shadcn-svelte components, and component composition. Use when writing Svelte components, using TanStack Query, or working with shadcn-svelte UI.
svelte-migrate
temporalio
Migrate a Svelte 4 component to Svelte 5 runes syntax. Use when asked to migrate, convert, or upgrade a .svelte file to Svelte 5.
admin-crud-page
svelte-society
Create admin dashboard pages with tables, forms, and actions
component-builder
svelte-society
Create UI components using tailwind-variants for type-safe styling. Use when creating or editing components in src/lib/ui/.