Does NestJS Work With UploadThing?

Fully CompatibleLast verified: 2026-02-20

NestJS and UploadThing work together seamlessly for building type-safe file upload backends in TypeScript.

Quick Facts

Compatibility
full
Setup Difficulty
Easy
Official Integration
No — community maintained
Confidence
high
Minimum Versions
NestJS: 9.0.0
UploadThing: 5.0.0

How NestJS Works With UploadThing

NestJS and UploadThing integrate naturally because both are TypeScript-first frameworks with similar architectural philosophies. UploadThing provides a backend SDK that works as a standard HTTP handler, which NestJS controllers can easily wrap and expose. You create an UploadThing router on your NestJS backend, then use the useUploadThing hook on the frontend—all with end-to-end type safety. NestJS handles routing, middleware, authentication, and error handling, while UploadThing manages file validation, storage, and CDN delivery. The main integration point is in your controller where you expose the UploadThing POST endpoint. Since UploadThing uses standard HTTP, it plays nicely with NestJS's decorator-based routing and guards for authentication. The developer experience is particularly smooth because both frameworks embrace TypeScript fully, eliminating friction around type definitions and validation schemas.

Best Use Cases

SaaS applications with user profile picture uploads and document management
Content management systems where admins upload media assets that need CDN optimization
Real estate platforms with property photo galleries and document verification
E-learning platforms with course material uploads and student assignment submissions

Quick Setup

bash
npm install nestjs uploadthing utapi
typescript
// src/upload/upload.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
import { createUploadthing, type FileRouter } from 'uploadthing/next';

const f = createUploadthing();

const uploadRouter = {
  imageUploader: f({ image: { maxFileSize: '4MB' } })
    .middleware(async () => ({ userId: 'user-123' }))
    .onUploadComplete(async ({ metadata, file }) => {
      console.log('Upload complete for userId:', metadata.userId);
      return { uploadedBy: metadata.userId };
    }),
} satisfies FileRouter;

@Controller('api/uploadthing')
export class UploadController {
  @Post('webhook')
  async handleWebhook(@Body() body: any) {
    // UploadThing webhook handling
    return { success: true };
  }
}

Known Issues & Gotchas

warning

UploadThing's Node SDK doesn't have built-in NestJS middleware; you need to manually wire the webhook handler

Fix: Create a dedicated NestJS controller method for the UploadThing webhook and use @Post('@uploadthing/webhook') with proper signature verification

info

File validation rules must be defined in your UploadThing router config, separate from NestJS pipes, which can lead to validation logic scattered across two places

Fix: Keep all file constraints (size, type) in UploadThing router and use NestJS validation only for metadata; document this separation clearly

info

UploadThing's useUploadThing hook only works in Next.js, React, and Vue, not all frameworks—your NestJS backend won't use it, which is correct but worth clarifying

Fix: Use UploadThing's vanilla JS SDK or HTTP client for non-standard frontend frameworks, or stick to supported frontends

Alternatives

  • AWS S3 with NestJS-specific packages like aws-sdk paired with multer for direct file handling
  • Cloudinary with NestJS controllers using the cloudinary npm package for media management
  • MinIO with NestJS for self-hosted, S3-compatible object storage with fine-grained permissions

Resources

Related Compatibility Guides

Explore more compatibility guides