SvelteKit
Eine vorgerenderte SvelteKit-Seite, deren Formular direkt an Ikiform sendet und mit fetch erweitert wird, sobald JavaScript lädt. Funktioniert mit adapter-static.
Diese Seite braucht keinen Server: Die action des Formulars ist dein Ikiform-Endpunkt, daher funktioniert sie mit adapter-static und auf jedem statischen Host. Ohne JavaScript sendet sie und leitet weiter wie einfaches HTML; mit JavaScript sendet sie per fetch und zeigt das Ergebnis direkt an. Um stattdessen über eine Form Action mit einem geheimen Schlüssel zu senden, siehe Svelte.
Warum nicht use:enhance
use:enhance von SvelteKit funktioniert nur mit method="POST"-Formularen, die auf Actions in einer +page.server.js-Datei zeigen. Ikiform ist eine externe URL, daher nutzt die Seite stattdessen einen kleinen onsubmit-Handler. Die Progressive Enhancement ist dieselbe: Das Formular funktioniert zuerst, das Skript verbessert es.
Einrichten
Füge öffentliche Umgebungsvariablen hinzu
.env PUBLIC_IKIFORM_FORM_ID=frm_xxxxxxxxxxxxxxxx PUBLIC_SITE_URL=https://example.comPUBLIC_SITE_URList für die Weiterleitung ohne JavaScript. Beim Prerendering istpage.url.originhttp://sveltekit-prerender, nicht deine Domain, daher lässt sich die Weiterleitung nicht daraus bauen.Prerendere die Seite
src/routes/contact/+page.js export const prerender = true;Füge das Formular hinzu
src/routes/contact/+page.svelte <script> import { PUBLIC_IKIFORM_FORM_ID, PUBLIC_SITE_URL } from "$env/static/public"; const endpoint = `https://ikiform.com/f/${PUBLIC_IKIFORM_FORM_ID}`; let status = $state("idle"); let errors = $state({}); let message = $state(""); async function onsubmit(event) { event.preventDefault(); status = "sending"; try { const response = await fetch(endpoint, { method: "POST", headers: { Accept: "application/json" }, body: new FormData(event.currentTarget), }); const result = await response.json(); if (result.ok) { status = "sent"; return; } errors = result.error.fields ?? {}; message = result.error.message; } catch { message = "Couldn't reach the server. Try again."; } status = "error"; } </script> {#if status === "sent"} <p>Thanks, we got it.</p> {:else} <form action={endpoint} method="POST" {onsubmit}> <label> Email <input name="email" type="email" autocomplete="email" required aria-invalid={errors.email ? "true" : undefined} /> </label> {#if errors.email}<p>{errors.email[0]}</p>{/if} <label> Message <textarea name="message" rows="5"></textarea> </label> <input type="hidden" name="_redirect" value={`${PUBLIC_SITE_URL}/contact/thanks`} /> <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden /> {#if status === "error" && !errors.email}<p role="alert">{message}</p>{/if} <button disabled={status === "sending"}>{status === "sending" ? "Sending" : "Send"}</button> </form> {/if}Füge eine
src/routes/contact/thanks/+page.svelteals Weiterleitungsziel hinzu.
Wenn du die CSP von SvelteKit nutzt
Wenn kit.csp konfiguriert ist, erlaube Ikiform sowohl für den fetch-Post als auch für den einfachen Formular-Post. Sonst blockiert der Browser das eine oder das andere.
const config = {
kit: {
csp: {
directives: {
"connect-src": ["self", "https://ikiform.com"],
"form-action": ["self", "https://ikiform.com"],
},
},
},
};
export default config;Erlaubte Domains
Liste die Produktion plus deine Preview-Hosts auf.
| Wo das Formular läuft | Zu Allowed domains hinzufügen |
|---|---|
vite dev | localhost. Passt auf http://localhost:5173: Ikiform vergleicht nur den Hostnamen, nie den Port. |
| Deine Domain | example.com, was auch www.example.com abdeckt |
| Vercel | your-project.vercel.app. Preview-URLs wie your-project-git-branch-team.vercel.app passen nicht darauf; füge den exakten Preview-Host hinzu, während du eine Preview testest. |
| Cloudflare Pages | your-project.pages.dev. Preview-URLs wie abc123.your-project.pages.dev sind Subdomains davon und passen daher bereits. |
| Netlify | your-site.netlify.app. Deploy Previews (deploy-preview-12--your-site.netlify.app) und Branch Deploys (branch--your-site.netlify.app) sind keine Subdomains davon, füge also den exakten Preview-Host hinzu, während du eine testest. |
- Füge niemals
vercel.app,pages.devodernetlify.appallein hinzu. Jede Site auf diesem Host würde passen, auch die von anderen Leuten.
Test-Checkliste
- Starte den Dev-Server mit
localhostin den erlaubten Domains und sende ab. Die Dankesnachricht sollte das Formular ersetzen. - Starte
vite buildund prüfe, dass die Ausgabecontact.htmlmit dem Formular darin enthält. - Schalte JavaScript aus, lade neu und sende ab. Auf deiner
https:-Domain solltest du auf/contact/thankslanden. - Sende von einem Preview-Deploy ab und prüfe, dass die Einsendung nicht als Spam markiert ist.
Fehlerbehebung
| Was du siehst | Warum | Lösung |
|---|---|---|
Der Build schlägt fehl mit der Meldung, dass PUBLIC_IKIFORM_FORM_ID nicht von $env/static/public exportiert wird | Die Variable ist dort, wo der Build läuft, nicht gesetzt | Füge sie lokal zu .env und zu den Build-Einstellungen deines Hosts hinzu. |
Beim Absenden passiert nichts, und die Konsole zeigt einen CORS-Fehler zum x-sveltekit-action-Header | use:enhance auf einem Formular, das außerhalb deiner App sendet | Entferne es und behalte den onsubmit-Handler. |
Der Browser verweigert das Senden des Formulars wegen form-action oder connect-src | kit.csp listet Ikiform nicht auf | Füge https://ikiform.com zu beiden Direktiven hinzu. |
| Ohne JavaScript landest du auf der Dankesseite von Ikiform | PUBLIC_SITE_URL ist http:, oder die Domain steht nicht in den erlaubten Domains | Verwende deine https:-Adresse und füge die Domain hinzu. |
Einsendungen landen im Spamfilter mit origin_mismatch | Die sendende Seite steht nicht in den erlaubten Domains des Formulars | Füge den Host aus der Tabelle oben hinzu. Mit Reject bekommen dieselben Requests stattdessen 403 origin_not_allowed. |