Formulir kontak di situs statis6 menit baca
Memperbaiki error 405 pada formulir kontak yang di-host di Vercel
Halaman statis di Vercel menjawab POST formulir dengan 405 Method Not Allowed; ini penyebabnya, dan cara mengirim formulir ke backend.
Vercel menyajikan build statis Anda sebagai file, dan POST ke file mendapat 405 dengan body kosong karena tidak ada function yang menangani path itu. Arahkan action formulir ke endpoint Ikiform Anda, atau tulis Vercel Function yang menerima kiriman. Dengan Ikiform, atur ID formulir per environment Vercel agar preview mengirim ke formulir uji dan production mengirim ke formulir sungguhan.
Mengapa Vercel menjawab 405
Vercel mengarahkan setiap request ke file statis atau ke function. Situs statis, build Vite, atau aplikasi Next.js dengan output: "export" hanya punya file. GET untuk /contact mengembalikan file; POST ke path yang sama tidak punya tujuan, jadi Vercel menolaknya sebelum kode Anda sempat berjalan:
curl -i -X POST -d "message=hello" https://your-project.vercel.app/contactHTTP/2 405
server: Vercel
content-disposition: inline
x-vercel-cache: HIT
content-length: 0Respons tidak punya body, jadi browser menampilkan halaman kosong atau layar error-nya sendiri. Tiga setup berujung di sini:
| Kode Anda | Mengapa 405 di Vercel |
|---|---|
<form method="post"> tanpa action | Formulir mengirim ke halaman tempat ia berada, yang berupa file statis |
action="/api/contact" di proyek Vite atau HTML biasa | Tidak ada file di folder api/ di root proyek, jadi tidak ada function untuk path itu |
| Server Action atau Route Handler Next.js dalam static export | output: "export" tidak mendukung Server Actions, atau Route Handlers yang membaca request. next dev melaporkan error-nya, dan build tidak punya server untuk menjalankannya |
- Formulir mengirim ke path di deployment Vercel Anda.
- Vercel mencari function yang menangani path itu.
- Jika Anda menulisnya, function itu berjalan. Di build statis tidak ada, jadi Vercel menjawab 405 dengan body kosong.
- Dengan action mengarah ke Ikiform, kiriman tidak pernah sampai ke Vercel.
- Ikiform menyimpan pesan, mengirimi Anda email, dan me-redirect browser kembali ke halaman statis di situs Vercel Anda.
Jadi Anda menambahkan function atau mengirim kiriman ke tempat lain. Vercel Function di api/contact.ts bisa dipakai, tetapi Anda lalu butuh API email, penyaringan spam, dan rate limit, dan Anda yang memeliharanya. Mengirim ke Ikiform menjaga deployment tetap statis. Perbaikan di HTML cukup satu atribut:
<form method="post">
<input name="email" type="email" required />
<textarea name="message" required></textarea>
<button>Send</button>
</form><form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">Jika Anda lebih suka menulis function sendiri
Function adalah pilihan yang wajar jika pesan harus dikirim ke tempat yang hanya bisa dijangkau kode Anda. Hitung apa saja yang dibutuhkan sebelum mulai:
- Akun penyedia email, domain pengirim yang terverifikasi, dan API key di environment variable Vercel.
- Validasi di server, karena atribut
requireddi browser hanya kemudahan, bukan pemeriksaan. - Penyaringan spam dan rate limit, atau formulir kontak yang mengirimi Anda email dari setiap bot di internet.
- Tempat menyimpan pesan saat penyedia email sedang down, dan cara mengirim ulang.
Form backend menangani daftar itu untuk Anda. Jika Anda tetap ingin kode sendiri ikut terlibat, biarkan formulir mengirim ke Ikiform dan terima webhook bertanda tangan di sebuah function; server Anda sendiri menunjukkan handler-nya.
Satu ID formulir per environment Vercel
Setiap pull request di Vercel mendapat deployment preview. Jika preview mengirim ke formulir production, setiap pesan uji masuk ke inbox Anda di samping pesan asli. Buat formulir Ikiform kedua untuk preview, dan biarkan environment variable Vercel yang memilih. Di Settings โบ Environment Variables, tambahkan nama yang sama dua kali:
VITE_IKIFORM_FORM_ID Production frm_xxxxxxxxxxxxxxxx
VITE_IKIFORM_FORM_ID Preview frm_yyyyyyyyyyyyyyyyVite mengganti placeholder %NAME% di index.html dengan variabel VITE_ saat build, jadi formulir HTML biasa bisa memakainya tanpa JavaScript. VITE_VERCEL_ENV diatur oleh Vercel untuk proyek Vite, dan mencatat dari deployment mana sebuah pesan berasal:
<form id="contact" action="https://ikiform.com/f/%VITE_IKIFORM_FORM_ID%" method="post">
<label for="name">Name</label>
<input id="name" name="name" autocomplete="name" required />
<label for="email">Email</label>
<input id="email" name="email" type="email" autocomplete="email" required />
<label for="message">Message</label>
<textarea id="message" name="message" rows="6" minlength="10" required></textarea>
<input type="hidden" name="build" value="%VITE_VERCEL_ENV%" />
<input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
<button type="submit">Send message</button>
</form>- Vercel membaca environment variable saat build untuk situs statis. Setelah mengubahnya, deploy ulang, atau nilai lama tetap ada di HTML.
- Vite membiarkan placeholder apa adanya jika variabelnya tidak ada, jadi ID yang hilang ikut terkirim sebagai
%VITE_IKIFORM_FORM_ID%dan setiap kiriman gagal dengan400 Bad Requestsebelum mencapai formulir. Pengaman di bawah menangkap hal itu. - ID formulir tetap publik bagaimanapun juga. Hanya variabel
VITE_yang sampai ke browser, itulah sebabnya rahasia tidak boleh disimpan di sana.
const form = document.querySelector("#contact");
if (form && form.action.includes("%VITE_")) {
console.error("VITE_IKIFORM_FORM_ID is not set for this Vercel environment");
form.querySelector("button").disabled = true;
}Memakai Next.js dengan output: "export"? Baca process.env.NEXT_PUBLIC_IKIFORM_FORM_ID di client component; panduan utama punya formulir untuk static export. Jika aplikasi Next.js Anda memang berjalan di server Vercel, Server Action bisa mengirim dengan secret key: lihat panduan Next.js.
Header dan URL bersih
Jika situs Anda mengatur Content-Security-Policy, atur di vercel.json dan sertakan Ikiform. cleanUrls menyajikan thanks.html di /thanks, yang menjadi tujuan redirect yang lebih rapi:
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"cleanUrls": true,
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "Content-Security-Policy",
"value": "default-src 'self'; form-action 'self' https://ikiform.com; connect-src 'self' https://ikiform.com"
}
]
}
]
}Preview dan domain yang diizinkan
URL preview seperti your-project-git-branch-team.vercel.app bukan subdomain dari your-project.vercel.app, jadi tidak cocok di Allowed domains. Kiriman dari sana masuk ke spam dengan origin_mismatch. Itu alasan lain untuk memakai formulir preview terpisah: biarkan domain yang diizinkannya kosong, atau tambahkan host preview yang sedang Anda uji.
localhost, jadi dihitung terhadap paket Anda seperti kiriman live lainnya.Pastikan berfungsi
- Jalankan
curldi atas terhadap URL production Anda sebelum perbaikan, dan pastikan hasilnya405. Setelah perbaikan,actionformulir di HTML yang di-deploy diawalihttps://ikiform.com/f/. - Buka deployment preview, kirim, dan pastikan pesannya masuk ke formulir preview, bukan formulir production.
- Kirim di domain production Anda dan cek field
buildberisiproduction. - Cek inbox setiap penerima notifikasi. Masing-masing mendapat email berisi field, dan Reply terkirim ke pengirim formulir jika formulir punya field
email. - Tidak ada yang masuk? Ubah filter status di dashboard ke Spam. Spam mendapat jawaban sukses yang sama dengan kiriman asli.
Hal yang sering menjebak
| Masalah | Yang harus dilakukan |
|---|---|
Masih 405 setelah mengubah formulir | Deployment yang Anda uji dibangun sebelum perubahan, atau handler JavaScript mengirim ke path Anda sendiri dengan fetch. Cari /api/contact di file hasil build. |
400 Bad Request di setiap kiriman, atau 404 not_found dari Ikiform | ID formulir tidak sampai ke build, atau ID-nya salah untuk environment itu. Cek variabelnya ada untuk environment tersebut lalu deploy ulang. |
| Preview berfungsi, kiriman production masuk ke spam | Domain production Anda tidak ada di Allowed domains formulir production. Tambahkan domain kustom serta your-project.vercel.app. |
| Browser mendarat di halaman terima kasih Ikiform, bukan halaman Anda | _redirect diabaikan kecuali domainnya ada di Allowed domains dan berupa URL https:. Tambahkan domainnya, atau atur Redirect after submit di pengaturan formulir sebagai gantinya. |
Pertanyaan
Formulir mengirim ke path yang hanya punya file statis. Vercel menyajikan file untuk request GET, dan tanpa function untuk path itu, Vercel menolak POST dengan 405. Kirim formulir ke form backend atau tambahkan Vercel Function.
Tidak. Server Actions tidak didukung dengan output: export, karena tidak ada server untuk menjalankannya. Kirim dari client component ke form backend, atau deploy tanpa static export agar Vercel menjalankan action-nya.
Sebaiknya tidak. Beri preview ID formulir sendiri lewat environment variable Preview, agar pesan uji tidak sampai ke inbox atau webhook Anda.
Tidak. Formulir berfungsi tanpanya. Tambahkan vercel.json hanya untuk mengatur Content-Security-Policy yang mengizinkan ikiform.com, atau untuk mengaktifkan cleanUrls agar URL terima kasih lebih rapi.
Tidak, tidak ada paket gratis. Pengujian gratis: Anda bisa mengirim 50 kiriman uji per bulan dari localhost sebelum membayar. Untuk go live, Pro mulai $6/bln untuk 500 kiriman, atau Anda bisa bayar sekali untuk 10.000 kiriman seharga $49 atau 50.000 kiriman seharga $149, dengan kredit yang tidak pernah kedaluwarsa.
Mentok di salah satu langkah, atau ingin panduan untuk situasi Anda? Email hello@ikiform.com.