Back to Skills

nextjs-tanstack-form

verified

TanStack Form for Next.js App Router - Server Actions, server validation, useActionState, Zod integration. Use when building forms in Next.js.

View on GitHub

Marketplace

fusengine-plugins

fusengine/agents

Plugin

fuse-nextjs

development

Repository

fusengine/agents

plugins/nextjs-expert/skills/nextjs-tanstack-form/SKILL.md

Last Verified

January 22, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/fusengine/agents/blob/main/plugins/nextjs-expert/skills/nextjs-tanstack-form/SKILL.md -a claude-code --skill nextjs-tanstack-form

Installation paths:

Claude
.claude/skills/nextjs-tanstack-form/
Powered by add-skill CLI

Instructions

# TanStack Form for Next.js

Type-safe forms with Server Actions and server-side validation.

## Installation

```bash
bun add @tanstack/react-form @tanstack/react-form-nextjs zod
```

---

## Shared Form Options

```typescript
// lib/forms/user-form.ts
import { formOptions } from '@tanstack/react-form'
import { z } from 'zod'

export const userSchema = z.object({
  email: z.string().email('Invalid email'),
  username: z.string().min(3, 'Min 3 characters'),
  age: z.number().min(18, 'Must be 18+'),
})

export const userFormOpts = formOptions({
  defaultValues: {
    email: '',
    username: '',
    age: 18,
  },
})
```

---

## Server Action with Validation

```typescript
// app/actions/user.ts
'use server'

import { ServerValidateError, createServerValidate } from '@tanstack/react-form-nextjs'
import { userFormOpts, userSchema } from '@/lib/forms/user-form'
import { prisma } from '@/lib/prisma'

const serverValidate = createServerValidate({
  ...userFormOpts,
  onServerValidate: async ({ value }) => {
    // Server-only validation (DB checks)
    const existing = await prisma.user.findUnique({
      where: { email: value.email },
    })

    if (existing) {
      return {
        fields: { email: 'Email already registered' },
      }
    }

    if (value.age < 18) {
      return 'You must be at least 18 to sign up'
    }

    return undefined
  },
})

export async function createUser(prev: unknown, formData: FormData) {
  try {
    const validatedData = await serverValidate(formData)

    await prisma.user.create({
      data: validatedData,
    })

    return { success: true }
  } catch (e) {
    if (e instanceof ServerValidateError) {
      return e.formState
    }
    throw e
  }
}
```

---

## Client Form Component

```typescript
// app/signup/SignupForm.tsx
'use client'

import { useActionState } from 'react'
import {
  initialFormState,
  mergeForm,
  useForm,
  useStore,
  useTransform,
} from '@tanstack/react-form-nextjs'
import { z } from 'zod'
import { cr

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
4305 chars