Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
netlify avatar

Netlify Forms

  • 1.4k installs
  • 31 repo stars
  • Updated August 4, 2026
  • netlify/context-and-tools

netlify-forms is a Claude skill that guides developers through adding contact, feedback, and file-upload forms to static or JavaScript-rendered sites using Netlify Forms without backend code.

About

netlify-forms is a skill from netlify/context-and-tools for HTML form handling on Netlify-hosted sites without server-side code. It covers the data-netlify attribute, spam filtering, AJAX submissions, file uploads, notifications, and the submissions API. Basic setup requires data-netlify="true" and a unique form name with form detection enabled in the Netlify UI Forms section. Developers reach for it when adding contact, feedback, or upload forms to static sites or JS-rendered pages that deploy on Netlify.

  • Zero server-side code required for form handling
  • Works with data-netlify="true" attribute and automatic form-name injection
  • Supports AJAX submissions, file uploads, spam filtering, and custom success pages
  • Requires static HTML skeleton for React, Vue, Next.js, SvelteKit and other JS frameworks
  • Includes submissions API and notification setup instructions

Netlify Forms by the numbers

  • 1,413 all-time installs (skills.sh)
  • +113 installs in the week ending Aug 4, 2026 (Skillselion tracking)
  • Ranked #304 of 2,245 Frontend Development skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/netlify/context-and-tools --skill netlify-forms

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs1.4k
repo stars31
Last updatedAugust 4, 2026
Repositorynetlify/context-and-tools

How do you add forms to a Netlify static site?

Add contact, feedback, and file-upload forms to any static or JavaScript-rendered site without writing backend code.

Who is it for?

Frontend developers deploying static or JS sites on Netlify who need contact, feedback, or file-upload forms without a custom backend.

Skip if: Applications hosted outside Netlify or backends requiring custom server-side form validation logic.

When should I use this skill?

User adds contact forms, feedback forms, file upload forms, or asks about data-netlify, spam filtering, or Netlify submissions API.

What you get

Netlify-ready HTML forms with data-netlify attributes, AJAX handlers, file upload support, and configured submission notifications.

  • data-netlify HTML forms
  • AJAX submission handlers

Files

SKILL.mdMarkdownGitHub ↗

Netlify Forms

Netlify Forms collects HTML form submissions without server-side code. Form detection must be enabled in the Netlify UI (Forms section).

Basic Setup

Add data-netlify="true" and a unique name to the form:

<form name="contact" method="POST" data-netlify="true">
  <label>Name: <input type="text" name="name" /></label>
  <label>Email: <input type="email" name="email" /></label>
  <label>Message: <textarea name="message"></textarea></label>
  <button type="submit">Send</button>
</form>

Netlify's build system detects the form and injects a hidden form-name input automatically. For a custom success page, add action="/thank-you" to the form tag. Use paths without .html extension — Netlify serves thank-you.html at /thank-you by default, and the .html path returns 404.

JavaScript-Rendered Forms (React, Vue, SSR Frameworks)

For forms rendered by JavaScript frameworks (React, Vue, TanStack Start, Next.js, SvelteKit, Remix, Nuxt), Netlify's build parser cannot detect the form in static HTML. You MUST create a static HTML skeleton file for build-time form detection:

Create a static HTML file in public/ (e.g. public/__forms.html) containing a hidden copy of each form:

<!DOCTYPE html>
<html>
  <body>
    <form name="contact" data-netlify="true" netlify-honeypot="bot-field" hidden>
      <input type="hidden" name="form-name" value="contact" />
      <input type="text" name="name" />
      <input type="email" name="email" />
      <textarea name="message"></textarea>
      <input name="bot-field" />
    </form>
  </body>
</html>

Rules:

  • The form name must exactly match the form-name value used in your component's fetch call
  • Include every field your component submits — Netlify validates field names against the registered form
  • Without this file, Netlify cannot detect the form and submissions will silently fail

Your component must also include a hidden form-name input:

