Use Cases (Actualizado: 3/6/2026)

Claude Code para Remix y React Router: loader, action y SEO

Implementa apps estilo Remix con Claude Code: loader, action, errores, SEO y prompts de revision.

Claude Code para Remix y React Router: loader, action y SEO

La forma correcta de mirar Remix en 2026

En 2026, hablar de desarrollo con Remix no significa solamente mantener una aplicacion Remix v2. Muchas ideas de Remix viven ahora dentro de React Router v7 Framework Mode, y la documentacion oficial de Remix apunta a React Router para las capacidades de framework mas recientes. Por eso, antes de pedirle codigo a Claude Code conviene aclarar si el proyecto es un Remix v2 existente o una aplicacion nueva con React Router v7. Si el prompt solo dice “hazlo en Remix”, es facil recibir una mezcla de imports antiguos de@remix-run/*, imports modernos dereact-router y llamadasfetch hechas a mano en el cliente.

La explicacion para principiantes es esta: el estilo Remix colocaloader yaction por ruta, acercando servidor y UI. Elloader lee datos antes de renderizar la pagina. Elaction recibe formularios y mutaciones. El componente pinta la interfaz, y la misma ruta puede tener su limite de error y su SEO. Esa cercania hace que Claude Code sea mas util, porque puedes pedir una revision de una ruta completa: lectura, escritura, errores, estados de usuario y metadatos.

Esta guia crea una mini app copiable con lista de productos, detalle de producto y formulario de contacto. Incluye tres casos reales: obtener datos conloader, procesar un formulario conaction, y controlar fallos conErrorBoundary. Tambien incluye un prompt de revision, errores comunes, enlaces internos y una llamada a formacion/productos. Para esta actualizacion se revisaron Remix Docs, React Router v7, Route Module docs, Error Boundaries y Form API.

flowchart LR
  A["URL / route"] --> B["loader lee datos"]
  B --> C["UI component"]
  C --> D["Form envia"]
  D --> E["action valida y guarda"]
  E --> B
  B --> F["ErrorBoundary"]
  E --> F

Decide el modo antes de escribir

React Router v7 puede usarse en modo Declarative, Data o Framework. El modo mas parecido a Remix es Framework Mode: route modules, server rendering,loader, action, generacion de tipos y convenciones de despliegue. Para una aplicacion interna nueva suele ser la opcion mas clara.

SituacionOpcionInstruccion para Claude Code
App nueva de negocioReact Router v7 Framework ModeUsacreate-react-router y route modules
Remix v2 existenteMantener imports actualesRespeta el estilo@remix-run/* del repo
React SPA existenteMigrar por pantallaPasa una vista a loader/action
Landing con formularioFramework o SPA ModeDecide si hace falta SSR y action servidor

Sin esta decision, Claude Code puede combinar patrones incompatibles. En este articulo usamos React Router v7 Framework Mode y lo explicamos como desarrollo estilo Remix.

Proyecto minimo ejecutable

Empieza con algo pequeño. Lista, detalle y contacto son suficientes para probar datos, formularios, errores y 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;

Coloca los datos en un modulo solo de servidor. Luego puedes cambiarlo por Prisma, Drizzle, Supabase o una API privada.

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

Caso 1: leer datos con loader

Unloader reune los datos necesarios antes de renderizar la ruta. Evita esconder datos iniciales en unuseEffect y permite revisar carga, error y SEO juntos.

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

Para codigo nuevo con React 19, la documentacion de route modules recomienda usar<title> y<meta> integrados. Si una app antigua ya usameta() export, mantenlo por consistencia. Lo importante es que cada ruta tenga titulo, descripcion e intencion de busqueda propios.

Caso 2: procesar formulario con action

Unaction recibe envios de formulario y mutaciones. <Form> funciona como HTML normal antes de cargar JavaScript y luego React Router lo mejora con estado de envio y revalidacion.

// 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 una app real faltan CSRF, rate limit, filtro de spam, email y CRM. La instruccion a Claude Code debe decirlo. “Haz un formulario” es demasiado amplio; “usa action, valida en servidor, muestra errores por campo, desactiva el boton al enviar y muestra exito” produce mejor codigo.

Caso 3: contener errores por ruta

Si un producto no existe, la ruta de detalle debe mostrar un 404 local, no romper toda la app. Ese es uno de los mayores beneficios del estilo Remix.

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

Revisa que los errores esperados den un siguiente paso claro y que los errores inesperados no muestrenerror.stack, variables de entorno, mensajes de base de datos ni URLs internas.

SEO, enlaces internos y monetizacion

El SEO no deberia ser una decoracion final. En este tipo de app la ruta ya conoce URL, datos y accion del usuario. La lista debe explicar que se puede comparar; el detalle debe empezar por el nombre del producto; contacto debe aclarar que ayuda puede pedir el visitante.

Tambien conviene enlazar temas relacionados: desarrollo React con Claude Code, desarrollo API con Claude Code y patrones de manejo de errores. Estos enlaces ayudan a convertir una visita tecnica en lectura profunda, producto o consulta.

Revisa este route module de React Router v7 Framework Mode.
Comprueba loader, action, ErrorBoundary, Form, title/description e imports.
Ordena problemas por gravedad, propone el diff minimo y termina con comandos de verificacion.

Los errores comunes son seis: mezclar imports viejos y nuevos, devolver datos privados desdeloader, confiar solo en validacion del navegador, mostrar stack en el limite de error, repetir titulos SEO y no entender la revalidacion despues de unaction. Para practicar, empieza por la hoja gratuita. Para equipos que necesitan React Router v7, mantenimiento Remix v2, formularios y revision con Claude Code, la ruta comercial es formacion y consultoria Claude Code. Los prompts y checklists reutilizables estan en productos.

Masa probo lista, 404 de detalle, validacion del formulario y mensaje de exito en un proyecto pequeño. El prompt vago “hazlo en Remix” genero imports mezclados yfetch cliente. Al pedir Framework Mode, route modules,loader, action, ErrorBoundary ytitle/meta, el resultado fue mas corto y facil de revisar. La leccion es clara: fija primero la responsabilidad de la ruta y despues deja que Claude Code acelere la implementacion.

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

PDF gratis: cheatsheet de Claude Code

Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.

Cuidamos tus datos y no enviamos spam.

Masa

Sobre el autor

Masa

Ingeniero enfocado en workflows prácticos con Claude Code.