SvelteKit
Una página prerenderizada de SvelteKit cuyo formulario envía directamente a Ikiform, mejorada con fetch cuando carga JavaScript. Funciona con adapter-static.
Esta página no necesita servidor: el action del formulario es tu endpoint de Ikiform, así que funciona con adapter-static y en cualquier hosting estático. Sin JavaScript, envía y redirige como HTML normal; con JavaScript, envía con fetch y muestra el resultado en su sitio. Para enviar mediante una form action con una clave secreta, consulta Svelte.
Por qué no usar use:enhance
El use:enhance de SvelteKit solo funciona con formularios method="POST" que apuntan a actions definidas en un archivo +page.server.js. Ikiform es una URL externa, así que la página usa un pequeño handler onsubmit. La mejora progresiva es la misma: primero funciona el formulario y el script lo mejora.
Configúralo
Añade variables de entorno públicas
.env PUBLIC_IKIFORM_FORM_ID=frm_xxxxxxxxxxxxxxxx PUBLIC_SITE_URL=https://example.comPUBLIC_SITE_URLes para la redirección sin JavaScript. Durante el prerenderizado,page.url.origineshttp://sveltekit-prerender, no tu dominio, así que la redirección no se puede construir a partir de él.Prerenderiza la página
src/routes/contact/+page.js export const prerender = true;Añade el formulario
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}Añade un
src/routes/contact/thanks/+page.sveltecomo destino de la redirección.
Si usas la CSP de SvelteKit
Con kit.csp configurado, permite Ikiform tanto para el envío con fetch como para el envío normal del formulario. Si no, el navegador bloquea uno de los dos.
const config = {
kit: {
csp: {
directives: {
"connect-src": ["self", "https://ikiform.com"],
"form-action": ["self", "https://ikiform.com"],
},
},
},
};
export default config;Dominios permitidos
Incluye producción y tus hosts de vista previa.
| Dónde funciona el formulario | Añadir a Allowed domains |
|---|---|
vite dev | localhost. Coincide con http://localhost:5173: Ikiform solo compara el nombre de host, nunca el puerto. |
| Tu dominio | example.com, que también cubre www.example.com |
| Vercel | your-project.vercel.app. Las URL de vista previa como your-project-git-branch-team.vercel.app no coinciden con él; añade el host exacto de la vista previa mientras la pruebas. |
| Cloudflare Pages | your-project.pages.dev. Las URL de vista previa como abc123.your-project.pages.dev son subdominios suyos, así que ya coinciden. |
| Netlify | your-site.netlify.app. Los deploy previews (deploy-preview-12--your-site.netlify.app) y los branch deploys (branch--your-site.netlify.app) no son subdominios suyos, así que añade el host exacto de la vista previa mientras la pruebas. |
- Nunca añadas
vercel.app,pages.devninetlify.appsolos. Coincidiría cualquier sitio de ese host, incluidos los de otras personas.
Lista de pruebas
- Ejecuta el servidor de desarrollo con
localhosten los dominios permitidos y envía. El mensaje de agradecimiento debería sustituir al formulario. - Ejecuta
vite buildy comprueba que el resultado contienecontact.htmlcon el formulario ya dentro. - Desactiva JavaScript, recarga y envía. En tu dominio
https:deberías llegar a/contact/thanks. - Envía desde un despliegue de vista previa y confirma que no se marca como spam.
Solución de problemas
| Qué ves | Por qué | Solución |
|---|---|---|
El build falla diciendo que $env/static/public no exporta PUBLIC_IKIFORM_FORM_ID | La variable no está definida donde se ejecuta el build | Añádela a .env en local y a los ajustes de build de tu hosting. |
Al enviar no pasa nada y la consola muestra un error de CORS sobre la cabecera x-sveltekit-action | use:enhance en un formulario que envía fuera de tu app | Quítalo y quédate con el handler onsubmit. |
El navegador se niega a enviar el formulario por form-action o connect-src | kit.csp no incluye Ikiform | Añade https://ikiform.com a ambas directivas. |
| Sin JavaScript llegas a la página de agradecimiento de Ikiform | PUBLIC_SITE_URL es http:, o el dominio no está en los dominios permitidos | Usa tu dirección https: y añade el dominio. |
Los envíos llegan al filtro de spam con origin_mismatch | La página que envió no está entre los dominios permitidos del formulario | Añade el host de la tabla de arriba. Si eliges Reject, esos mismos envíos reciben 403 origin_not_allowed. |