Skip to content

Integration guide · Framer

A Framer contact form that emails you — with one small code component

Framer's built-in forms are quick to style and can email you, but how spam is handled and where submissions are stored is Framer's call. When you need a dashboard to review held spam, EU hosting, or the same form backend across every site you build, you want the form to post somewhere you control.

A small Framer code component does that: paste it in once, drop it on any page, and set the endpoint URL in the properties panel. Submissions post from the visitor's browser straight to PostTo, which filters spam, emails you, and logs everything to a searchable dashboard.

Free plan, no credit card required · Updated

Three steps, a few minutes

1

Create an endpoint

Sign up free, create an endpoint in the dashboard, and set your destination email. You'll get an endpoint URL right away.

2

Add the code component

In Framer, create a new code component from the Assets panel, replace its contents with the snippet below, and save. It appears in your assets like any other component.

3

Drop it on a page and publish

Place the component, paste your endpoint URL into its Endpoint URL property, and publish. Submit the form from the live site — the email lands in your inbox and the dashboard.

The code

Paste it as-is — set your endpoint URL in the component's Endpoint URL property, not in the code.

PostToForm.tsx — a Framer code component
import { useState } from "react"
import { addPropertyControls, ControlType } from "framer"

export default function PostToForm(props) {
    const [status, setStatus] = useState("idle")

    async function handleSubmit(event) {
        event.preventDefault()
        const payload = Object.fromEntries(new FormData(event.currentTarget))

        const response = await fetch(props.endpoint, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                Accept: "application/json",
            },
            body: JSON.stringify(payload),
        })

        setStatus(response.ok ? "sent" : "error")
    }

    if (status === "sent") {
        return <p>{props.successMessage}</p>
    }

    return (
        <form onSubmit={handleSubmit} style={{ display: "grid", gap: 12, width: "100%" }}>
            <input type="text" name="name" placeholder="Name" required />
            <input type="email" name="email" placeholder="Email" required />
            <textarea name="message" placeholder="Message" rows={5} required />

            {/* Honeypot: bots fill this in, humans never see it */}
            <input type="text" name="_hp" tabIndex={-1} autoComplete="off" style={{ display: "none" }} />

            <button type="submit">Send</button>
            {status === "error" && <p>Something went wrong. Please try again.</p>}
        </form>
    )
}

addPropertyControls(PostToForm, {
    endpoint: {
        type: ControlType.String,
        title: "Endpoint URL",
        defaultValue: "https://postto.dev/api/v1/send/YOUR_TOKEN",
    },
    successMessage: {
        type: ControlType.String,
        title: "Success message",
        defaultValue: "Thanks — we'll be in touch.",
    },
})

Good to know

One component, every site

The endpoint URL is a property, so the same component works across pages and projects — paste a different endpoint per site, each with its own destination email, without touching the code.

Token only — never signed mode here

The request runs in the visitor's browser, so use the plain endpoint URL with its token. Never enable signed mode for this endpoint — the HMAC secret would have to ship inside your published site, visible to anyone.

Spam protection is already wired in

The hidden _hp field is a honeypot — humans never see it, bots fill it in, and PostTo silently discards those submissions. Server-side baseline filtering (heuristics and optional AI classification) runs on every submission after that, so you don't need a CAPTCHA to start.

Frequently asked questions

Do I need to know React to use this?
No. Paste the component as-is and set the Endpoint URL property — nothing in the code needs editing. Style it by wrapping it in a Framer frame, or adjust the inline styles if you want to go further.
Can I add more fields?
Yes — add another input with a name attribute and it arrives in the email and dashboard automatically. PostTo accepts any fields; name, email, and message are just the ones it uses for the sender, Reply-To, and body.
Does it show a success message without leaving the page?
Yes. The component submits with fetch and swaps the form for the Success message property when PostTo accepts the submission, so the visitor never leaves your Framer page.
What does it cost?
The free plan includes 50 submissions per month with the full dashboard — no credit card required. Paid plans start at $9/month.

Add a form to your Framer site today

Create an endpoint, paste the snippet, and see your first submission in the dashboard — all on the free plan.

Try PostTo free