Use Cases (Mis à jour: 03/06/2026)

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.

Claude Code pour Remix et React Router : guide loader/action

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.

SituationChoixPrompt pour Claude Code
Nouvelle app interneReact Router v7 Framework ModeUtilisecreate-react-router et des route modules
App Remix v2 existanteGarder la convention actuelleRespecte les imports@remix-run/*
SPA React existanteMigration progressiveDeplace une page vers loader/action
Page marketing avec formulaireFramework ou SPA ModeDecider 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.

#Claude Code #Remix #React #full-stack #frontend
Gratuit

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.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.