<form name="contact" method="POST" data-netlify="true">
  <input type="hidden" name="form-name" value="contact" />
  {/* ... fields ... */}
</form>

AJAX Submissions

Vanilla JavaScript

const form = document.querySelector("form");
form.addEventListener("submit", async (e) => {
  e.preventDefault();
  const formData = new FormData(form);
  await fetch("/", {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams(formData).toString(),
  });
});
SSR frameworks (TanStack Start, Next.js, SvelteKit, Remix, Nuxt): The fetch URL must target the static skeleton
file path (e.g. "/__forms.html"), not "/". In SSR apps, fetch("/") is intercepted by the SSR catch-all
function and never reaches Netlify's form processing middleware. See the React example and troubleshooting section below.

React Example

function ContactForm() {
  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const formData = new FormData(e.currentTarget);
    // For SSR apps, use the skeleton file path instead of "/" (e.g. "/__forms.html")
    const response = await fetch("/__forms.html", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: new URLSearchParams(formData as any).toString(),
    });
    if (response.ok) {
      // Show success feedback
    }
  };

  return (
    <form name="contact" method="POST" data-netlify="true" onSubmit={handleSubmit}>
      <input type="hidden" name="form-name" value="contact" />
      <input type="text" name="name" placeholder="Name" />
      <input type="email" name="email" placeholder="Email" />
      <textarea name="message" placeholder="Message" />
      <button type="submit">Send</button>
    </form>
  );
}
SSR troubleshooting: If form submissions appear to succeed (200 response) but nothing shows in the Netlify Forms
UI, the POST is likely being intercepted by the SSR function. Ensure fetch targets the skeleton file path (e.g.
"/__forms.html"), not "/". The skeleton file path routes through the CDN origin where Netlify's form handler runs.

Spam Filtering

Netlify uses Akismet automatically. Add a honeypot field for extra protection:

<form name="contact" method="POST" netlify-honeypot="bot-field" data-netlify="true">
  <p style="display:none">
    <label>Don't fill this out: <input name="bot-field" /></label>
  </p>
  <!-- visible fields -->
</form>

For reCAPTCHA, add data-netlify-recaptcha="true" to the form and include <div data-netlify-recaptcha="true"></div> where the widget should appear.

File Uploads

<form name="upload" enctype="multipart/form-data" data-netlify="true">
  <input type="text" name="name" />
  <input type="file" name="attachment" />
  <button type="submit">Upload</button>
</form>

For AJAX file uploads, use FormData directly — do not set Content-Type (the browser sets it with the correct boundary):

await fetch("/", { method: "POST", body: new FormData(form) });

Limits: 8 MB max request size, 30-second timeout, one file per input field.

Notifications

Configure in the Netlify UI under Project configuration > Notifications:

  • Email: Auto-sends on submission. Add <input type="hidden" name="subject" value="Contact form" /> for custom subject lines.
  • Slack: Via Netlify App for Slack.
  • Webhooks: Trigger external services on submission.

Submissions API

Access submissions programmatically:

GET /api/v1/forms/{form_id}/submissions
Authorization: Bearer <PERSONAL_ACCESS_TOKEN>

Key endpoints:

ActionMethodPath
List formsGET/api/v1/sites/{site_id}/forms
Get submissionsGET/api/v1/forms/{form_id}/submissions
Get spamGET/api/v1/forms/{form_id}/submissions?state=spam
Delete submissionDELETE/api/v1/submissions/{id}

Related skills

FAQ

What HTML attribute enables Netlify Forms?

Netlify Forms requires data-netlify="true" and a unique name attribute on the form element. The netlify-forms skill notes form detection must also be enabled in the Netlify UI Forms section.

Does netlify-forms require a backend server?

netlify-forms collects HTML form submissions without server-side code on Netlify. The skill covers contact, feedback, and file-upload forms plus AJAX submissions, spam filtering, notifications, and the submissions API.

Frontend Developmentfrontendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.