Single-page apps often want to stay on the current route and show an inline success message. Formbase returns a 303 redirect for browser submissions, so you should prevent the browser from following it and handle the result manually.
There are two recommended patterns:
- Client-side fetch with
redirect: 'manual'
- Server-side submit (API route or server action)
Client-side fetch
const response = await fetch('https://formbase.dev/s/YOUR_FORM_ID', {
method: 'POST',
body: new FormData(event.currentTarget),
redirect: 'manual',
});
if (response.status === 303 || response.ok) {
setStatus('Submitted!');
}
const response = await fetch('https://formbase.dev/s/YOUR_FORM_ID', {
method: 'POST',
body: new FormData(event.currentTarget),
redirect: 'manual',
});
status.value = response.status === 303 || response.ok
? 'Submitted!'
: 'Failed.';
const response = await fetch('https://formbase.dev/s/YOUR_FORM_ID', {
method: 'POST',
body: new FormData(event.currentTarget),
redirect: 'manual',
});
status = response.status === 303 || response.ok
? 'Submitted!'
: 'Failed.';
redirect: 'manual' prevents the browser from following the redirect and failing CORS checks.Server-side submit
Post to Formbase from your backend (API route, server action, or serverless function). This returns JSON and avoids browser redirects entirely.
If you use a server action (Next.js, Remix), you get a JSON response from Formbase and can return a clean success state to the client.