Svelte Forms
Implementing forms in Svelte is highly intuitive due to Svelte’s reactive bindings. Using bind:value, we can link form variables directly and send submissions via the Fetch API asynchronously.
AI Prompt (Cursor, Claude, v0, ChatGPT)
Section titled “AI Prompt (Cursor, Claude, v0, ChatGPT)”If you are building your Svelte or SvelteKit app with an AI assistant (such as Cursor, Claude, v0, Windsurf, or ChatGPT), copy and paste this prompt to generate a Svelte component:
Create a responsive Svelte contact form component.
Submission Endpoint:https://api.lucidforms.co/f/{your-form-id}
Requirements:- Reactive two-way bindings (bind:value) for Name, Email, and Message fields- Include an invisible honeypot trap field (_honeypot) for spam bot protection- Handle submissions asynchronously with fetch() to the submission endpoint with 'Accept: application/json' and 'Content-Type: application/json'- Provide reactive state handling for loading (disable button), success notification, and error message- Reset form inputs on successful submission- Style with responsive Tailwind CSS classesSvelte Component Example
Section titled “Svelte Component Example”Here is a ready-to-use Svelte component that submits details to Lucid Forms.
<script> let name = ''; let email = ''; let message = ''; let _honeypot = ''; // Spam trap
let status = 'idle'; // 'idle' | 'loading' | 'success' | 'error' let errorMessage = '';
async function handleSubmit(event) { status = 'loading'; errorMessage = '';
// Honeypot bot trap check if (_honeypot) { status = 'success'; return; }
try { const response = await fetch('https://api.lucidforms.co/f/{your-form-id}', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ name, email, message }) });
const data = await response.json();
if (response.ok) { status = 'success'; // Reset form variables name = ''; email = ''; message = ''; } else { status = 'error'; errorMessage = data.error || 'Form submission failed.'; } } catch (err) { status = 'error'; errorMessage = 'A network error occurred. Please try again.'; } }</script>
<div class="form-container"> <h2>Contact Us</h2>
{#if status === 'success'} <div class="alert success"> ✓ Thank you! Your message was received. </div> {/if}
{#if status === 'error'} <div class="alert error"> ✗ {errorMessage} </div> {/if}
<form on:submit|preventDefault={handleSubmit}> <!-- Invisible Honeypot Field --> <input type="text" bind:value={_honeypot} class="hidden" tabindex="-1" autocomplete="off" />
<div class="form-group"> <label for="name">Name</label> <input type="text" id="name" bind:value={name} required /> </div>
<div class="form-group"> <label for="email">Email</label> <input type="email" id="email" bind:value={email} required /> </div>
<div class="form-group"> <label for="message">Message</label> <textarea id="message" bind:value={message} required rows="4"></textarea> </div>
<button type="submit" disabled={status === 'loading'}> {status === 'loading' ? 'Sending...' : 'Send Message'} </button> </form></div>
<style> .form-container { max-width: 400px; margin: 0 auto; font-family: sans-serif; } .form-group { margin-bottom: 12px; } label { display: block; margin-bottom: 4px; font-weight: bold; } input[type="text"], input[type="email"], textarea { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } .hidden { display: none; } button { padding: 10px 15px; background-color: #ff3e00; color: white; border: none; border-radius: 4px; cursor: pointer; } button:disabled { opacity: 0.6; } .alert { padding: 10px; border-radius: 4px; margin-bottom: 15px; } .success { color: #1b5e20; background-color: #e8f5e9; } .error { color: #b71c1c; background-color: #ffebee; }</style>
