UploadThing mit Claude Code: File Uploads fuer Next.js 2026

UploadThing macht File Uploads in Next.js trivial — kein S3-Setup, keine Presigned URLs manuell, kein CORS-Gefummel. Claude Code generiert vollstaendige Upload-Infrastruktur mit Validation, Auth und Callbacks.

File Router: Server-seitige Upload-Konfiguration

RouterUpload-Endpoints mit Validation

# Prompt: "Erstelle UploadThing-Setup fuer Avatar und Dokument-Uploads" npm install uploadthing @uploadthing/react // server/uploadthing.ts — File Router import { createUploadthing, type FileRouter } from "uploadthing/next"; import { auth } from "@/lib/auth"; const f = createUploadthing(); export const ourFileRouter = { // Avatar: nur Bilder, max 4MB avatarUploader: f({ image: { maxFileSize: "4MB", maxFileCount: 1 } }) .middleware(async ({ req }) => { const session = await auth(); if (!session) throw new Error("Unauthorized"); return { userId: session.user.id }; // In onUploadComplete verfuegbar }) .onUploadComplete(async ({ metadata, file }) => { await db.user.update({ where: { id: metadata.userId }, data: { avatarUrl: file.url }, }); return { uploadedBy: metadata.userId }; }), // Dokument-Upload: PDF und Office, max 32MB documentUploader: f({ pdf: { maxFileSize: "32MB" }, "application/msword": { maxFileSize: "32MB" }, "application/vnd.openxmlformats-officedocument.wordprocessingml.document": { maxFileSize: "32MB" }, }) .middleware(async ({ req }) => { const session = await auth(); if (!session) throw new Error("Unauthorized"); return { userId: session.user.id }; }) .onUploadComplete(async ({ metadata, file }) => { await db.document.create({ data: { name: file.name, url: file.url, userId: metadata.userId }, }); }), } satisfies FileRouter; export type OurFileRouter = typeof ourFileRouter; // app/api/uploadthing/route.ts import { createRouteHandler } from "uploadthing/next"; export const { GET, POST } = createRouteHandler({ router: ourFileRouter });

Client-seitige Upload-Komponenten

ClientUploadButton und UploadDropzone

// utils/uploadthing.ts — typisierte Client-Hilfsfunktionen import { generateUploadButton, generateUploadDropzone } from "@uploadthing/react"; import type { OurFileRouter } from "@/server/uploadthing"; export const UploadButton = generateUploadButton<OurFileRouter>(); export const UploadDropzone = generateUploadDropzone<OurFileRouter>(); // AvatarUpload.tsx function AvatarUpload({ onUpload }: { onUpload: (url: string) => void }) { return ( <UploadButton endpoint="avatarUploader" onClientUploadComplete={(res) => { const url = res[0]?.url; if (url) onUpload(url); toast.success("Bild hochgeladen!"); }} onUploadError={(err) => toast.error(`Upload fehlgeschlagen: ${err.message}`)} appearance={{ button: "bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded", allowedContent: "text-gray-500 text-sm", }} /> ); } // Dropzone fuer Dokumente: <UploadDropzone endpoint="documentUploader" onClientUploadComplete={(res) => { setDocuments(prev => [...prev, ...res.map(f => ({ name: f.name, url: f.url }))]); }} onUploadProgress={(p) => setProgress(p)} // 0-100 className="border-2 border-dashed border-gray-300 rounded-lg p-8" />
Styling-Tipp: UploadButton/Dropzone akzeptieren appearance Prop fuer CSS-Klassen oder Style-Objekte. Claude Code passt das Styling automatisch an Tailwind-Klassen an.

useUploadThing Hook fuer Custom UI

HookVolle Kontrolle mit useUploadThing

# Prompt: "Custom Drag-and-Drop UI mit Fortschrittsbalken" import { useUploadThing } from "@uploadthing/react"; function CustomUploader() { const [files, setFiles] = useState<File[]>([]); const [progress, setProgress] = useState(0); const { startUpload, isUploading } = useUploadThing("documentUploader", { onClientUploadComplete: (res) => { console.log("Uploaded:", res); setFiles([]); setProgress(0); }, onUploadProgress: setProgress, onUploadError: (err) => console.error(err), }); return ( <div onDrop={(e) => { e.preventDefault(); setFiles(Array.from(e.dataTransfer.files)); }} onDragOver={(e) => e.preventDefault()} > {files.length > 0 && ( <div> {files.map(f => <div key={f.name}>{f.name}</div>)} <button onClick={() => startUpload(files)} disabled={isUploading}> {isUploading ? `${progress}%` : "Hochladen"} </button> </div> )} </div> ); }

File-Handling im Kurs

Im Claude Code Mastery Kurs: vollstaendiges File-Upload-Modul mit UploadThing, S3/R2 direkt und Image-Processing — inkl. Virus-Scanning, CDN-Integration und Multi-File-Workflows.

14 Tage kostenlos testen →