https://github.com/didier/formshape
Type-safe form validation for SvelteKit Remote Functions using Standard Schema compatible validators.
https://github.com/didier/formshape
forms remote-functions standard-schema svelte sveltekit sveltekit-remote-functions valibot zod
Last synced: about 2 months ago
JSON representation
Type-safe form validation for SvelteKit Remote Functions using Standard Schema compatible validators.
- Host: GitHub
- URL: https://github.com/didier/formshape
- Owner: didier
- Created: 2025-08-13T00:14:56.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2025-08-13T00:53:39.000Z (5 months ago)
- Last Synced: 2025-11-09T09:39:37.257Z (2 months ago)
- Topics: forms, remote-functions, standard-schema, svelte, sveltekit, sveltekit-remote-functions, valibot, zod
- Language: TypeScript
- Homepage: https://formshape.vercel.app
- Size: 538 KB
- Stars: 12
- Watchers: 0
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# formshape
[](https://www.npmjs.com/package/formshape)
Type-safe form validation for SvelteKit Remote Functions using [Standard Schema](https://standardschema.dev/) compatible validators.
## Features
- 🎯 Works with any Standard Schema compatible library (Zod, Valibot, Arktype, etc.)
- 🔒 Full type safety with automatic type inference
- âš¡ Preserves all SvelteKit form features (progressive enhancement, `enhance`, `buttonProps`, etc.)
- 📦 Lightweight with zero dependencies (besides your validator)
- 🎠Same API as SvelteKit's `form` function
## Installation
```bash
npm install formshape
# or
pnpm add formshape
```
## Usage
### 1. Create a validated function in your server code
```typescript
// src/routes/contact/data.remote.ts
import { z } from 'zod'
import { form } from '$app/server'
import { createValidated } from 'formshape'
// Create the validated function using your app's form function
const validated = createValidated(form)
// Define your schema
const contactSchema = z.object({
name: z.string().min(2, 'Name must be at least 2 characters'),
email: z.string().email('Invalid email address'),
message: z.string().min(10, 'Message must be at least 10 characters')
})
// Create your form handler - data is fully typed!
export const submitContact = validated(contactSchema, async (data) => {
// data is typed as { name: string; email: string; message: string }
await sendEmail(data)
return {
success: true,
message: 'Thank you for your message!'
}
})
```
### 2. Use it in your Svelte component
```svelte
import { submitContact } from './data.remote.js'
{#if submitContact.result && 'errors' in submitContact.result}
{submitContact.result.errors.name?.join(', ')}
{/if}
{#if submitContact.result && 'errors' in submitContact.result}
{submitContact.result.errors.email?.join(', ')}
{/if}
{#if submitContact.result && 'errors' in submitContact.result}
{submitContact.result.errors.message?.join(', ')}
{/if}
Send Message
{#if submitContact.result?.success === true}
{submitContact.result.message}
{/if}
```
## How it works
The `createValidated` function takes your app's `form` function and returns a `validated` function. This approach ensures that the package works correctly when installed from npm, as it uses your app's SvelteKit context rather than trying to import from `$app/server` directly.
When validation fails, the function returns:
```typescript
{
success: false,
errors: Record,
data: unknown // The original form data
}
```
When validation succeeds, your handler is called with the validated data and its return value is passed through.
## Using with enhance
The validated form maintains full compatibility with SvelteKit's `enhance`:
```svelte
{
const result = await submit()
// Handle the result
})}
>
```
## Using with other validators
Any Standard Schema compatible validator works:
### Valibot
```typescript
import * as v from 'valibot'
const schema = v.object({
email: v.pipe(v.string(), v.email())
})
export const myForm = validated(schema, async (data) => {
// ...
})
```
### Arktype
```typescript
import { type } from 'arktype'
const schema = type({
email: 'email',
age: 'number > 0'
})
export const myForm = validated(schema, async (data) => {
// ...
})
```
## API
### `createValidated(form)`
Creates a validated function using your app's form function.
- **Parameters:**
- `form`: The form function from `$app/server`
- **Returns:** A `validated` function
### `validated(schema, handler)`
Creates a form handler with validation.
- **Parameters:**
- `schema`: A Standard Schema compatible validator
- `handler`: An async function that receives validated data
- **Returns:** A `RemoteForm` object (same as SvelteKit's `form`)
## License
MIT