<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nikhil Nagar</title>
    <description>The latest articles on DEV Community by Nikhil Nagar (@nikhil_nagar_c3a9f957ffe9).</description>
    <link>https://dev.to/nikhil_nagar_c3a9f957ffe9</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3489733%2F1be92a1a-8e87-4206-8eb0-872128643085.png</url>
      <title>DEV Community: Nikhil Nagar</title>
      <link>https://dev.to/nikhil_nagar_c3a9f957ffe9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nikhil_nagar_c3a9f957ffe9"/>
    <language>en</language>
    <item>
      <title>How to Add a Contact Form to Any Website Without a Backend</title>
      <dc:creator>Nikhil Nagar</dc:creator>
      <pubDate>Thu, 02 Apr 2026 09:52:47 +0000</pubDate>
      <link>https://dev.to/nikhil_nagar_c3a9f957ffe9/how-to-add-a-contact-form-to-any-website-without-a-backend-el</link>
      <guid>https://dev.to/nikhil_nagar_c3a9f957ffe9/how-to-add-a-contact-form-to-any-website-without-a-backend-el</guid>
      <description>&lt;p&gt;title: How to Add a Contact Form to Any Website Without a Backend&lt;br&gt;
published: true&lt;br&gt;
tags: tutorial, html, contact form, static site&lt;/p&gt;
&lt;h2&gt;
  
  
  canonical_url: &lt;a href="https://rowen.in/blog/add-contact-form-without-backend" rel="noopener noreferrer"&gt;https://rowen.in/blog/add-contact-form-without-backend&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Every website needs a contact form, but not every website has a backend. If you are running a static site on GitHub Pages, Netlify, Vercel, or any simple hosting provider, you have probably hit this wall: HTML can collect form data, but it cannot &lt;em&gt;send&lt;/em&gt; it anywhere without a server.&lt;/p&gt;

&lt;p&gt;That is exactly the problem Rowen solves. In this tutorial you will add a working contact form to any website in under five minutes -- with zero backend code.&lt;/p&gt;
&lt;h2&gt;
  
  
  What You Need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A website (HTML, React, Next.js, Astro, Vue -- anything that renders a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A free Rowen account at &lt;a href="https://rowen.in/signup" rel="noopener noreferrer"&gt;rowen.in/signup&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 1 -- Create a Rowen Form Endpoint
&lt;/h2&gt;

&lt;p&gt;Sign up at &lt;strong&gt;rowen.in&lt;/strong&gt; and open your dashboard. Click &lt;strong&gt;"+ New Form"&lt;/strong&gt;. Rowen instantly generates a unique endpoint URL that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://rowen.in/api/f/YOUR_FORM_ID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy that URL. This is the only thing you need from the Rowen side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 -- Write Your HTML Form
&lt;/h2&gt;

&lt;p&gt;Paste the Rowen endpoint URL into the &lt;code&gt;action&lt;/code&gt; attribute of a standard HTML form. Here is a complete, working example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"https://rowen.in/api/f/YOUR_FORM_ID"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Name&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Message&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt; &lt;span class="na"&gt;rows=&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Send Message&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is it. No JavaScript. No fetch calls. No API keys in the markup. When a visitor fills out this form and clicks &lt;strong&gt;Send Message&lt;/strong&gt;, the data goes straight to Rowen, which stores it in your dashboard and emails it to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 -- Add Spam Protection
&lt;/h2&gt;

&lt;p&gt;Rowen includes a built-in honeypot system. Add one hidden field to your form and bots will fill it in automatically, allowing Rowen to silently discard the submission:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"_gotcha"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display:none"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real users never see this field, so their submissions pass through normally. This technique blocks over 99% of automated spam without forcing your visitors to solve annoying CAPTCHAs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 -- Set Up a Custom Redirect (Optional)
&lt;/h2&gt;

&lt;p&gt;By default, Rowen shows a simple "Thank you" page after submission. If you want visitors to land on your own thank-you page instead, add a hidden input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"_redirect"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"https://yoursite.com/thank-you"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rowen will capture the data and then redirect the browser to the URL you specify.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 -- Enable Email Notifications
&lt;/h2&gt;

&lt;p&gt;In your Rowen dashboard, open the form settings. You can configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email notifications&lt;/strong&gt; -- get an instant email every time someone submits the form.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-reply emails&lt;/strong&gt; -- automatically send a confirmation email to the person who submitted the form.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhooks&lt;/strong&gt; -- forward submission data to Slack, Discord, Zapier, or any custom URL in real time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using Rowen with JavaScript (fetch)
&lt;/h2&gt;

&lt;p&gt;If you prefer AJAX submissions (no page reload), Rowen supports that too. Here is a minimal fetch example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://rowen.in/api/f/YOUR_FORM_ID&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Message sent!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rowen automatically handles CORS headers, so cross-origin requests work out of the box from any domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Rowen with React or Next.js
&lt;/h2&gt;

&lt;p&gt;In a React component, the pattern is almost identical:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://rowen.in/api/f/YOUR_FORM_ID&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No backend route, no API middleware, no environment variables to manage. Just point to your Rowen endpoint and submit.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens Behind the Scenes
&lt;/h2&gt;

&lt;p&gt;When a submission arrives, Rowen does the following in under 400 milliseconds:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Validates the payload and checks for spam using server-side pattern recognition.&lt;/li&gt;
&lt;li&gt;Stores the clean data securely in your dashboard.&lt;/li&gt;
&lt;li&gt;Sends you an email notification (if enabled).&lt;/li&gt;
&lt;li&gt;Fires any configured webhooks.&lt;/li&gt;
&lt;li&gt;Redirects the user to your thank-you page or shows a default confirmation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;Adding a contact form to a static website used to mean spinning up a server, configuring SMTP, and writing validation logic. With Rowen, you write one HTML form, paste one URL, and everything else is handled for you -- spam filtering, email delivery, data storage, and integrations.&lt;/p&gt;

&lt;p&gt;Create your free account at &lt;a href="https://rowen.in/signup" rel="noopener noreferrer"&gt;rowen.in/signup&lt;/a&gt; and have your first form running in 30 seconds.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>html</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
