Forms
SnipForm Forms give you a form backend without writing one. You supply the markup (or let the dashboard supply it), and SnipForm validates every submission on the server, scores it for spam, stores it, notifies your team, and records it in Signals as a form submit.
There are three clients. All three talk to the same server, share the same validation rules, and run the same session model.
Pick a client
Section titled “Pick a client”| HTML library | React | Managed | |
|---|---|---|---|
| You write | HTML with sf- directives | JSX with a hook | Nothing. Fields live in the dashboard |
| Styling | Yours | Yours | Dashboard theme, overridable with CSS variables |
| Works in | Static sites, Astro, Blade, WordPress, anything that renders HTML | React 18+, Next.js, Remix, Vite | Any page that can hold a script tag |
| Validation feedback | Directives toggle classes, text and visibility | errors in React state, optional validate-on-blur | Rendered for you |
| Start | HTML library | React | Managed forms |
Use the HTML library unless React renders the form. The HTML library works by mutating the DOM, and React overwrites those mutations on its next render, which breaks the validation UI. The React package keeps values, errors and status in React state and never touches the DOM.
The same form, three ways
Section titled “The same form, three ways”<snip-form key="YOUR_FORM_KEY"> <form> <input type="email" name="email" sf-validate:required sf-validate:email /> <div if-error="email" then-show-text></div> <button type="submit" on-submit-text="Sending...">Subscribe</button> </form> <sf-success style="display:none"> <h2>Thanks, %email% is on the list.</h2> </sf-success></snip-form><script src="https://cdn.snipform.io/api/v2/sf.iife.js" defer></script>import { useSnipForm, SnipForm, FieldError } from '@snipform/react';
export function Subscribe() { const form = useSnipForm({ key: 'YOUR_FORM_KEY', fields: { email: { type: 'email', rules: { required: null, email: null } } }, });
if (form.success) return <h2>Thanks, {form.success.values.email} is on the list.</h2>;
return ( <SnipForm form={form}> <input {...form.register('email')} placeholder="Email" /> <FieldError form={form} name="email" /> <button disabled={form.isSubmitting}>Subscribe</button> </SnipForm> );}<snip-form data-key="YOUR_FORM_KEY"></snip-form><script src="https://cdn.snipform.io/api/v2/sf.iife.js" defer></script>What every client gets
Section titled “What every client gets”- Server validation. 35 Laravel rules, applied by the server, so the client can never disagree with what gets stored.
- Spam protection without a CAPTCHA. A human gate, a honeypot and behavioural scoring. Spam is stored, labelled and kept out of your inbox, and the bot is never told.
- Double-submit protection. Each form session is single use.
- Domain lock. A form only initialises from its property’s domain (plus localhost when you switch that on).
- Signals tracking. Every accepted submission is a
form_submitevent on the visitor’s session, usable as a conversion step and as an automation trigger. - Notifications. Submissions email the form’s notification list and can post to Slack, call a webhook or create a contact through Automations.
- Style integrity. The HTML library never changes your CSS unless a directive tells it to. The React package renders nothing you did not write.
Documentation
Section titled “Documentation”- How forms work - the session model behind all three clients: init, token, submit, and what 419 and 403 mean.
- Validation rules - every rule, with parameters and custom messages.
- HTML library - getting started, then error states, valid states, submit states, success content and testing.
- React -
useSnipForm, then inputs, validation and spam protection. - Managed forms - build the fields in the dashboard and embed a single tag.
- IDE setup - autocomplete for the directives in VS Code and JetBrains.