deepagents-architectur…
Guides architectural decisions for Deep Agents applications. Use when deciding between Deep Agents vs alternatives, choosing backend strategies, designing…
Remix v2 form submissions and mutations. Use when implementing forms, optimistic UI, file uploads, or multi-action routes. Triggers on <Form>, useFetcher, useSubmit, useNavigation for pending state, unstable_parseMultipartFormData, fetcher.formData, intent-based actions, encType
$ npx -y skills add existential-birds/beagle --skill remix-v2-forms --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/remix-v2-formsContext preview
The summary Claude sees to decide when to auto-load this skill.
Remix v2 form submissions and mutations. Use when implementing forms, optimistic UI, file uploads, or multi-action routes. Triggers on <Form>, useFetcher, useSubmit, useNavigation for pending state, unstable_parseMultipartFormData, fetcher.formData, intent-based actions, encType
name: remix-v2-forms description: Remix v2 form submissions and mutations. Use when implementing forms, optimistic UI, file uploads, or multi-action routes. Triggers on <Form>, useFetcher, useSubmit, useNavigation for pending state, unstable_parseMultipartFormData, fetcher.formData, intent-based actions, encType multipart.
Canonical mutation primitives for the `@remix-run/react@^2` route-module framework. A correct Remix v2 mutation is: a `<Form method="post">` (or `<fetcher.Form>`), an `action` that parses `request.formData()` and returns either `redirect(...)` or `json(...)`, and UI that reads `useActionData()` (or `fetcher.data`) for errors plus `useNavigation()` (or `fetcher.state`) for pending state. Anything that bypasses this loop — `fetch()`, raw `<form>`, `e.preventDefault()` + client state — silently sacrifices revalidation, progressive enhancement, and race-safe transitions.
**`<Form>` + action**:
import { json, redirect, type ActionFunctionArgs } from "@remix-run/node";
import { Form, useActionData, useNavigation } from "@remix-run/react";
export async function action({ request }: ActionFunctionArgs) {
const form = await request.formData();
const email = String(form.get("email") ?? "");
if (!email.includes("@")) return json({ errors: { email: "Invalid" } }, { status: 400 });
await createUser({ email });
return redirect("/dashboard");
}
export default function Signup() {
const actionData = useActionData<typeof action>();
const nav = useNavigation();
const busy = nav.state !== "idle" && nav.formAction === "/signup";
return (
<Form method="post" replace>
<input name="email" type="email" />
{actionData?.errors?.email ? <em>{actionData.errors.email}</em> : null}
<button disabled={busy}>{busy ? "Signing up..." : "Sign Up"}</button>
</Form>
);
}| Name | Purpose | |---|---| | `<Form>` from `@remix-run/react` | Navigating, progressively-enhanced form that posts to a route `action` and triggers full-page revalidation | | `<Form navigate={false}>` | Shorthand for "post via fetcher; do not navigate." Equivalent to `<fetcher.Form>` without holding a fetcher ref — useful when you only need pending state, not a programmatic handle | | `useFetcher()` | Non-navigating submission channel for inline mutations, list rows, popovers — same revalidation, no URL change | | `useFetchers()` | **Read-only** array of all in-flight fetcher states across the app. Use for global pending indicators (top-bar loader) without prop drilling. No `Form`/`submit`/`load` methods on the returned items — just `formData`, `state`, etc. | | `useNavigation()` | Observes page-level navigation; the source of truth for `<Form>` pending state | | `useSubmit()` | Programmatic submission (onChange autosave, keyboard shortcuts). Accepts `HTMLFormElement`, `FormData`, plain object (form-encoded), or plain object encoded as JSON via `{ encType: "application/json" }` | | `useActionData<typeof action>()` | Read the most recent action result for the current route |
State transitions:
form submissions; `idle → loading → idle` for GET navigation.
**Asymmetry:** `useNavigation` skips `submitting` for GET navigations; `useFetcher` does NOT — only `fetcher.load()` skips it. `<fetcher.Form method='get'>` and `fetcher.submit(..., {method:'get'})` both transition through `submitting`.
`<Form>` changes the URL, adds history, and revalidates all loaders. `useFetcher` does the same revalidation but stays on the current URL. Each `useFetcher()` call returns an independent submission channel, so two rows submitting at once do not share pending state.
One `action`, switch on `formData.get("intent")`, distinct `<button name="intent" value="...">` per operation. Only the clicked submit button's `name=value` lands in the body. See [references/intent-actions.md](references/intent-actions.md).
`fetcher.formData` and `navigation.formData` are populated synchronously on submit and cleared at `idle`. Read directly each render; never mirror into local React state. See [references/optimistic-ui.md](references/optimistic-ui.md).
Without it, `request.formData()` strips file data and you get the filename string instead of a `File`. Parse with `unstable_parseMultipartFormData` and a bounded upload handler. The `unstable_` prefix is permanent in v2. See [references/uploads.md](references/uploads.md).
Answer **in order**. **Pass** means the condition is true; pick the API on the same line and **stop**.
1. **Does the URL need to change after the mutation** (creating a record and routing to `/records/:id`, deleting and going back to a list, multi-step flow)?
2. **Is this a mutation against a row, cell, toggle, or sub-section while the user stays on the same page** (favorite, like, increment quantity, inline edit)?
3. **Is this loading data outside of normal navigation** (popover content, combobox results, prefetch)?
choice — revalidation and history work out of the box.
Hard rule: never reach for `fetch()` or `axios` for in-app mutations against your own Remix routes. That bypasses the action lifecycle and skips loader revalidation.
Image: NASA, Public Domain. Source Beagle is an Agent Skills marketplace: framework-aware code review, documentation, testing, architectural analysis, and git workflows for any compatible coding agent.
Repo: existential-birds/beagle
Guides architectural decisions for Deep Agents applications. Use when deciding between Deep Agents vs alternatives, choosing backend strategies, designing…
Reviews Deep Agents code for bugs, anti-patterns, and improvements. Use when reviewing code that uses create_deep_agent, backends, subagents, middleware, or…
Implements agents using Deep Agents. Use when building agents with create_deep_agent, configuring backends, defining subagents, adding middleware, or setting…
Guides architectural decisions for LangGraph applications. Use when deciding between LangGraph vs alternatives, choosing state management strategies, designing…
Reviews LangGraph code for bugs, anti-patterns, and improvements. Use when reviewing code that uses StateGraph, nodes, edges, checkpointing, or other LangGraph…
Implements stateful agent graphs using LangGraph. Use when building graphs, adding nodes/edges, defining state schemas, implementing checkpointing, handling…