send.webforms.toRead the docs →

Site builders and CMS

Add a contact form to Framer

Framer's built-in forms cover the basics and stop there. A small code component gives you full control - validation, loading state, a custom success message - and posts to an endpoint that handles storage, spam filtering and fan-out. If you would rather not write a component, the HTML embed at the bottom needs no code at all.

Get an endpointRead the docs

Setup

  1. Copy your endpoint

    Create a form in the dashboard.

  2. Add a code component

    In Framer, create a new code file and paste the component below. It appears in your assets panel ready to drop onto the canvas.

  3. Or use an embed

    Prefer no code? Add an Embed element with the HTML snippet instead.

Framer examples

Swap in your own endpoint and these run as-is.

A Framer code component with property controls for the endpoint and button label.

ContactForm.tsx
import { addPropertyControls, ControlType } from "framer";
import { useState } from "react";

export default function ContactForm(props) {
  const { endpoint, buttonLabel } = props;
  const [status, setStatus] = useState("idle");

  async function onSubmit(e) {
    e.preventDefault();
    setStatus("sending");

    const res = await fetch(endpoint, {
      method: "POST",
      headers: { accept: "application/json" },
      body: new FormData(e.currentTarget),
    });

    setStatus(res.ok ? "sent" : "error");
  }

  if (status === "sent") {
    return <p style={{ fontFamily: "Inter, sans-serif" }}>Thanks, we got it.</p>;
  }

  return (
    <form
      onSubmit={onSubmit}
      style={{ display: "grid", gap: 12, fontFamily: "Inter, sans-serif" }}
    >
      <input name="name" placeholder="Your name" required />
      <input name="email" type="email" placeholder="you@example.com" required />
      <textarea name="message" placeholder="Message" rows={4} required />
      <button disabled={status === "sending"}>
        {status === "sending" ? "Sending…" : buttonLabel}
      </button>
    </form>
  );
}

ContactForm.defaultProps = {
  endpoint: "https://send.webforms.to/wft_your_key",
  buttonLabel: "Send",
};

addPropertyControls(ContactForm, {
  endpoint: { type: ControlType.String, title: "Endpoint" },
  buttonLabel: { type: ControlType.String, title: "Button" },
});

The no-code option. Paste into a Framer Embed.

Embed element
<form action="https://send.webforms.to/wft_your_key" method="POST">
  <input type="text" name="name" placeholder="Your name" required />
  <input type="email" name="email" placeholder="you@example.com" required />
  <textarea name="message" placeholder="Message" required></textarea>
  <input type="hidden" name="_next" value="https://example.com/thanks" />
  <button type="submit">Send</button>
</form>

Framer form FAQ

Code components are available on Framer's standard plans, and the embed option works without writing any code at all.

Ready to wire up your Framer form?

Free for 300 submissions a month. Endpoint in under a minute, no card required.

Start free