Documentation
Framework Examples
Integrate Static Forms with your favorite framework
Choose Your Framework
Basic React component with form handling:
import { useState } from 'react';
export default function ContactForm() {
const [status, setStatus] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
const form = e.target;
const data = new FormData(form);
try {
const response = await fetch('https://api.staticforms.xyz/submit', {
method: 'POST',
body: data
});
if (response.ok) {
setStatus('Message sent successfully!');
form.reset();
} else {
setStatus('Error sending message.');
}
} catch (error) {
setStatus('Error sending message.');
}
};
return (
<form onSubmit={handleSubmit}>
<input type="hidden" name="apiKey" value="YOUR_API_KEY" />
<input
type="text"
name="name"
placeholder="Your Name"
required
/>
<input
type="email"
name="email"
placeholder="Your Email"
required
/>
<textarea
name="message"
placeholder="Your Message"
required
/>
<button type="submit">Send Message</button>
{status && <p>{status}</p>}
</form>
);
}Next.js component with server-side API key handling:
'use client';
import { useState } from 'react';
export default function ContactForm() {
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
const formData = new FormData(e.target);
try {
const response = await fetch('https://api.staticforms.xyz/submit', {
method: 'POST',
body: formData,
});
const result = await response.json();
if (result.success) {
setMessage('Message sent successfully!');
e.target.reset();
} else {
setMessage('Failed to send message.');
}
} catch (error) {
setMessage('An error occurred.');
} finally {
setLoading(false);
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="hidden"
name="apiKey"
value={process.env.NEXT_PUBLIC_STATICFORMS_KEY}
/>
<div>
<label htmlFor="name">Name</label>
<input id="name" type="text" name="name" required />
</div>
<div>
<label htmlFor="email">Email</label>
<input id="email" type="email" name="email" required />
</div>
<div>
<label htmlFor="message">Message</label>
<textarea id="message" name="message" required />
</div>
<button type="submit" disabled={loading}>
{loading ? 'Sending...' : 'Send Message'}
</button>
</form>
{message && <p>{message}</p>}
</div>
);
}💡 Tip: Store your API key in .env.local as NEXT_PUBLIC_STATICFORMS_KEY
Vue component with reactive form handling:
<template>
<form @submit.prevent="handleSubmit">
<input type="hidden" name="apiKey" :value="apiKey" />
<div>
<label for="name">Name</label>
<input id="name" v-model="form.name" type="text" required />
</div>
<div>
<label for="email">Email</label>
<input id="email" v-model="form.email" type="email" required />
</div>
<div>
<label for="message">Message</label>
<textarea id="message" v-model="form.message" required></textarea>
</div>
<button type="submit" :disabled="loading">
{{ loading ? 'Sending...' : 'Send Message' }}
</button>
<p v-if="status">{{ status }}</p>
</form>
</template>
<script>
export default {
data() {
return {
apiKey: 'YOUR_API_KEY',
form: {
name: '',
email: '',
message: ''
},
loading: false,
status: ''
};
},
methods: {
async handleSubmit() {
this.loading = true;
const formData = new FormData();
formData.append('apiKey', this.apiKey);
formData.append('name', this.form.name);
formData.append('email', this.form.email);
formData.append('message', this.form.message);
try {
const response = await fetch('https://api.staticforms.xyz/submit', {
method: 'POST',
body: formData
});
if (response.ok) {
this.status = 'Message sent successfully!';
this.form = { name: '', email: '', message: '' };
} else {
this.status = 'Failed to send message.';
}
} catch (error) {
this.status = 'An error occurred.';
} finally {
this.loading = false;
}
}
}
};
</script>Simple HTML form without any framework:
<form action="https://api.staticforms.xyz/submit" method="POST">
<input type="hidden" name="apiKey" value="YOUR_API_KEY" />
<input type="hidden" name="redirectTo" value="https://yoursite.com/thanks" />
<label for="name">Name:</label>
<input type="text" id="name" name="name" required />
<label for="email">Email:</label>
<input type="email" id="email" name="email" required />
<label for="message">Message:</label>
<textarea id="message" name="message" required></textarea>
<button type="submit">Send</button>
</form>AJAX Implementation
Submit forms without page reload using vanilla JavaScript:
<form id="contactForm">
<input type="hidden" name="apiKey" value="YOUR_API_KEY" />
<input type="text" name="name" placeholder="Name" required />
<input type="email" name="email" placeholder="Email" required />
<textarea name="message" placeholder="Message" required></textarea>
<button type="submit">Send Message</button>
<div id="status"></div>
</form>
<script>
document.getElementById('contactForm').addEventListener('submit', async (e) => {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
const statusDiv = document.getElementById('status');
try {
const response = await fetch('https://api.staticforms.xyz/submit', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.success) {
statusDiv.textContent = 'Message sent successfully!';
statusDiv.style.color = 'green';
form.reset();
} else {
statusDiv.textContent = 'Failed to send message.';
statusDiv.style.color = 'red';
}
} catch (error) {
statusDiv.textContent = 'An error occurred.';
statusDiv.style.color = 'red';
}
});
</script>More Examples
Check out our blog for detailed guides on integrating with specific frameworks: