# Remix

MuxForms on Remix adds embed.js via <Scripts> in root.tsx and a contact route with data-form-id. For custom UI, use an action that POSTs JSON to the submit API with process.env.MUXFORMS_INGEST_SECRET.

## Remix

| Approach | Detail |
| --- | --- |
| Embed | root.tsx script + contact route |
| action | Server POST with secret |
| Env | INGEST secret in .env |
| Allowlist | Browser embed origin |

## app/routes/contact.tsx

```
export default function Contact() {
  return (
    <main>
      <h1>Contact</h1>
      <div data-form-id="FORM_UUID" />
    </main>
  );
}
```

## app/root.tsx (script once)

```
export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <script src="https://www.muxforms.com/embed.js" defer />
      </body>
    </html>
  );
}
```

## Optional action submit

```
import type { ActionFunctionArgs } from "@remix-run/node";

export async function action({ request }: ActionFunctionArgs) {
  const form = await request.formData();
  const res = await fetch("https://www.muxforms.com/api/v1/forms/FORM_UUID/submit", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.MUXFORMS_INGEST_SECRET}`,
    },
    body: JSON.stringify({
      email: String(form.get("email")),
      message: String(form.get("message")),
      _hp: "",
    }),
  });
  if (!res.ok) return { ok: false };
  return { ok: true };
}
```

## FAQ

### Vite Remix?

Same root script and route markup.

### Progressive enhancement?

Embed handles client submit; action path for native <form> if you build it.

### Fly.io deploy?

Allow https://your-app.fly.dev on the form.

### React Router 7?

Mirror this pattern in the root layout.

---

HTML version: https://www.muxforms.com/docs/remix
Source: MuxForms (https://www.muxforms.com)
