Use Cases (Aktualisiert: 3.6.2026)

Claude Code fuer Remix und React Router: loader/action Praxis

Remix-artige React Router Apps mit Claude Code bauen: loader, action, Fehlergrenzen, SEO und Review-Prompts.

Claude Code fuer Remix und React Router: loader/action Praxis

Remix im Jahr 2026 richtig einordnen

Wer 2026 von Remix-Entwicklung spricht, meint oft zwei Dinge: bestehende Remix-v2-Anwendungen warten und neue Apps mit den Remix-Ideen in React Router v7 Framework Mode bauen. Die Remix-Dokumentation verweist fuer aktuelle Framework-Funktionen auf React Router, und die Ankuendigung zu React Router v7 beschreibt, dass viele Remix-Funktionen in React Router angekommen sind. Fuer Claude Code ist diese Unterscheidung entscheidend. Ein ungenauer Prompt wie “baue das in Remix” kann alte@remix-run/*-Imports, neuereact-router-Imports und handgeschriebenes Client-fetch mischen.

Das einfache Modell fuer Einsteiger lautet: Remix/React Router bringt Serverlogik und UI auf Route-Ebene zusammen. Einloader liest Daten vor dem Rendern. Eineaction verarbeitet Formulare und Mutationen. Die Komponente rendert die Seite, und die Route kann Fehlergrenze und SEO enthalten. Dadurch kann Claude Code eine Route komplett pruefen: Lesen, Schreiben, Fehlerfaelle, Ladezustand und Suchsnippet.

Dieser Artikel baut eine kleine, kopierbare React-Router-v7-App mit Produktliste, Produktdetail und Kontaktformular. Die Beispiele zeigen drei Use Cases: Daten mitloader lesen, ein Formular mitaction verarbeiten und Fehler mitErrorBoundary begrenzen. Geprueft wurden die offiziellen Quellen Remix Docs, React Router v7, Route Module docs, Error Boundaries und Form API.

flowchart LR
  A["URL / route"] --> B["loader liest Daten"]
  B --> C["UI component"]
  C --> D["Form sendet"]
  D --> E["action validiert und schreibt"]
  E --> B
  B --> F["ErrorBoundary"]
  E --> F

Den Modus zuerst festlegen

React Router v7 kann Declarative, Data oder Framework Mode sein. Die Remix-nahe Variante ist Framework Mode: Route Modules, Server Rendering,loader, action, Typgenerierung und Deployment-Konventionen gehoeren zusammen. Fuer neue interne Tools ist das meistens der klarste Start.

SituationWahlPrompt fuer Claude Code
Neue Business-AppReact Router v7 Framework ModeNutzecreate-react-router und route modules
Bestehende Remix-v2-AppBestehende Konvention haltenPasse dich an@remix-run/* im Repo an
Bestehende React SPASchrittweise MigrationEine Seite zu loader/action verschieben
Landingpage mit FormularFramework oder SPA ModeSSR und Server-action vorher klaeren

Diese Entscheidung spart Review-Zeit. Claude Code ist schnell, aber ohne klare Leitplanke kombiniert es Muster aus verschiedenen Versionen. In diesem Beispiel gehen wir von React Router v7 Framework Mode aus.

Laufendes Mini-Projekt

Starte klein. Produktliste, Detailseite und Kontaktformular reichen, um Daten, Mutationen, Fehler und SEO zu testen.

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;

Die Daten liegen zuerst in einem Server-Modul. Spaeter kann das Prisma, Drizzle, Supabase oder eine interne API werden.

// 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;
}

Use Case 1: Daten mit loader lesen

Einloader sammelt Daten, bevor die Route gerendert wird. Das ist uebersichtlicher als initiale Daten inuseEffect zu verstecken, weil Ladezustand, Fehler und SEO zusammen auf Route-Ebene geprueft werden.

// 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>
  );
}

Fuer neuen React-19-Code empfehlen die Route-Module-Dokumente die eingebauten<title>- und<meta>-Elemente. Bestehende Projekte mitmeta() koennen diese Konvention behalten. Wichtig ist, doppelte Titel und leere Beschreibungen zu vermeiden.

Use Case 2: Formular mit action verarbeiten

Eineaction nimmt Formulare und Mutationen entgegen. <Form> funktioniert ohne JavaScript als normales HTML-Formular und wird danach von React Router erweitert.

// 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 };
}

In Produktion kommen CSRF, Rate Limit, Spamfilter, E-Mail und CRM dazu. Der Prompt sollte nicht “mach ein Formular” lauten, sondern “validiere serverseitig, zeige Feldfehler, deaktiviere den Button beim Senden und zeige Erfolg”.

Use Case 3: Fehler mit ErrorBoundary begrenzen

Wenn ein Produkt nicht existiert, soll nur die Detailroute einen lokalen 404 zeigen. Die ganze App muss nicht abstuerzen.

// 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>;
}

Bei der Review zaehlt: erwartete Fehler brauchen eine sinnvolle naechste Aktion, unerwartete Fehler duerfen keine Stacks, Secrets, SQL-Meldungen oder internen URLs zeigen.

SEO gehoert in die Route. Die Liste sagt, was verglichen werden kann, die Detailseite beginnt mit dem Produktnamen, die Kontaktseite macht die Anfrage klar. Interne Links zu React-Entwicklung mit Claude Code, API-Entwicklung mit Claude Code und Error-Handling-Patterns fuehren Leser tiefer in die Site.

Review dieses React Router v7 Framework Mode route module.
Pruefe loader, action, ErrorBoundary, Form, title/description und imports.
Liste Befunde nach Schwere, schlage den kleinsten sicheren Diff vor und nenne Pruefkommandos.

Typische Fehler sind: alte und neue Imports mischen, zu viele Daten aus demloader zurueckgeben, nur Browser-Validierung vertrauen, Stacktraces anzeigen, SEO-Metas duplizieren und Revalidation nach eineraction ignorieren. Einzelne koennen mit dem kostenlosen Cheat Sheet starten. Teams mit React Router v7, Remix-v2-Wartung, Formularen und Claude-Code-Reviews sollten Claude Code Training und Beratung nutzen. Wiederverwendbare Prompts und Checklisten liegen in den Produkten.

Masa hat Suche, Produkt-404, Formularvalidierung und Erfolgsmeldung in einem kleinen Projekt getestet. Ein vager Remix-Prompt erzeugte gemischte Imports und Client-fetch. Mit Framework Mode, route modules,loader, action, ErrorBoundary undtitle/meta wurde der Diff kleiner und besser reviewbar. Die praktische Lehre: erst die Verantwortung der Route festlegen, dann Claude Code beschleunigen lassen.

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

Kostenloses PDF: Claude-Code-Cheatsheet

E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.

Wir schützen Ihre Daten und senden keinen Spam.

Masa

Über den Autor

Masa

Engineer für praktische Claude-Code-Workflows und Team-Einführung.