Usage
Usage
Usage
Learn how to integrate Formic into your web application.
Quick Start
- Get your API key from the Formic dashboard
- Create a form in the dashboard and get your form slug
- Set up the adapter for your framework
- Submit forms from your frontend
Frontend Integration
Simple Form Submission
<form id="my-form">
<input type="email" name="email" required placeholder="Your email">
<textarea name="message" required placeholder="Your message"></textarea>
<button type="submit">Submit</button>
</form>
<script>
document.getElementById('my-form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const data = Object.fromEntries(formData);
const response = await fetch('/api/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
const result = await response.json();
console.log(result);
});
</script>
With React/Vue/Svelte
// React example
function ContactForm() {
const [status, setStatus] = useState('idle');
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const data = Object.fromEntries(formData);
setStatus('submitting');
const res = await fetch('/api/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
const result = await res.json();
setStatus(result.success ? 'success' : 'error');
};
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" required />
<textarea name="message" required />
<button type="submit" disabled={status === 'submitting'}>
{status === 'submitting' ? 'Sending...' : 'Send'}
</button>
</form>
);
}
Security Best Practices
When using the Formic client library, follow these security guidelines:
- Never expose your API key in client-side code — Always use the server-side proxy pattern (see examples below). The API key should only exist in server-side environment variables.
- Use server-side adapters — The Astro, Next.js, and Remix adapters handle request proxying so the API key stays on your server.
- Validate payload size client-side — Enable
validatePayloadSize: trueto catch oversized submissions before they reach the network. - Forward Turnstile tokens — Pass Turnstile tokens from your frontend to the Formic API for anti-bot protection.
For a complete guide, see the Security Overview and Authentication documentation.
Server-Side Setup
Astro
// src/pages/api/contact.ts
import { handleFormicRequest } from '@audelabs/formic-client/adapters/astro';
export const POST = handleFormicRequest({
apiKey: import.meta.env.FORMIC_API_KEY,
slug: 'contact-form'
});
Next.js (App Router)
// app/api/contact/route.ts
import { handleFormicRequest } from '@audelabs/formic-client/adapters/next';
export const POST = handleFormicRequest({
apiKey: process.env.FORMIC_API_KEY!,
slug: 'contact-form'
}).POST;
Remix
// app/routes/contact.tsx
import { handleFormicRequest } from '@audelabs/formic-client/adapters/remix';
export const action = handleFormicRequest({
apiKey: process.env.FORMIC_API_KEY!,
slug: 'contact-form'
});
Error Handling
All adapters support error handling via try/catch:
import { createFormicClient } from '@audelabs/formic-client/adapters/next';
export const POST = async (request) => {
try {
const client = createFormicClient({
apiKey: process.env.FORMIC_API_KEY!,
slug: 'my-form'
});
return await client.handleProxyRequest(request);
} catch (error) {
return new Response(JSON.stringify({
error: 'Submission failed',
message: error instanceof Error ? error.message : 'Unknown error'
}), { status: 500 });
}
};
Configuration Options
Custom Base URL
Use a custom API endpoint for development or testing:
const client = new FormicClient({
apiKey: 'your-api-key',
slug: 'your-form-slug',
baseUrl: 'http://localhost:3000' // For local development
});
Hooks
Adapters support before/after hooks:
handleFormicRequest({
apiKey: process.env.FORMIC_API_KEY!,
slug: 'my-form',
beforeRequest: (request) => {
console.log('Processing form submission...');
},
afterResponse: (response) => {
console.log('Form submitted successfully');
}
});