Getting Started
Next.js (pages/)

Next.js (Legacy) Page Router Setup

No shame in using Page Router still! We still use it for a lot of things at Ping 😊. If your code is still mostly served from the pages/ directory, this is where you want to be

Setting up your environment

Install the packages

npm install uploadthing @uploadthing/react

Add env variables

UPLOADTHING_SECRET=... # A secret key for your app (starts with sk_live_)
⚠️

If you don't already have a uploadthing secret key, sign up (opens in a new tab) and create one from the dashboard! (opens in a new tab)

Set Up A FileRouter

Creating your first FileRoute

All files uploaded to uploadthing are associated with a FileRoute. Think of a FileRoute similar to an endpoint, it has:

  • Permitted types ["image", "video", etc]
  • Max file size
  • (Optional) middleware to authenticate and tag requests
  • onUploadComplete callback for when uploads are completed
server/uploadthing.ts
import type { NextApiRequest, NextApiResponse } from "next";
 
import { createUploadthing, type FileRouter } from "uploadthing/next-legacy";
 
const f = createUploadthing();
 
const auth = (req: NextApiRequest, res: NextApiResponse) => ({ id: "fakeId" }); // Fake auth function
 
// FileRouter for your app, can contain multiple FileRoutes
export const ourFileRouter = {
  // Define as many FileRoutes as you like, each with a unique routeSlug
  imageUploader: f({ image: { maxFileSize: "4MB" } })
    // Set permissions and file types for this FileRoute
    .middleware(async ({ req, res }) => {
      // This code runs on your server before upload
      const user = await auth(req, res);
 
      // If you throw, the user will not be able to upload
      if (!user) throw new Error("Unauthorized");
 
      // Whatever is returned here is accessible in onUploadComplete as `metadata`
      return { userId: user.id };
    })
    .onUploadComplete(async ({ metadata, file }) => {
      // This code RUNS ON YOUR SERVER after upload
      console.log("Upload complete for userId:", metadata.userId);
 
      console.log("file url", file.url);
 
      // !!! Whatever is returned here is sent to the clientside `onClientUploadComplete` callback
      return { uploadedBy: metadata.userId };
    }),
} satisfies FileRouter;
 
export type OurFileRouter = typeof ourFileRouter;

Create a Next.js API route using the FileRouter

File path here doesn't matter, you can serve this from any route. We recommend serving it from /api/uploadthing.

pages/api/uploadthing.ts
import { createNextPageApiHandler } from "uploadthing/next-legacy";
 
import { ourFileRouter } from "~/server/uploadthing";
 
const handler = createNextPageApiHandler({
  router: ourFileRouter,
});
 
export default handler;

Add UploadThing's Styles

Wrap your Tailwind config with the withUt helper. You can learn more about our Tailwind helper in the "Theming" page

tailwind.config.ts
import { withUt } from "uploadthing/tw";
 
export default withUt({
  // Your existing Tailwind config
  content: ["./src/**/*.{ts,tsx,mdx}"],
  ...
});

Create The UploadThing Components (Recommended)

src/utils/uploadthing.ts
import { generateComponents } from "@uploadthing/react";
 
import type { OurFileRouter } from "~/server/uploadthing";
 
export const { UploadButton, UploadDropzone, Uploader } =
  generateComponents<OurFileRouter>();

Mount A Button And Upload!

The @uploadthing/react package includes an "UploadButton" component that you can simply drop into your app, and start uploading files immediately.

app/example-uploader.tsx
import { UploadButton } from "~/utils/uploadthing";
 
export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <UploadButton
        endpoint="imageUploader"
        onClientUploadComplete={(res) => {
          // Do something with the response
          console.log("Files: ", res);
          alert("Upload Completed");
        }}
        onUploadError={(error: Error) => {
          // Do something with the error.
          alert(`ERROR! ${error.message}`);
        }}
      />
    </main>
  );
}

🎉 You're Done!

Want to customize the components? Check out the "Theming" page

Want to make your own components? Check out our useUploadThing hook