Claude Code pour Remix et React Router : guide loader/action
Construisez des apps style Remix avec Claude Code: loaders, actions, erreurs, SEO et prompts de revue.
Le bon point de depart en 2026
En 2026, le developpement Remix ne se limite plus a la maintenance d’applications Remix v2. Une grande partie de l’experience Remix se trouve maintenant dans React Router v7 Framework Mode, et la documentation Remix renvoie vers React Router pour les fonctionnalites framework les plus recentes. C’est important pour Claude Code: si le prompt dit seulement “fais-le en Remix”, le resultat peut melanger des imports anciens de@remix-run/*, des imports modernes dereact-router et dufetch cote client.
Le modele mental pour debuter est simple: le style Remix placeloader etaction au niveau de chaque route, afin de rapprocher le serveur et l’interface. Leloader lit les donnees avant le rendu de la page. L’action gere les formulaires et les mutations. Le composant affiche l’interface, et la route peut aussi porter sonErrorBoundary et ses metas SEO. Cette proximite rend la revue beaucoup plus concrete: on peut demander a Claude Code de verifier lecture, ecriture, erreurs, et extrait de recherche pour une seule route.
Dans ce guide, nous construisons une petite application React Router v7 Framework Mode: liste de produits, detail produit, formulaire de contact. Les exemples couvrent trois cas utiles: charger des donnees avecloader, traiter un formulaire avecaction, et contenir les erreurs avecErrorBoundary. Les sources officielles verifiees sont Remix Docs, React Router v7, Route Module docs, Error Boundaries et Form API.
flowchart LR
A["URL / route"] --> B["loader lit les donnees"]
B --> C["UI component"]
C --> D["Form envoie"]
D --> E["action valide et ecrit"]
E --> B
B --> F["ErrorBoundary"]
E --> F
Choisir le mode avant de coder
React Router v7 propose plusieurs usages: Declarative, Data et Framework. L’experience la plus proche de Remix est Framework Mode, avec route modules, rendu serveur,loader, action, generation de types et conventions de deploiement. Pour une nouvelle application metier, c’est souvent le point de depart le plus lisible.
| Situation | Choix | Prompt pour Claude Code |
|---|---|---|
| Nouvelle app interne | React Router v7 Framework Mode | Utilisecreate-react-router et des route modules |
| App Remix v2 existante | Garder la convention actuelle | Respecte les imports@remix-run/* |
| SPA React existante | Migration progressive | Deplace une page vers loader/action |
| Page marketing avec formulaire | Framework ou SPA Mode | Decider SSR et action serveur avant |
Cette decision evite les corrections inutiles. Claude Code est rapide, mais il suit les indices du prompt. Ici, le code cible React Router v7 Framework Mode.
Mini projet executable
Commencez petit: liste, detail et contact. Cela suffit pour tester les donnees, les mutations, les erreurs et le SEO.
npx create-react-router@latest rr-claude-shop
cd rr-claude-shop
npm install
npm run dev
// app/routes.ts
import { type RouteConfig, index, route } from "@react-router/dev/routes";
export default [
index("routes/home.tsx"),
route("products", "routes/products.tsx"),
route("products/:productId", "routes/products.$productId.tsx"),
route("contact", "routes/contact.tsx"),
] satisfies RouteConfig;
Le module de donnees reste cote serveur. Plus tard, il pourra appeler Prisma, Drizzle, Supabase ou une API interne sans changer la logique de route.
// app/data/products.server.ts
export type Product = {
id: string;
name: string;
description: string;
price: number;
};
const products: Product[] = [
{
id: "starter",
name: "Claude Code Starter Kit",
description: "Small prompts and review checklists for the first team rollout.",
price: 9800,
},
{
id: "team",
name: "Team Workflow Pack",
description: "Route reviews, test prompts, and deployment checklists for teams.",
price: 29800,
},
];
const leads: Array<{ id: string; email: string; message: string }> = [];
export async function listProducts(query = "") {
const q = query.trim().toLowerCase();
if (!q) return products;
return products.filter((product) =>
`${product.name} ${product.description}`.toLowerCase().includes(q),
);
}
export async function getProduct(productId: string) {
return products.find((product) => product.id === productId) ?? null;
}
export async function saveLead(input: { email: string; message: string }) {
const lead = { id: crypto.randomUUID(), ...input };
leads.push(lead);
return lead;
}
Cas 1: lire avec loader
Unloader rassemble les donnees avant le rendu. Il evite de cacher le chargement initial dans unuseEffect et permet de revoir en meme temps les donnees, l’etat d’attente, les erreurs et les metas.
// app/routes/products.tsx
import { Form, Link, useLoaderData, useNavigation } from "react-router";
import { listProducts } from "~/data/products.server";
export async function loader({ request }: { request: Request }) {
const url = new URL(request.url);
const q = url.searchParams.get("q") ?? "";
const products = await listProducts(q);
return { q, products };
}
export default function ProductsRoute() {
const { q, products } = useLoaderData<typeof loader>();
const navigation = useNavigation();
const searching = navigation.location?.pathname === "/products";
return (
<main>
<title>Products | Claude Code Shop</title>
<meta
name="description"
content="Browse Claude Code workflow products and team enablement kits."
/>
<h1>Products</h1>
<Form method="get" role="search">
<label>
Search
<input name="q" defaultValue={q} placeholder="workflow" />
</label>
<button type="submit">{searching ? "Searching..." : "Search"}</button>
</Form>
<ul>
{products.map((product) => (
<li key={product.id}>
<Link to={`/products/${product.id}`}>{product.name}</Link>
<p>{product.description}</p>
<strong>{product.price.toLocaleString()} JPY</strong>
</li>
))}
</ul>
</main>
);
}
Pour un nouveau code React 19, les docs de route modules recommandent les elements integres<title> et<meta>. Une application existante peut conservermeta() si c’est deja la convention. L’essentiel est d’eviter les titres dupliques et les descriptions vides.
Cas 2: traiter un formulaire avec action
Uneaction recoit les formulaires et les mutations. <Form> fonctionne comme un formulaire HTML avant JavaScript, puis React Router ajoute les etats de navigation et la revalidation.
// app/routes/contact.tsx
import { Form, useActionData, useNavigation } from "react-router";
import { saveLead } from "~/data/products.server";
type ActionData =
| { ok: true; leadId: string }
| { ok: false; errors: { email?: string; message?: string } };
export async function action({ request }: { request: Request }): Promise<ActionData> {
const formData = await request.formData();
const email = String(formData.get("email") ?? "").trim();
const message = String(formData.get("message") ?? "").trim();
const errors: { email?: string; message?: string } = {};
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
errors.email = "Enter a valid email address.";
}
if (message.length < 20) {
errors.message = "Tell us at least 20 characters about your situation.";
}
if (Object.keys(errors).length > 0) {
return { ok: false, errors };
}
const lead = await saveLead({ email, message });
return { ok: true, leadId: lead.id };
}
En production, ajoutez CSRF, rate limit, anti-spam, email et CRM. Le prompt doit etre precis: “valider cote serveur, afficher les erreurs par champ, desactiver le bouton pendant l’envoi, puis afficher le succes”.
Cas 3: limiter la casse avec ErrorBoundary
Si le produit n’existe pas, la route de detail doit afficher un 404 local. Le reste de l’application ne doit pas tomber.
// app/routes/products.$productId.tsx
import { data, isRouteErrorResponse, Link, useLoaderData } from "react-router";
import { getProduct } from "~/data/products.server";
export async function loader({ params }: { params: { productId?: string } }) {
const productId = params.productId;
if (!productId) {
throw data("Missing product id", { status: 400 });
}
const product = await getProduct(productId);
if (!product) {
throw data("Product not found", { status: 404 });
}
return { product };
}
export function ErrorBoundary({ error }: { error: unknown }) {
if (isRouteErrorResponse(error)) {
return (
<main>
<h1>{error.status === 404 ? "Product not found" : "Could not load product"}</h1>
<p>{error.data}</p>
<Link to="/products">Back to products</Link>
</main>
);
}
return <main><h1>Unexpected error</h1><p>Please try again later.</p></main>;
}
Un bonErrorBoundary donne une suite utile pour les erreurs attendues et cache les details sensibles pour les erreurs inattendues. Ne laissez pas Claude Code publiererror.stack, des variables d’environnement ou des messages SQL bruts dans l’UI.
SEO, liens et conversion
Le SEO doit etre une partie de la route, pas une tache de finition. La liste explique ce que l’on compare, le detail commence par le nom du produit, et la page contact dit quel type d’aide est disponible. Les liens internes vers developpement React avec Claude Code, developpement API avec Claude Code et patterns d’erreurs aident le lecteur a continuer.
Revise ce route module React Router v7 Framework Mode.
Verifie loader, action, ErrorBoundary, Form, title/description et imports.
Classe les problemes par gravite, propose le plus petit diff sur, puis liste les commandes de verification.
Les erreurs frequentes sont: melanger imports anciens et nouveaux, retourner trop de donnees depuisloader, faire confiance a la validation navigateur, exposer la stack dans l’erreur, dupliquer les metas SEO, et oublier que les loaders peuvent etre revalides apres uneaction. Pour s’entrainer, commencez par la fiche gratuite. Pour une equipe qui doit cadrer React Router v7, Remix v2, formulaires et revues Claude Code, allez vers formation et conseil Claude Code. Les prompts reutilisables sont dans les produits.
Masa a teste la recherche produit, le 404 du detail, la validation du formulaire et l’etat de succes dans un petit projet. Un prompt vague a produit des imports melanges et dufetch client. En nommant Framework Mode, route modules,loader, action, ErrorBoundary ettitle/meta, Claude Code a produit un diff plus court et plus facile a relire. La bonne pratique est donc de fixer la responsabilite de la route avant de demander l’implementation.
PDF gratuit: cheatsheet Claude Code
Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.
Nous protégeons vos données et n'envoyons pas de spam.
À propos de l'auteur
Masa
Ingénieur spécialisé dans les workflows pratiques avec Claude Code.
Articles liés
Workflow Obsidian vers CLAUDE.md avec Claude Code
Transformer des notes Obsidian en notes CLAUDE.md concises pour reprendre les sessions sans réexpliquer.
Claude Code Revenue CTA Routing : relier articles, PDF, Gumroad et consultation
Un workflow Claude Code pour orienter les lecteurs vers PDF gratuit, Gumroad ou consultation selon l'intention.
Règles de handoff Claude Code en équipe: preuves, permissions, rollback et revenus
Un format concret pour transmettre un travail Claude Code avec preuves, permissions, rollback, PDF gratuit, Gumroad et consultation.