UploadThing

> Type-safe file uploads for Next.js/React — no S3 config, built-in validation, instant CDN.

39 stars

Best use case

UploadThing is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

> Type-safe file uploads for Next.js/React — no S3 config, built-in validation, instant CDN.

Teams using UploadThing should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/uploadthing/SKILL.md --create-dirs "https://raw.githubusercontent.com/InugamiDev/ultrathink-oss/main/.claude/skills/uploadthing/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/uploadthing/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How UploadThing Compares

Feature / AgentUploadThingStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

> Type-safe file uploads for Next.js/React — no S3 config, built-in validation, instant CDN.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# UploadThing

> Type-safe file uploads for Next.js/React — no S3 config, built-in validation, instant CDN.

## When to Use
- Adding file uploads to Next.js or React apps
- Need type-safe upload routes with auth middleware
- Want pre-built or custom upload UI components
- File validation (size, type) without manual wiring

## Core Patterns

### File Router (Server)
```typescript
import { createUploadthing, type FileRouter } from "uploadthing/next";

const f = createUploadthing();

export const uploadRouter = {
  avatar: f({ image: { maxFileSize: "4MB", maxFileCount: 1 } })
    .middleware(async ({ req }) => {
      const user = await auth(req);
      if (!user) throw new UploadThingError("Unauthorized");
      return { userId: user.id }; // Passed to onUploadComplete
    })
    .onUploadComplete(async ({ metadata, file }) => {
      await db.user.update({ where: { id: metadata.userId }, data: { avatar: file.url } });
      return { url: file.url };
    }),

  documents: f({ pdf: { maxFileSize: "16MB" }, image: { maxFileSize: "8MB" } })
    .middleware(async () => ({}))
    .onUploadComplete(({ file }) => ({ url: file.url })),
} satisfies FileRouter;

export type OurFileRouter = typeof uploadRouter;
```

### Route Handler (Next.js App Router)
```typescript
// app/api/uploadthing/route.ts
import { createRouteHandler } from "uploadthing/next";
import { uploadRouter } from "@/server/uploadthing";

export const { GET, POST } = createRouteHandler({ router: uploadRouter });
```

### Client Components
```typescript
import { generateReactHelpers, generateUploadButton, generateUploadDropzone } from "@uploadthing/react";
import type { OurFileRouter } from "@/server/uploadthing";

export const UploadButton = generateUploadButton<OurFileRouter>();
export const UploadDropzone = generateUploadDropzone<OurFileRouter>();
export const { useUploadThing } = generateReactHelpers<OurFileRouter>();

// Pre-built: <UploadButton endpoint="avatar" onClientUploadComplete={(res) => setUrl(res[0].url)} />
// Custom UI with hook:
const { startUpload, isUploading } = useUploadThing("avatar", {
  onClientUploadComplete: (res) => setUrl(res[0].url),
  onUploadError: (err) => toast.error(err.message),
});
// Trigger: await startUpload(files)
```

### Key Features
- **Validators**: `.image()`, `.pdf()`, `.video()`, `.audio()`, `.blob()` with `maxFileSize`/`maxFileCount`
- **Middleware**: Runs server-side before upload; return metadata or throw to reject
- **Callbacks**: `onUploadComplete` receives `{ metadata, file: { url, name, size, key } }`
- **Client hooks**: `useUploadThing` for custom UIs, `useDropzone` for drag-and-drop
- **SSR ready**: `generateComponents`/`generateReactHelpers` for type-safe client utils
- **Delete**: `utapi.deleteFiles(fileKey)` via `uploadthing/server` for server-side file removal
- **CSS**: Import `@uploadthing/react/styles.css` or use `appearance` prop for custom styling

Related Skills

ultrathink

39
from InugamiDev/ultrathink-oss

UltraThink Workflow OS — 4-layer skill mesh with persistent memory and privacy hooks for complex engineering tasks. Routes prompts through intent detection to activate the right domain skills automatically.

ultrathink_review

39
from InugamiDev/ultrathink-oss

Multi-pass code review powered by UltraThink's quality gate — checks correctness, security (OWASP), performance, readability, and project conventions in a single structured pass.

ultrathink_memory

39
from InugamiDev/ultrathink-oss

Persistent memory system for UltraThink — search, save, and recall project context, decisions, and patterns across sessions using Postgres-backed fuzzy search with synonym expansion.

ui-design

39
from InugamiDev/ultrathink-oss

Comprehensive UI design system: 230+ font pairings, 48 themes, 65 design systems, 23 design languages, 30 UX laws, 14 color systems, Swiss grid, Gestalt principles, Pencil.dev workflow. Inherits ui-ux-pro-max (99 UX rules) + impeccable-frontend-design (anti-AI-slop). Triggers on any design, UI, layout, typography, color, theme, or styling task.

Zod

39
from InugamiDev/ultrathink-oss

> TypeScript-first schema validation with static type inference.

webinar-registration-page

39
from InugamiDev/ultrathink-oss

Build a webinar or live event registration page as a self-contained HTML file with countdown timer, speaker bio, agenda, and registration form. Triggers on: "build a webinar registration page", "create a webinar sign-up page", "event registration landing page", "live training registration page", "workshop sign-up page", "create a webinar page", "build an event page", "free webinar landing page", "live demo registration page", "online event page", "create a registration page for my webinar", "build a training event page".

webhooks

39
from InugamiDev/ultrathink-oss

Webhook design patterns — delivery, retry with exponential backoff, HMAC signature verification, payload validation, idempotency keys

web-workers

39
from InugamiDev/ultrathink-oss

Offload heavy computation from the main thread using Web Workers, SharedWorkers, and Comlink — structured messaging, transferable objects, and off-main-thread architecture patterns

web-vitals

39
from InugamiDev/ultrathink-oss

Core Web Vitals monitoring (LCP, FID, CLS, INP, TTFB), measurement with web-vitals library, reporting to analytics, and optimization strategies for Next.js

web-components

39
from InugamiDev/ultrathink-oss

Native Web Components, custom elements API, Shadow DOM, HTML templates, slots, lifecycle callbacks, and framework-agnostic design patterns

wasm

39
from InugamiDev/ultrathink-oss

WebAssembly integration — Rust to WASM with wasm-pack/wasm-bindgen, WASI, browser usage, server-side WASM, and performance considerations

vue

39
from InugamiDev/ultrathink-oss

Vue 3 Composition API, Nuxt patterns, reactivity system, component architecture, and production development practices