UploadKit
Getting Started

Quickstart

Add file uploads to an existing Next.js app in under 5 minutes.

Need an API key? Create a free account at app.uploadkit.dev to get one.

This quickstart adds UploadKit to an existing Next.js project. Most people land here — that's the path we optimize for. If you're starting from a blank slate, see Starting a new project at the bottom.

Install packages

Add @uploadkitdev/next (server-side handler) and @uploadkitdev/react (UI components) to your project:

pnpm add @uploadkitdev/next @uploadkitdev/react
npm install @uploadkitdev/next @uploadkitdev/react
yarn add @uploadkitdev/next @uploadkitdev/react
bun add @uploadkitdev/next @uploadkitdev/react

Create the file router

Create app/api/uploadkit/[...uploadkit]/route.ts (catch-all segment) and define which files your app accepts:

app/api/uploadkit/[...uploadkit]/route.ts
import { createUploadKitHandler } from '@uploadkitdev/next';
import type { FileRouter } from '@uploadkitdev/next';

const router = {
  default: {
    maxFileSize: '4MB',
    allowedTypes: ['image/*'],
    onUploadComplete: async ({ file, metadata }) => {
      // Persist file info to your database
      console.log('Upload complete:', file.url);
    },
  },
} satisfies FileRouter;

export const { GET, POST } = createUploadKitHandler({
  router,
  apiKey: process.env.UPLOADKIT_API_KEY!,
});

Using satisfies FileRouter (not a type annotation) preserves the literal route names — this is what makes the client components fully type-safe.

Set environment variables

Add your API key to .env.local:

.env.local
UPLOADKIT_API_KEY=uk_live_xxxxxxxxxxxxxxxxxxxxx
  • UPLOADKIT_API_KEYserver-side only. It's read by createUploadKitHandler and never exposed to the browser. Never prefix with NEXT_PUBLIC_.

Wrap your root layout

Add UploadKitProvider to app/layout.tsx, pointing it at the route handler you created:

app/layout.tsx
import { UploadKitProvider } from '@uploadkitdev/react';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <UploadKitProvider endpoint="/api/uploadkit">
          {children}
        </UploadKitProvider>
      </body>
    </html>
  );
}

Drop in a dropzone

Drop <UploadDropzone> into any page and point it at your route. The route prop is required and must match a key in your file router:

app/page.tsx
import { UploadDropzone } from '@uploadkitdev/react';

export default function Page() {
  return (
    <main>
      <h1>Upload a file</h1>
      <UploadDropzone
        route="default"
        onUploadComplete={(files) => {
          console.log('Uploaded:', files);
        }}
      />
    </main>
  );
}

That's it. You now have working file uploads with type validation, size limits, and direct-to-storage transfers via presigned URLs — no server bottleneck.


Starting a new project

If you're scaffolding from scratch (not adding to an existing app), skip the setup above and run:

npx create-uploadkit-app my-app

It asks two questions (template + package manager), wires up a working upload page, and you're done. Templates: next · sveltekit · remix · vite. See the CLI guide for the full flag reference.

Using an AI-assistant IDE?

Claude Code, Cursor, Windsurf, Zed

Install the UploadKit MCP server so your assistant has first-class knowledge of every component and can wire the route handler, provider, and .env.local for you. npx -y @uploadkitdev/mcp — no API key required.

Next steps

On this page