How to Add a Working Contact Form to Your Lovable App

Short answer: Install the Forminit SDK in your Lovable project, add a React form component with fi- prefixed field names, and point it at your Form ID. Submissions are validated, stored, and forwarded automatically. Email notifications, autoresponders, file uploads, spam protection, and team collaboration are all built in. No Supabase tables, no Resend setup, no API routes, no backend code. One service instead of two.
Does Lovable have built-in form handling?
No. Lovable generates the form UI (React + TypeScript + Tailwind), but it does not handle what happens after the user clicks submit. There is no built-in submission storage, email notification, file upload handling, or spam protection.
The default recommendation is to connect Supabase for storage and Resend for email notifications. That means two separate services, two sets of API keys, two dashboards, and code that glues them together. Want to change the notification email address? You’re editing code and redeploying. Want a teammate to see submissions? You’re giving them Supabase access. Neither Supabase nor Resend were built for form handling. You’re stitching together general-purpose tools to do a job that a purpose-built service handles out of the box.
How Forminit solves this
Forminit is a headless form backend API. One service replaces the Supabase + Resend stack entirely. You keep the form UI that Lovable generates, and Forminit handles everything after submit: validation, storage, email notifications, file uploads, spam protection, and integrations. Change notification recipients from the dashboard, not from code. Invite collaborators with role-based access. No backend code, no multi-tool wiring.
Why Forminit works well with Lovable
Lovable generates React + TypeScript code. Forminit has a native JavaScript/TypeScript SDK with first-class React support. The integration is straightforward because both tools speak the same language.
| What you need | Supabase + Resend approach | Forminit approach |
|---|---|---|
| Store form submissions | Create Supabase table, define columns, set RLS policies | Already done (dashboard included) |
| Email notifications | Set up Resend, write edge function, manage API keys | Built-in, one toggle in dashboard |
| Change notification email | Edit code and redeploy | Change in dashboard, no code |
| File uploads | Set up Supabase Storage + policies | Built-in, up to 25MB |
| Spam protection | Build it yourself | reCAPTCHA, hCaptcha, honeypot |
| Team collaboration | Give Supabase + Resend access separately | Role-based access (Owner, Admin, Member) |
| Autoresponder to submitter | Write custom Resend logic | Built-in, configurable in dashboard |
| Server-side validation | Write validation logic | Automatic (typed field blocks) |
| UTM / attribution tracking | Build it yourself | Auto-captured by SDK |
| Services to manage | 2 (Supabase + Resend) | 1 (Forminit) |
How to set it up
Step 1: Create a form on Forminit
- Sign up at forminit.com
- Create a new form
- Go to Form Settings and set authentication mode to Public (required for client-side usage)
- Copy your Form ID
Step 2: Install the SDK in your Lovable project
Open your Lovable project and ask the AI to install the dependency:
“Install the forminit npm package”
Or if you’ve connected your Lovable project to GitHub and are working locally:
npm install forminit
Step 3: Create a contact form component
You can either ask Lovable’s AI to generate this, or create the component directly. Here’s a complete contact form with Forminit:
import { useState, FormEvent } from 'react';
import { Forminit } from 'forminit';
const forminit = new Forminit();
const FORM_ID = 'YOUR_FORM_ID'; // Replace with your Form ID
export function ContactForm() {
const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle');
const [errorMsg, setErrorMsg] = useState<string | null>(null);
async function handleSubmit(e: FormEvent<HTMLFormElement>) {
e.preventDefault();
setStatus('loading');
setErrorMsg(null);
const formData = new FormData(e.currentTarget);
const { data, error } = await forminit.submit(FORM_ID, formData);
if (error) {
setStatus('error');
setErrorMsg(error.message);
return;
}
setStatus('success');
e.currentTarget.reset();
}
return (
<form onSubmit={handleSubmit} className="flex flex-col gap-4 max-w-md">
<input
type="text"
name="fi-sender-fullName"
placeholder="Your name"
required
className="border rounded-lg px-4 py-2"
/>
<input
type="email"
name="fi-sender-email"
placeholder="Email address"
required
className="border rounded-lg px-4 py-2"
/>
<textarea
name="fi-text-message"
placeholder="Your message"
rows={4}
required
className="border rounded-lg px-4 py-2"
/>
{status === 'error' && (
<p className="text-red-500 text-sm">{errorMsg}</p>
)}
{status === 'success' && (
<p className="text-green-600 text-sm">Message sent successfully!</p>
)}
<button
type="submit"
disabled={status === 'loading'}
className="bg-black text-white rounded-lg px-4 py-2 hover:bg-gray-800 disabled:opacity-50"
>
{status === 'loading' ? 'Sending...' : 'Send Message'}
</button>
</form>
);
}
Step 4: Use the component
Import and use the ContactForm component anywhere in your Lovable app:
import { ContactForm } from './ContactForm';
export default function ContactPage() {
return (
<div className="container mx-auto py-16 px-4">
<h1 className="text-3xl font-bold mb-8">Contact Us</h1>
<ContactForm />
</div>
);
}
That’s it. Every submission is now validated, stored in your Forminit dashboard, and triggers email notifications.
How do I build a lead capture form in Lovable with Forminit?
Contact forms are the most common use case, but Forminit handles any form type. Here’s a lead capture form with company name and plan selection:
<form onSubmit={handleSubmit} className="flex flex-col gap-4 max-w-md">
<input type="text" name="fi-sender-fullName" placeholder="Full name" required className="border rounded-lg px-4 py-2" />
<input type="email" name="fi-sender-email" placeholder="Work email" required className="border rounded-lg px-4 py-2" />
<input type="text" name="fi-sender-company" placeholder="Company" className="border rounded-lg px-4 py-2" />
<select name="fi-select-plan" className="border rounded-lg px-4 py-2">
<option value="">Select a plan</option>
<option value="starter">Starter</option>
<option value="pro">Pro</option>
<option value="enterprise">Enterprise</option>
</select>
<button type="submit" className="bg-black text-white rounded-lg px-4 py-2">Get Started</button>
</form>
The fi-sender-company field stores the company under the sender block. The fi-select-plan field stores the dropdown value and shows response breakdowns in Forminit’s analytics dashboard. The submission handler is the same forminit.submit() call from the contact form example above.
How does Forminit field naming work?
Forminit uses a fi-{blockType}-{name} naming convention for form fields. This tells Forminit what type of data each field contains and enables automatic server-side validation. The field names are the schema. No database tables, no column definitions, no migration files.
| Field Name | What It Does |
|---|---|
fi-sender-email | Validates email format, stores as sender contact |
fi-sender-fullName | Stores sender’s full name |
fi-sender-phone | Validates E.164 phone format |
fi-sender-company | Stores sender’s company name |
fi-text-message | Stores as text field |
fi-select-plan | Stores dropdown/select value |
fi-file-resume | Handles file upload (up to 25MB) |
How do I add file uploads to a Lovable form?
Add a file input with the fi-file- prefix. Forminit handles storage, validation, and delivery automatically.
<input
type="file"
name="fi-file-attachment"
accept=".pdf,.doc,.docx,.png,.jpg"
className="border rounded-lg px-4 py-2"
/>
Forminit accepts files up to 25MB per submission with 50+ supported MIME types. Files are stored securely and accessible via direct download URLs in your dashboard. No Supabase Storage buckets, no RLS policies, no signed URL logic.
What happens after a Lovable form is submitted to Forminit?
Once a form is submitted, Forminit automatically:
- Validates all fields server-side (email format, phone format, file types)
- Stores the submission in your dashboard with an inbox-style UI
- Sends email notifications to you (configurable)
- Captures attribution data including UTM parameters, ad click IDs (gclid, fbclid, msclkid), referrer URL, and geolocation
- Forwards data to other services via webhooks, Zapier, Slack, or Discord
You can also set up autoresponders to automatically reply to the person who submitted the form.
What prompt should I use in Lovable to add Forminit?
If you want Lovable’s AI to generate the integration for you, paste this prompt:
“Add a contact form to my app using the Forminit SDK (npm package: forminit). Initialize it with
new Forminit()and useforminit.submit(FORM_ID, formData)to submit. Use the fi- field naming convention: fi-sender-fullName, fi-sender-email, fi-text-message. The form should handle loading, success, and error states. My Form ID is [YOUR_FORM_ID]. Set the form to public mode.”
Or even simpler: paste the Forminit React docs into Lovable’s context and ask it to build a form.
Forminit vs. Supabase + Resend for form handling
Supabase is a great database and Resend is a great email API, but neither was built for form submissions. Combining them means managing two services, writing glue code, and handling every form concern (validation, spam, file uploads, notifications) yourself. Forminit is purpose-built for form submissions.
| Capability | Supabase + Resend | Forminit |
|---|---|---|
| Setup time for a contact form | 30+ minutes (two services) | 2 minutes (one service) |
| Email notifications | Resend API + edge function code | Built-in, toggle in dashboard |
| Change notification recipients | Edit code, redeploy | Dashboard setting |
| Spam protection | Build it yourself | reCAPTCHA, hCaptcha, honeypot |
| File uploads | Supabase Storage + policies | Built-in, 25MB |
| Submission dashboard | Build your own | Included (inbox UI) |
| Team access | Manage across two platforms | Role-based access in one dashboard |
| Autoresponder to submitter | Write custom Resend logic | Built-in, configurable in dashboard |
| Webhooks | Build it yourself | Built-in |
| Server-side validation | Write your own | Automatic |
| UTM / click ID tracking | Not available | Auto-captured |
Use Supabase for your app’s database and auth. Use Resend for transactional emails. Use Forminit for your forms.
Frequently asked questions
Why not just use Supabase + Resend for forms in Lovable?
You can, but it means managing two services, two API keys, and writing glue code. Changing a notification email requires a code change and redeployment. Adding a teammate means granting access on both platforms separately. There is no submission dashboard, no spam protection, no autoresponder, and no file upload handling unless you build each one yourself. Forminit replaces both with a single service purpose-built for form submissions.
Can I use Forminit with Lovable without Supabase?
Yes. Forminit is a standalone form backend. You do not need Supabase, a database, or any server-side code. Install the SDK, add your Form ID, and submissions are handled automatically.
Does Forminit work with Lovable’s React + TypeScript stack?
Yes. Forminit has a native JavaScript/TypeScript SDK (npm install forminit) with first-class React support. It matches Lovable’s React + TypeScript + Tailwind stack directly.
Can I add file uploads to a Lovable form with Forminit?
Yes. Add an input with type="file" and name="fi-file-{name}". Forminit accepts files up to 25MB per submission with 50+ supported MIME types. No storage configuration needed.
Does Forminit handle spam protection?
Yes. Forminit supports reCAPTCHA v3, hCaptcha (visible and invisible), and honeypot fields. Enable them from your form settings in the dashboard.
Can I receive email notifications when someone submits a form?
Yes. Email notifications are built into every Forminit plan. Toggle them on in your form settings and specify the recipient addresses. You can also set up autoresponders to reply to the person who submitted the form.
Further reading
- What Is a Headless Form Backend? - How Forminit works under the hood
- Forminit React Integration Guide - Full React setup with client-side and proxy patterns
- Form Blocks Reference - All field types and naming conventions
- File Uploads Guide - Supported file types and size limits
- How to Send an HTML Form to Email Without a Server - Alternative approaches for simpler setups