Home/File & Media/Uploadthing
File & Media
uploadthing

Uploadthing

File UploadsNext.jsServerlessType-safeS3

Type-safe file uploads for Next.js and full-stack TypeScript apps. Handles S3 under the hood, works in serverless environments, and provides a strongly-typed router with built-in auth callbacks.

License

MIT

Language

TypeScript

Used for
30
Trust
Limited

Why Uploadthing?

Next.js app that needs file uploads without managing S3 yourself

Type-safe upload routes with per-route validation and auth

Serverless or edge deployment where direct S3 multipart is tricky

Signal Breakdown

What drives the Trust Score

Weekly npm downloads
120k/wk
GitHub commits (90d)
185
GitHub stars
8.5k
Stack Overflow questions
1.2k
Community health
Very Active
Weighted Trust Score30 / 100

Download Trend

Last 12 months

Tradeoffs & Caveats

Know before you commit

Need image transformations on upload — use Cloudinary instead

Non-Next.js stack — support outside Next.js/React is limited

Need video processing or CDN streaming — too limited for media pipelines

Pricing

Free tier & paid plans

Free tier

2GB storage · 2GB bandwidth/mo

Paid

From $10/mo (Pro)

Storage and bandwidth-based pricing

Alternative Tools

Other options worth considering

cloudinary
Cloudinary86Strong

Cloud-based image and video management platform with on-the-fly transformations, CDN delivery, and AI-powered media features. Zero-config optimization for web performance.

Often Used Together

Complementary tools that pair well with Uploadthing

nextjs

Next.js

Frontend & UI

98Excellent
View
supabase

Supabase

Database & Cache

95Excellent
View
clerk

Clerk

Auth & Users

80Strong
View
cloudflare-r2

Cloudflare R2

File & Media

74Good
View
cloudinary

Cloudinary

File & Media

86Strong
View

Learning Resources

Docs, videos, tutorials, and courses

Get Started

Repository and installation options

View on GitHub

github.com/pingdotgg/uploadthing

npmnpm install uploadthing @uploadthing/react

Quick Start

Copy and adapt to get going fast

// app/api/uploadthing/core.ts
import { createUploadthing, type FileRouter } from 'uploadthing/next';

const f = createUploadthing();

export const ourFileRouter = {
  profilePicture: f({ image: { maxFileSize: '4MB', maxFileCount: 1 } })
    .middleware(async ({ req }) => {
      const user = await currentUser(); // your auth
      if (!user) throw new Error('Unauthorized');
      return { userId: user.id };
    })
    .onUploadComplete(async ({ metadata, file }) => {
      await db.user.update({ where: { id: metadata.userId }, data: { avatarUrl: file.url } });
    }),
} satisfies FileRouter;

export type OurFileRouter = typeof ourFileRouter;

Code Examples

Common usage patterns

Profile picture upload

Upload and save user avatar with auth check

// components/UploadButton.tsx
'use client';
import { UploadButton } from '@uploadthing/react';
import type { OurFileRouter } from '../api/uploadthing/core';

export function ProfilePictureUpload() {
  return (
    <UploadButton<OurFileRouter>
      endpoint="profilePicture"
      onClientUploadComplete={(res) => {
        console.log('Files:', res);
        alert('Upload complete!');
      }}
      onUploadError={(error: Error) => {
        alert(`Error: ${error.message}`);
      }}
    />
  );
}

Multi-file document upload

Allow uploading multiple PDFs with size validation

// core.ts — add a document uploader
documentUploader: f({
  pdf: { maxFileSize: '16MB', maxFileCount: 5 },
  'application/msword': { maxFileSize: '8MB' },
})
  .middleware(async ({ req }) => {
    const session = await getServerSession(req);
    if (!session?.user) throw new Error('Must be logged in');
    return { userId: session.user.id, orgId: session.user.orgId };
  })
  .onUploadComplete(async ({ metadata, file }) => {
    await db.document.create({
      data: { url: file.url, name: file.name, orgId: metadata.orgId, uploadedBy: metadata.userId },
    });
  }),

Community Notes

Real experiences from developers who've used this tool