Skip to content
Interactive demoDataCore

Validated forms

One Zod schema shared by the browser and the server, with field-level errors and a real submission lifecycle.

Built withServer ActionsZoduseActionState

Before you try it

What it needs

Nothing to configure. It runs the same everywhere.

Mode right now

ReadyThe provider is configured here; nobody has watched the real path succeed on this deployment yet.

A safe failure to try

Type a slug with spaces: the field is refused before submit, and the same schema refuses it again on the server.

New project

Every field below is validated twice. Try submitting the slug admin to see a rule the schema cannot express reject it on the server.

/p/

Generated from the name until you edit it.

Environments *

Optional. Up to 240 characters.

What to try

Each of these exercises a different validation layer.

Client

Blur the name field while empty — instant feedback, no request.

Server

Set the slug to “admin” — only the server knows it is reserved.

Schema

Type “My Project!” as the slug — the pattern rejects it on both sides.

Required

Untick every environment and submit — the array minimum fires.

What this demonstrates

  • A single schema is the contract for both sides of the wire
  • Client validation is a convenience; server validation is the security boundary
  • Errors attach to fields, announced via aria-describedby
  • Pending UI driven by useActionState rather than a manual boolean

Where the code lives

src/experiments/forms/demo.tsx

Registered in src/experiments/registry.ts and loaded on demand by loader.tsx.