Claude Code Remix: Full-Stack-Apps mit Nested Routing und KI entwickeln
Remix Run ist eines der wenigen Frameworks, das die Web-Plattform wirklich ernst nimmt. Kein Virtueller DOM als Hauptabstraktion, keine clientseitige State-Maschine als Standardlösung — stattdessen: serverseitiges Rendering, native Formulare, HTTP-Semantik als Programmiermodell. Wer Remix verstanden hat, versteht das Web besser als vorher.
Wer Claude Code Remix-Entwicklung verstanden hat, baut Full-Stack-Anwendungen in einem Bruchteil der Zeit. Nicht weil Claude Code die Architektur übernimmt — sondern weil es die repetitiven Schichten von Loader, Action, Route-Struktur und Form-Handling so zuverlässig generiert, dass du dich auf das Wesentliche konzentrieren kannst: die Fachlogik, die Datenmodelle, die Nutzerführung.
Dieser Artikel zeigt, wie das konkret funktioniert: mit echten Codebeispielen, nachvollziehbaren Prompts und einem klaren Bild davon, wo Claude Code im Remix-Workflow wirklich Zeit spart.
Claude Code Mastery — Remix, Agents, Full-Stack auf Deutsch
Der Kurs deckt nicht nur Remix ab: du lernst, wie du Claude Code für ganze Entwicklungsabläufe einsetzt — von der ersten Route bis zum produktiven Deploy. Einmalig bezahlt, kein Abo.
Zum Kurs — Jetzt starten → Einmalzahlung · Kein Abo · 14 Tage Rückgaberecht1. Warum Remix und Claude Code so gut zusammenpassen
Remix hat eine klare Konvention: jede Route ist eine Datei, jede Datei kann einen loader für das Lesen von Daten und eine action für das Schreiben exportieren. Das klingt simpel — und ist es auch. Aber genau diese Konvention macht Remix ideal für KI-gestützte Entwicklung.
Claude Code kennt das Remix-Muster. Es generiert keine generischen React-Komponenten und hofft, dass du sie in dein Framework einfügst. Es versteht, dass ein loader serverseitig läuft, dass useLoaderData() typsicher sein sollte, dass eine action eine Response oder ein redirect() zurückgibt. Diese Kenntnis macht den Unterschied zwischen brauchbarem Output und Output, den du erst wieder umbauen musst.
Der zweite Grund: Remix ist gut dokumentiert und hat stabile Konventionen. Das sind zwei Eigenschaften, die KI-Codegenerierung systematisch bessermachen. Je klarer das Muster, desto zuverlässiger die Ausgabe. Und Remix-Muster sind sehr klar.
Voraussetzung: Dieser Artikel setzt ein Remix-Projekt voraus, das bereits initialisiert ist. Falls du noch keins hast: npx create-remix@latest im Terminal, dann Claude Code aus dem Projektverzeichnis starten.
2. Nested Routes: Die Architektur verstehen lassen
Nested Routing ist das mächtigste und anfangs am schwierigsten zu verinnerlicende Konzept in Remix. Routen schachteln sich ineinander: ein äußeres Layout bleibt bestehen, während ein innerer Inhalt je nach URL wechselt. Das Ergebnis ist performantes, kontrolliertes Rendering ohne Doppelarbeit.
Das Problem: die Dateistruktur, die Remix dafür erwartet, ist nicht intuitiv, wenn man aus React Router v5 oder Next.js kommt. Genau hier hilft Claude Code am stärksten: nicht beim Schreiben einzelner Komponenten, sondern beim Entwerfen der gesamten Route-Hierarchie.
claude "Ich baue eine Remix-App für ein Projektmanagement-Tool.
Nutzer können Projekte sehen und innerhalb eines Projekts
Aufgaben, Mitglieder und Einstellungen verwalten.
Entwirf die vollständige Nested-Route-Struktur mit
korrekter Dateiorganisation unter app/routes/."
Claude Code antwortet nicht mit einer abstrakten Beschreibung — es gibt dir eine konkrete Dateistruktur:
app/routes/
_layout.tsx # Root-Layout mit Navigation
_layout.projects.tsx # Projekte-Bereich
_layout.projects._index.tsx # /projects - Übersicht
_layout.projects.$projectId.tsx # /projects/:id - Wrapper
_layout.projects.$projectId._index.tsx # Aufgaben-Tab
_layout.projects.$projectId.members.tsx # Mitglieder-Tab
_layout.projects.$projectId.settings.tsx # Einstellungen-Tab
Dazu erklärt es, warum die Struktur so aussieht: welche Route welches <Outlet /> füllt, wo gemeinsame Daten sinnvollerweise geladen werden (auf der $projectId-Ebene, nicht in jedem Tab einzeln), und wie URL-Segmente auf Dateinamen gemappt werden. Das ist Lernmaterial und funktionaler Code in einem.
Shared Loader-Daten auf der richtigen Ebene
Ein häufiger Anfängerfehler in Remix: jeder Tab lädt das Projekt-Objekt neu, obwohl es schon auf der übergeordneten Route verfügbar ist. Claude Code kennt useRouteLoaderData() und baut die Datenarchitektur von Anfang an richtig:
// app/routes/_layout.projects.$projectId.tsx
import { json, type LoaderFunctionArgs } from "@remix-run/node";
import { Outlet, useLoaderData } from "@remix-run/react";
import { getProject } from "~/models/project.server";
export async function loader({ params }: LoaderFunctionArgs) {
const project = await getProject(params.projectId!);
if (!project) throw new Response("Nicht gefunden", { status: 404 });
return json({ project });
}
export default function ProjectLayout() {
const { project } = useLoaderData<typeof loader>();
return (
<div>
<ProjectHeader project={project} />
<ProjectTabNav />
<Outlet /> {/* Tab-Inhalt wird hier eingesetzt */}
</div>
);
}
// app/routes/_layout.projects.$projectId.members.tsx
import { useRouteLoaderData } from "@remix-run/react";
import type { loader as projectLoader } from "./_layout.projects.$projectId";
export default function MembersTab() {
// Kein eigener Loader nötig — Daten kommen von oben
const data = useRouteLoaderData<typeof projectLoader>(
"routes/_layout.projects.$projectId"
);
return <MembersList members={data?.project.members ?? []} />;
}
Das generiert Claude Code, wenn du die Anforderung klar formulierst — und erklärt dabei, warum useRouteLoaderData hier besser ist als ein eigener loader. Das ist der Unterschied zwischen "Code bekommen" und "etwas lernen".
3. Loader und Action: Das Full-Stack-Muster komplett bauen lassen
Der Kern von Remix ist das Loader-Action-Muster: loader liest, action schreibt, das Formular verbindet beides ohne clientseitigen JavaScript-Code. Für jeden CRUD-Anwendungsfall in deiner App musst du dieses Muster implementieren — und es ist immer dasselbe Muster.
Genau hier ist Claude Code am effektivsten. Du beschreibst die Fachlogik, Claude Code generiert das vollständige Muster:
claude "Erstelle eine vollständige Remix-Route für das Erstellen
und Bearbeiten von Aufgaben in einem Projekt.
Die Aufgabe hat: Titel (Pflichtfeld), Beschreibung (optional),
Fälligkeitsdatum (optional), Zugewiesener (aus Projekt-Mitgliedern).
Nutze Prisma für die Datenbankzugriffe und zeige
zod-Validierung in der action."
Das Ergebnis ist eine vollständige Route-Datei mit Loader, Action, Formular und Fehlerbehandlung:
// app/routes/_layout.projects.$projectId.tasks.new.tsx
import {
json,
redirect,
type ActionFunctionArgs,
type LoaderFunctionArgs,
} from "@remix-run/node";
import { Form, useActionData, useLoaderData } from "@remix-run/react";
import { z } from "zod";
import { db } from "~/db.server";
import { requireUserId } from "~/session.server";
const TaskSchema = z.object({
title: z.string().min(1, "Titel ist Pflichtfeld").max(255),
description: z.string().optional(),
dueDate: z.string().optional().transform(v =>
v ? new Date(v) : undefined
),
assigneeId: z.string().optional(),
});
export async function loader({ params }: LoaderFunctionArgs) {
const members = await db.projectMember.findMany({
where: { projectId: params.projectId },
include: { user: { select: { id: true, name: true } } },
});
return json({ members });
}
export async function action({ request, params }: ActionFunctionArgs) {
const userId = await requireUserId(request);
const formData = await request.formData();
const result = TaskSchema.safeParse({
title: formData.get("title"),
description: formData.get("description"),
dueDate: formData.get("dueDate"),
assigneeId: formData.get("assigneeId"),
});
if (!result.success) {
return json(
{ errors: result.error.flatten().fieldErrors },
{ status: 400 }
);
}
await db.task.create({
data: {
...result.data,
projectId: params.projectId!,
createdById: userId,
},
});
return redirect(`/projects/${params.projectId}`);
}
export default function NewTaskPage() {
const { members } = useLoaderData<typeof loader>();
const actionData = useActionData<typeof action>();
return (
<Form method="post">
<div>
<label htmlFor="title">Titel *</label>
<input id="title" name="title" type="text" required />
{actionData?.errors?.title && (
<p className="error">{actionData.errors.title[0]}</p>
)}
</div>
<div>
<label htmlFor="description">Beschreibung</label>
<textarea id="description" name="description" />
</div>
<div>
<label htmlFor="dueDate">Fällig am</label>
<input id="dueDate" name="dueDate" type="date" />
</div>
<div>
<label htmlFor="assigneeId">Zugewiesen an</label>
<select id="assigneeId" name="assigneeId">
<option value="">Niemand</option>
{members.map(m => (
<option key={m.user.id} value={m.user.id}>
{m.user.name}
</option>
))}
</select>
</div>
<button type="submit">Aufgabe erstellen</button>
</Form>
);
}
Das ist kein Pseudo-Code und kein vereinfachtes Beispiel — das ist produktionsreifer Remix-Code mit korrekter Zod-Validierung, Typsicherheit durch typeof loader und typeof action, und einer Fehlerbehandlung, die auf jedem Formularfeld individuell anzeigt, was falsch war.
Prisma-Schema nicht vergessen: Claude Code generiert die Datenbankabfragen, aber nicht automatisch das passende Prisma-Schema. Zeige Claude Code dein bestehendes schema.prisma, damit die generierten Queries wirklich zu deinen Tabellen passen. Einfach den Schema-Inhalt vor dem Prompt in den Kontext geben: claude "Hier ist mein Prisma-Schema: [Inhalt]. Jetzt erstelle..."
4. Progressive Enhancement: Optimistische UI auf Remix-Art
Remix funktioniert ohne JavaScript — das ist kein Zufall, sondern Designentscheidung. Gleichzeitig unterstützt es erstklassiges Progressive Enhancement: mit useFetcher und useNavigation kannst du Ladezustände und optimistische Updates bauen, ohne eine clientseitige State-Maschine zu schreiben.
Das ist das Muster, das die meisten Remix-Tutorials überspringen — und das Claude Code auf Anfrage vollständig implementiert:
claude "Baue eine Aufgaben-Checkbox in Remix die:
1. Ohne JavaScript funktioniert (natives Form-Submit)
2. Mit JavaScript optimistisch aktualisiert wird (kein Warten auf Server)
3. Den Fehlerzustand korrekt behandelt wenn der Request fehlschlägt"
// Optimistische Checkbox mit useFetcher
import { useFetcher } from "@remix-run/react";
export function TaskCheckbox({ task }: { task: Task }) {
const fetcher = useFetcher();
// Optimistischer Zustand: zeige den neuen Wert sofort
const optimisticCompleted =
fetcher.formData
? fetcher.formData.get("completed") === "true"
: task.completed;
return (
<fetcher.Form method="post" action={`/tasks/${task.id}/toggle`}>
<input
type="hidden"
name="completed"
value={String(!optimisticCompleted)}
/>
<button
type="submit"
aria-label={optimisticCompleted ? "Als offen markieren" : "Als erledigt markieren"}
className={optimisticCompleted ? "checked" : "unchecked"}
>
{optimisticCompleted ? "✓" : "○"}
</button>
</fetcher.Form>
);
}
Das fetcher.formData-Muster ist der Schlüssel: solange der Request noch läuft, liefert fetcher.formData die gesendeten Formulardaten — also den "optimistischen" Zustand. Sobald der Request abgeschlossen ist, wechselt die Komponente automatisch zum echten Serverzustand. Claude Code erklärt dieses Muster und baut es korrekt auf.
5. Error Boundaries und 404-Behandlung
Remix hat ein eingebautes System für Fehlerbehandlung, das deutlich leistungsfähiger ist als was die meisten Frameworks anbieten: ErrorBoundary-Exporte in Route-Dateien fangen Fehler und HTTP-Responses ab und zeigen kontextuell korrekte Fehlermeldungen an.
claude "Füge meiner Projekt-Route eine vollständige Fehlerbehandlung hinzu:
- 404 wenn das Projekt nicht existiert
- 403 wenn der Nutzer kein Mitglied des Projekts ist
- Generische 500-Seite für alle anderen Fehler
Nutze Remix ErrorBoundary korrekt."
// In der $projectId.tsx Route
import { isRouteErrorResponse, useRouteError } from "@remix-run/react";
export function ErrorBoundary() {
const error = useRouteError();
if (isRouteErrorResponse(error)) {
if (error.status === 404) {
return (
<div className="error-page">
<h1>Projekt nicht gefunden</h1>
<p>Dieses Projekt existiert nicht oder wurde gelöscht.</p>
<a href="/projects">Zurück zur Übersicht</a>
</div>
);
}
if (error.status === 403) {
return (
<div className="error-page">
<h1>Kein Zugriff</h1>
<p>Du bist kein Mitglied dieses Projekts.</p>
<a href="/projects">Zurück zur Übersicht</a>
</div>
);
}
}
return (
<div className="error-page">
<h1>Etwas ist schiefgelaufen</h1>
<p>Bitte lade die Seite neu oder kontaktiere den Support.</p>
</div>
);
}
// Im Loader: korrekte HTTP-Responses werfen
export async function loader({ params, request }: LoaderFunctionArgs) {
const userId = await requireUserId(request);
const project = await db.project.findUnique({
where: { id: params.projectId },
include: { members: true },
});
if (!project) {
throw new Response("Nicht gefunden", { status: 404 });
}
const isMember = project.members.some(m => m.userId === userId);
if (!isMember) {
throw new Response("Kein Zugriff", { status: 403 });
}
return json({ project });
}
Das Wichtige hier: Claude Code baut nicht nur die ErrorBoundary-Komponente, sondern auch den passenden Loader, der die korrekten HTTP-Responses wirft. Beides gehört zusammen — und Claude Code weiß das.
6. Meta-Funktion: SEO und soziale Previews automatisch generieren
Remix hat eine elegante Lösung für dynamische Meta-Tags: die meta-Funktion in jeder Route hat Zugriff auf die Loader-Daten und kann damit seitenspezifische Titel, Beschreibungen und OG-Tags setzen. Boilerplate-Arbeit, die Claude Code übernimmt:
claude "Füge der $projectId.tsx Route eine meta-Funktion hinzu,
die den Projektnamen in den Titel setzt, eine sinnvolle
og:description generiert und Twitter-Cards konfiguriert."
import type { MetaFunction } from "@remix-run/node";
import type { loader } from "./_layout.projects.$projectId";
export const meta: MetaFunction<typeof loader> = ({ data }) => {
if (!data) {
return [{ title: "Projekt nicht gefunden | MeineTool" }];
}
const { project } = data;
const memberCount = project.members.length;
const taskCount = project.tasks?.length ?? 0;
return [
{ title: `${project.name} | MeineTool` },
{
name: "description",
content: `${project.name}: ${taskCount} Aufgaben, ${memberCount} Mitglieder.`,
},
{ property: "og:title", content: project.name },
{
property: "og:description",
content: project.description ?? `Projektmanagement mit ${memberCount} Mitgliedern`,
},
{ name: "twitter:card", content: "summary" },
{ name: "twitter:title", content: project.name },
];
};
7. Deployment: Von lokal zu produktiv
Remix läuft auf vielen Plattformen: Fly.io, Vercel, Cloudflare Workers, Railway, klassischen Node.js-Servern. Die Wahl der Plattform bestimmt, wie das Deployment-Setup aussieht. Claude Code kennt die Unterschiede und hilft beim Aufsetzen:
claude "Konfiguriere meine Remix-App für das Deployment auf Fly.io
mit einer PostgreSQL-Datenbank. Zeige Dockerfile, fly.toml und
die nötigen Umgebungsvariablen für Prisma in Production."
Oder wenn die App auf Cloudflare Workers laufen soll:
claude "Ich möchte meine Remix-App auf Cloudflare Workers deployen.
Was muss ich am Prisma-Setup ändern? Welche Adapter brauche ich?
Was funktioniert dort nicht und warum?"
Die letzte Frage ist besonders wichtig: Cloudflare Workers haben keinen Node.js-kompatiblen Filesystem-Zugriff, was Prisma in der Standard-Konfiguration ausschließt. Claude Code erklärt das korrekt und zeigt Alternativen (Prisma Data Proxy, Neon serverless driver, D1). Es rät nicht — es beschreibt die konkrete Situation und die konkreten Optionen.
Fly.io Deployment-Konfiguration
# fly.toml (von Claude Code generiert)
app = "mein-remix-projekt"
primary_region = "fra"
[build]
dockerfile = "Dockerfile"
[env]
PORT = "8080"
NODE_ENV = "production"
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0
[[vm]]
memory = "1gb"
cpu_kind = "shared"
cpus = 1
# Dockerfile für Remix (Claude Code Version mit multi-stage build)
FROM node:20-alpine AS base
WORKDIR /app
FROM base AS deps
COPY package*.json ./
RUN npm ci --include=dev
FROM base AS build
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npx prisma generate
RUN npm run build
FROM base AS production
ENV NODE_ENV=production
COPY --from=build /app/build ./build
COPY --from=build /app/public ./public
COPY --from=build /app/package*.json ./
COPY --from=build /app/node_modules/.prisma ./node_modules/.prisma
RUN npm ci --omit=dev
EXPOSE 8080
CMD ["npm", "start"]
Das Multi-Stage-Dockerfile ist ein Detail, das viele vergessen: ohne es landen alle Dev-Dependencies im Production-Image, was es unnötig aufbläht und langsamer macht. Claude Code baut das von Anfang an richtig.
Migrations in Production: Claude Code wird dich darauf hinweisen, dass prisma migrate deploy (nicht migrate dev) der richtige Befehl für Production-Deployments ist. Das ist einer der häufigsten Deployment-Fehler bei Prisma — und Claude Code kennt ihn.
8. Der typische Remix-Arbeitstag mit Claude Code
Ein realistisches Bild, wie ein Arbeitstag aussieht, wenn man Remix mit Claude Code entwickelt:
Morgens: Route-Planung. Du beschreibst das nächste Feature — zum Beispiel ein Kommentar-System für Aufgaben. Claude Code entwirft die Route-Struktur, den Datenbankzugriff und das Formular-Muster. Du bewertest, ob die Architektur stimmt, und gibst grünes Licht.
Vormittags: Implementierung. Loader, Action, Validierung, Fehlerbehandlung — Claude Code generiert die Schichten. Du prüfst, ob die Business-Logik korrekt ist: Darf dieser Nutzer diesen Kommentar sehen? Welche Felder sind Pflichtfelder? Das ist dein Beitrag — nicht das Tippen von Boilerplate.
Nachmittags: Feinschliff und Tests. Edge Cases einbauen, Remix-spezifische Optimierungen (Prefetching, Stale-While-Revalidate), Unit-Tests für die Action-Logik. Claude Code hilft hier ebenfalls — aber du führst das Review durch, weil du weißt, was das System tun soll.
- Boilerplate-Zeit sinkt um circa 60–70 % — Loader, Action, Formulare entstehen in Minuten statt Stunden
- Architekturentscheidungen bleiben beim Entwickler — Claude Code schlägt vor, du entscheidest
- Fehlermuster werden frühzeitig eingebaut — nicht nachträglich als Fix
- Deployment-Konfiguration wird nicht mehr aus Tutorials zusammengesucht, sondern direkt generiert
Der Punkt, an dem die meisten Entwickler den größten Gewinn sehen: die zweite und dritte Route. Die erste Route baut man noch manuell oder mit großem Lernaufwand. Ab der zweiten kennt man das Muster — und Claude Code repliziert es fehlerfrei und schnell auf alle weiteren Routes.
9. Was Claude Code bei Remix nicht übernimmt
Vollständigkeit erfordert, dass auch das gesagt wird: Claude Code ist kein Ersatz für das Verstehen von Remix. Wer nicht weiß, warum ein loader auf dem Server läuft und was das für Session-Management und Authentifizierung bedeutet, wird Sicherheitslücken bauen — auch mit Claude Code-Support.
Claude Code übernimmt die Implementierung von Mustern, die du verstanden hast. Es macht dich schneller beim Bauen — aber nicht richtig, wenn du die Grundlagen nicht kennst. Der Unterschied zwischen einer sicheren und einer unsicheren Remix-App liegt oft in drei Zeilen Code, und diese drei Zeilen muss ein Mensch mit Urteilsvermögen schreiben oder überprüfen.
"Claude Code beschleunigt meine Remix-Entwicklung erheblich — aber es ersetzt nicht das Wissen darüber, was Remix tut und warum. Es ist ein Multiplikator für Kompetenz, kein Ersatz für sie."
Drei Bereiche, bei denen du besonders genau hinschauen solltest:
- Authentifizierung und Session-Management: Claude Code generiert funktionierende Code-Muster, aber ob
requireUserIdwirklich wasserdicht ist, muss du überprüfen - CSRF-Schutz: Remix schützt standardmäßig gegen CSRF bei POST-Requests, aber Custom-Implementierungen können Lücken einführen
- SQL-Injection via Prisma: Prisma parametrisiert standardmäßig, aber
$queryRaw-Aufrufe können gefährlich sein — prüfe jeden$queryRawim generierten Code
Zwei weiterführende Artikel aus dieser Serie:
- Claude Code Debugging — Bugs in Remix-Anwendungen systematisch finden und beheben
- Claude Code für Unternehmen — Team-Workflows, Zugriffskontrolle und Deployment auf Unternehmensebene
Claude Code Mastery — Remix, Agents, Full-Stack auf Deutsch
Dieser Artikel zeigt einen Bruchteil davon, was Claude Code im Remix-Workflow leisten kann. Im Kurs lernst du den vollständigen Workflow: von der ersten Route bis zum produktiven Multi-Agent-System. Vollständig auf Deutsch, einmalig bezahlt.
Jetzt starten → Einmalzahlung · Kein Abo · 14 Tage RückgaberechtKurs · Claude Code Mastery
Von der ersten Remix-Route zum produktiven KI-System
Remix. Agents. MCP. Hooks. Multi-Agent-Workflows. Alles auf Deutsch, einmalig bezahlt — kein Abo, keine Plattformabhängigkeit.
Einmalzahlung · Kein Abo · 14 Tage Rückgaberecht · €29 Basis / €49 Pro