Documentation
DirectForm is a form backend service that lets you add working contact forms to any website — static sites, React apps, Vue projects, and more — without writing any backend code.
Your endpoint
https://directform.vercel.app/f/YOUR_FORM_IDQuick Start
Create an account
Sign up at directform.vercel.app and create your first form.
Get your endpoint
Copy your unique form endpoint URL from the dashboard.
Add to your site
Point your form's action to your endpoint. That's it.
How It Works
When a user submits your form, DirectForm processes it through the following pipeline:
1. Receive form submission (JSON or multipart)
2. Validate CORS against allowed domains
3. Strip reserved fields (_redirect, _subject, etc)
4. Validate Cloudflare Turnstile token
5. Rate limit check (5 req/IP/form/hour)
6. Store submission in database
7. Send email notification via your SMTP
8. Send auto-reply to submitter (if enabled)
9. Redirect to success page or return JSON
HTML
The simplest integration — just set your form action to your endpoint.
<form action="https://directform.vercel.app/f/YOUR_ID" method="POST" > <!-- Redirect to your custom success page --> <input type="hidden" name="_next" value="https://yoursite.com/thanks" /> <input type="email" name="email" required /> <textarea name="message" required></textarea> <button type="submit">Send</button> </form>
React
Use the Fetch API to submit form data from your React component.
export default function ContactForm() {
async function handleSubmit(e) {
e.preventDefault();
const formData = new FormData(e.target);
await fetch(
"https://directform.vercel.app/f/YOUR_ID",
{ method: "POST", body: formData }
);
}
return (
<form onSubmit={handleSubmit}>
<input type="email" name="email" required />
<textarea name="message" required />
<button type="submit">Send</button>
</form>
);
}Vue
Use Vue's submit event modifier to handle form submissions.
<template>
<form @submit.prevent="handleSubmit">
<input type="email" name="email" required />
<textarea name="message" required />
<button type="submit">Send</button>
</form>
</template>
<script setup>
async function handleSubmit(e) {
const formData = new FormData(e.target);
await fetch(
"https://directform.vercel.app/f/YOUR_ID",
{ method: "POST", body: formData }
);
}
</script>Svelte
Use Svelte's event directive to handle form submissions cleanly.
<script>
async function handleSubmit(e) {
const formData = new FormData(e.target);
await fetch(
"https://directform.vercel.app/f/YOUR_ID",
{ method: "POST", body: formData }
);
}
</script>
<form on:submit|preventDefault={handleSubmit}>
<input type="email" name="email" required />
<textarea name="message" required />
<button type="submit">Send</button>
</form>Angular
Use Angular's HttpClient to post form data to your endpoint.
import { HttpClient } from "@angular/common/http";
export class ContactComponent {
constructor(private http: HttpClient) {}
handleSubmit(e: Event) {
const formData = new FormData(
e.target as HTMLFormElement
);
this.http.post(
"https://directform.vercel.app/f/YOUR_ID",
formData
).subscribe();
}
}Reserved Fields
These fields are processed by DirectForm and stripped before storing the submission.
| Field | Description |
|---|---|
| _next | URL to redirect to after successful submission (e.g. your custom thank you page) |
| _subject | Custom subject line for notification email |
| _replyto | Sets the reply-to address on notification email. Also used as the auto-reply recipient. |
| cf-turnstile-response | Cloudflare Turnstile spam protection token |
Email Notifications
DirectForm uses your own SMTP credentials to send email notifications. This means emails come from your own email address with no third party dependencies or sending limits.
Gmail
Host: smtp.gmail.com
Port: 587
Note: Use an App Password
Outlook
Host: smtp.office365.com
Port: 587
Note: Use your Microsoft password
Yahoo
Host: smtp.mail.yahoo.com
Port: 587
Note: Use an App Password
Auto-Reply
Automatically send a customizable reply email to the person who submitted your form. Perfect for confirming receipt of a message, sharing next steps, or setting expectations on response times.
How it works
- Enable Auto-Reply in your form settings
- Set a custom subject line and message body
- The recipient email is auto-detected from the
_replytofield or any field namedemail - The reply is sent using your configured SMTP credentials
<form action="https://directform.vercel.app/f/YOUR_ID" method="POST" > <!-- This field is used as the auto-reply recipient --> <input type="email" name="email" required /> <textarea name="message" required></textarea> <!-- Or use a hidden _replyto field --> <input type="hidden" name="_replyto" value="user@example.com" /> <button type="submit">Send</button> </form>
Note: Auto-reply requires SMTP to be configured in your account settings. If no recipient email is found in the submission, the auto-reply is silently skipped.
Spam Protection
DirectForm uses Cloudflare Turnstile for spam protection. Unlike reCAPTCHA, Turnstile is invisible to real users and never shows annoying puzzles. Simply enable it in your form settings and add the Turnstile widget to your form.
<!-- Add Turnstile script --> <script src="https://challenges.cloudflare.com/turnstile/v0/api.js"></script> <!-- Add widget inside your form --> <div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>
Rate Limiting
DirectForm automatically rate limits submissions to protect your forms from abuse. The current limit is 5 submissions per IP address per form per hour. When exceeded, the endpoint returns a 429 Too Many Requests response.
CSV Export
Export all submissions for any form as a CSV file directly from the dashboard. The CSV includes all fields submitted, timestamps, and auto-detects column headers from your form fields.
Submit Endpoint
Accepts both application/x-www-form-urlencoded and application/json content types.
Response Codes
| Code | Meaning |
|---|---|
| 302 | Success — redirects to _redirect or /thanks |
| 200 | Success — JSON { success: true } for fetch requests |
| 400 | Spam check failed (Turnstile validation error) |
| 403 | Domain not in allowed list |
| 404 | Form not found |
| 429 | Rate limit exceeded (5 req/IP/hour) |
| 500 | Internal server error |