Sanity & Formspark Form Generator
On the fly form generation with Sanity & Formspark
Form Field Builder
import {FaAlignLeft} from 'react-icons/fa'
export default {
name: 'formBuilder',
title: 'Form Builder',
icon: FaAlignLeft,
type: 'object',
fields: [
{
name: 'formFields',
title: 'Form Fields',
type: 'array',
of: [{type: 'formFields'}],
},
],
preview: {
prepare() {
return {
title: `Custom form setup`,
subtitle: `Form Builder`,
media: FaAlignLeft,
}
},
},
}
Form Fields
export default {
name: 'formFields',
title: 'Form Fields',
type: 'object',
fields: [
{
name: 'required',
title: 'Required',
type: 'boolean',
initialValue: false,
},
{
name: 'fieldName',
title: 'Field Name',
type: 'string',
validation: Rule => Rule.required(),
},
{
name: 'placeholder',
title: 'Placeholder',
type: 'string',
validation: Rule => Rule.required(),
},
{
name: 'fieldId',
title: 'Field ID',
type: 'slug',
options: {
source: (doc, options) => options.parent.fieldName,
maxLength: 200,
},
validation: Rule => Rule.required(),
},
{
name: 'inputType',
title: 'Input Type',
type: 'string',
initialValue: 'text',
options: {
layout: 'dropdown',
list: [
{value: 'text', title: 'Text input'},
{value: 'email', title: 'Email'},
{value: 'phone', title: 'Phone number'},
{value: 'textArea', title: 'Text area'},
{value: 'file', title: 'File upload'},
],
},
validation: Rule => Rule.required(),
},
],
};
React Code
'use client';
import { useFormspark } from '@formspark/use-formspark';
import React, { FC, useState } from 'react';
import { useForm } from 'react-hook-form';
const InputField = ({ type, id, fieldName, required, placeholder, register }) => (
<div>
<label htmlFor={id}>{fieldName}</label>
<div>
<input
type={type}
id={id}
required={!!required}
placeholder={placeholder}
aria-describedby={type}
{...register(id)}
/>
</div>
</div>
);
export const FormBuilderBlock = ({ formFields, uid }) => {
const [submitted, setSubmitted] = useState(false);
const [submit, submitting] = useFormspark({ formId: 'YOUR_FORMSPARK_ID' });
const { register, handleSubmit } = useForm();
const onSubmit = (data) => {
submit(data);
setSubmitted(true);
};
if (submitted) {
return (
<div>
<h1>Success box</h1>
</div>
);
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
{Array.isArray(formFields) &&
formFields.map((field) => {
const { inputType, _key, fieldId, placeholder, _type, fieldName, required } = field ?? {};
const { current } = fieldId ?? {};
if (!inputType || !current) return null;
if (inputType === 'textArea') {
return (
<div key={_key}>
<label htmlFor={current}>{fieldName}</label>
<div>
<textarea
id={current}
required={!!required}
placeholder={placeholder}
aria-describedby="textarea"
{...register(current)}
/>
</div>
</div>
);
}
return (
<InputField
key={_key}
type={inputType}
id={current}
fieldName={fieldName}
required={required}
placeholder={placeholder}
register={register}
/>
);
})}
<button type="submit" disabled={submitting}>
Submit
</button>
</form>
);
};
You're coming from WordPress, and you want to get similar functionality to WP Forms but without the monstrous negative performance cost of actually using WordPress?
Boy gee, do we have some schema to help you out! This piece of code helps you to:
- Generate forms on the fly
- Add fields to a form
- Remove fields from a form
- Create
textareas,text inputs,email inputs, etc - Generate an email when somebody submits
It's also using React Server Components, so feel free to drop the "use client" if you're using an older version of React or Next.js.
Oh, and if you're wondering why we're using Formspark? It's because it's got probably the best pricing tier for any form-handling system we've seen. Seriously 50,000 submissions for $25. I honestly don't know how they stay afloat as a business.
Want more great tips on how to structure your Sanity schema, Are you looking to build your company website with Sanity? Want to see what you can achieve with our team of experts?
Contributors

Roboto Studio
The best editorial experiences on the web

Hrithik Prasad
Technical Lead at Roboto Studio
India
