Connect your GitHub Copilot form.
Simplest
Ask your agent
- 1
Open your project and paste this into the chat: “Use Ellieforms: ellieforms.com/agent”.
- 2
Your agent shows a sign-in link and a short code. Open the link, sign in with Google or your email, and check the code matches.
- 3
Your agent connects the form, builds the thank-you message, and sends a test. Look for the [TEST] email from Ellieforms.
Your agent keeps your design. On the Free plan, a small “Sent with Ellieforms” link appears under your form.
For developers
Set it up yourself
The same connection by hand, in about ten minutes. The result is identical to what an agent builds.
1. Create the form in Ellieforms
- Sign in at app.ellieforms.com with Google or your email.
- Open Forms → Add website. Type the site's web address, so messages from it are trusted straight away.
- Press + Form, name it (“Contact form”), then open Code.
- Copy your form ID (it starts with
frm_) and your badge link. In the code below, replacefrm_YOUR_FORM_IDandYOUR_BADGE_LINKwith them.
2. Add the code to your GitHub Copilot project
GitHub Copilot works in any stack. This is the plain HTML version; for a framework, open its guide below.
- Add the attributes to your existing <form>, or start from this one. Every field needs a name.
- Add the script tag once per page, before </body>. The script after it shows your own success and error messages.
<form data-ellieforms="frm_YOUR_FORM_ID" action="https://in.ellieforms.com/f/frm_YOUR_FORM_ID" method="POST" accept-charset="UTF-8">
<label>Name <input name="name" autocomplete="name" required></label>
<label>Email <input type="email" name="email" autocomplete="email" required></label>
<label>Message <textarea name="message" required></textarea></label>
<!-- Bot trap: keep it hidden and empty -->
<input type="text" name="_fh_hp" tabindex="-1" autocomplete="off" aria-hidden="true" style="position:absolute;left:-9999px">
<button type="submit">Send</button>
</form>
<p class="form-success" role="status" hidden>Thanks! We got your message.</p>
<p class="form-error" role="alert" hidden>Sorry, that didn't send. Please try again.</p>
<p class="form-badge"><a href="YOUR_BADGE_LINK">Sent with Ellieforms</a></p>
<script src="https://in.ellieforms.com/v1/f.js" defer></script>
<script>
// Ellieforms shows nothing to visitors. This code shows the result.
document.addEventListener("ellieforms:sent", (event) => {
event.target.hidden = true;
document.querySelector(".form-success").hidden = false;
});
document.addEventListener("ellieforms:error", () => {
document.querySelector(".form-error").hidden = false;
});
</script>- React
- Next.js
- Vue
- Nuxt
- Svelte
- Astro
- Angular
- React Router
- Preact
- SolidJS
- Alpine.js
- htmx
- Eleventy
- Hugo
- Jekyll
- VitePress
3. Test, then go live
- Publish your site, open the page and send one message through the form.
- It appears in your Ellieforms inbox, and Ellieforms learns the form's fields from it.
- In Forms, press Go live. That locks in the fields, so Ellieforms notices if the form changes later.
Free sends one daily summary of real messages; Pro and Team alert you instantly.
Advanced
Everything the code above relies on, for adapting it to your own setup.
What goes on the form
| Attribute or field | Required | Why |
|---|---|---|
data-ellieforms="frm_YOUR_FORM_ID" | Yes | Tells the script which form this is. |
action="https://in.ellieforms.com/f/frm_YOUR_FORM_ID", method="POST" | Yes | The fallback: if JavaScript fails, the browser still posts the message there. |
accept-charset="UTF-8" | Recommended | Keeps every language intact in the fallback post. |
name on every field | Yes | Fields without a name are not sent. Repeated names (checkboxes) arrive joined with commas. |
Hidden _fh_hp field | Yes | A bot trap. People never see it; bots fill it in. Keep it off-screen exactly as shown. |
data-ellieforms-mode="call" | Only with your own handler | The script stops handling submit, and your code calls ellieforms.send(form). |
The script
Load https://in.ellieforms.com/v1/f.js exactly as shown, once per page, with defer. Don't bundle it, copy it, or add an integrity attribute: fixes reach every site from one place, and v1 never changes in a breaking way. It sets no cookies and makes no third-party requests. On load it solves an invisible bot check for each form, so sending is instant when the visitor clicks.
| You use | What you get |
|---|---|
ellieforms:sent event | Fired on the form after a successful send; it bubbles. event.detail is { ok: true, status, id }. |
ellieforms:error event | Fired when sending failed. detail is { ok: false, status }, with network: true when the visitor is offline. In automatic mode the script then falls back to the plain post, so the message still arrives. |
await window.ellieforms.send(form) | Call mode. Sends the HTMLFormElement you pass (never a component or data object), retries twice, fires the same events and returns true or false. |
Forms added later (client-side navigation, htmx swaps, modals) work without extra code: the script listens on the whole page.
Show a sending state
In automatic mode the script takes over the submit. To disable the button while sending, switch to call mode and send from your own handler:
<form id="contact" data-ellieforms="frm_YOUR_FORM_ID" data-ellieforms-mode="call"
action="https://in.ellieforms.com/f/frm_YOUR_FORM_ID" method="POST" accept-charset="UTF-8">
<!-- the same fields, trap and button as above -->
</form>
<script>
const form = document.getElementById("contact");
form.addEventListener("submit", async (event) => {
event.preventDefault();
if (!window.ellieforms) return form.submit(); // script blocked: the plain post still delivers
const button = form.querySelector("button");
button.disabled = true;
document.querySelector(".form-error").hidden = true;
const ok = await window.ellieforms.send(form);
button.disabled = false;
form.hidden = ok;
document.querySelector(ok ? ".form-success" : ".form-error").hidden = false;
});
</script>Limits and changes
- Up to 100 fields, 10,000 characters per field and 32 KB per message. File uploads are not sent.
- The visitor's email address (usually a field named
email) becomes the Reply-To of your alert, so you can answer straight from your inbox. - Changed the form's fields after going live? Messages still arrive, with a note asking you to confirm the new version. To relearn on purpose: Forms → Relearn fields, send one message, then Go live.
- Visitors without JavaScript return to your home page after sending, or to your own thank-you page: Forms → Settings.
- Want Cloudflare Turnstile as well? Add your own keys under Forms → Advanced and put the Turnstile widget inside the form; the script sends its answer along.
Webhooks and the API
Send messages to Zapier, Make, n8n or your own server, or script the setup: see the developer docs.