Remix forms run through server-side actions by default, which is ideal for Formbase. Your action can forward the form data to Formbase and return a clean success or error state to the client.
This avoids browser redirects and gives you full control over validation and UI feedback.
Create a Remix action
Forward the form data to Formbase from the server.// app/routes/contact.tsx
import { json } from '@remix-run/node';
export async function action({ request }) {
const formData = await request.formData();
const response = await fetch('https://formbase.dev/s/YOUR_FORM_ID', {
method: 'POST',
body: formData,
});
if (!response.ok) {
return json({ ok: false, message: 'Submission failed.' }, { status: 400 });
}
return json({ ok: true, message: 'Submitted!' });
}
Because this runs on the server, Formbase responds with JSON. Build the form
import { Form, useActionData } from '@remix-run/react';
export default function ContactPage() {
const actionData = useActionData();
return (
<Form method="post">
<input name="name" placeholder="Name" required />
<input name="email" type="email" placeholder="Email" required />
<textarea name="message" required />
<button type="submit">Send</button>
{actionData?.message && <p>{actionData.message}</p>}
</Form>
);
}
Add encType="multipart/form-data" if you include file inputs.
Server actions are the recommended Remix pattern. Client-side fetch works too, but you must handle a 303 redirect response.