documentation / get started
Next.js quickstart
Add a typed upload button to a Next.js App Router project. The example accepts up to four images of 4 MB each.
npm install @uploadfile/core @uploadfile/reactpnpm, yarn, and bun work the same way.
UPLOADFILE_TOKEN=paste-the-token-from-the-dashboardSet UPLOADFILE_TOKEN on the server. Tokens from https://staging.uploadfile.dev use staging; tokens from https://www.uploadfile.dev use production. The SDK picks the address from the token. Tokens issued before version 0.2.0 count as production. Staging users need to copy a fresh token from the staging dashboard.
Keep UPLOADFILE_TOKEN on the server. Don't prefix it with NEXT_PUBLIC_, and don't read it in client components.
import { createUploadfile, type FileRouter } from "@uploadfile/core/next";
const f = createUploadfile();
export const fileRouter = {
imageUploader: f({ image: { maxFileSize: "4MB", maxFileCount: 4 } })
.middleware(async () => {
// Look up the signed-in user here and throw to reject the upload.
const user = { id: "demo-user" };
return { userId: user.id };
})
.onUploadComplete(async ({ metadata, file }) => {
console.log("Uploaded by", metadata.userId, file.ufsUrl);
return { url: file.ufsUrl };
}),
} satisfies FileRouter;
export type AppFileRouter = typeof fileRouter;Each key in the router is an endpoint. middleware runs on your server before any bytes move. Throw an error there to reject the upload, and return what you want to receive later as metadata. The value onUploadComplete returns reaches the browser as serverData.
import { createRouteHandler } from "@uploadfile/core/next";
import { fileRouter } from "./core";
export const { GET, POST } = createRouteHandler({ router: fileRouter });The client components call /api/uploadfile by default. If you serve the route somewhere else, pass its path as url to the component or helper.
"use client";
import { generateUploadButton } from "@uploadfile/react";
import type { AppFileRouter } from "./api/uploadfile/core";
const UploadButton = generateUploadButton<AppFileRouter>();
export function ImageUpload() {
return (
<UploadButton
endpoint="imageUploader"
onClientUploadComplete={(files) => {
console.log(files.map((file) => file.ufsUrl));
}}
onUploadError={(error) => {
alert(error.message);
}}
/>
);
}import "@uploadfile/react/styles.css";The stylesheet styles the button and dropzone. Import it once in your root layout. If your project uses Tailwind CSS, use the Tailwind setup in Upload components instead.
Render <ImageUpload /> on any page. The endpoint prop only accepts keys from your router, and files carries the types your onUploadComplete returns.
Run npm run dev, open the page, and upload an image. The browser console prints the file's URL, and your server console prints the log line from onUploadComplete.
In development, where NODE_ENV is development, the SDK polls Uploadfile for completion events and runs onUploadComplete on your machine. You don't need a public URL or a tunnel.
In production, Uploadfile posts completion events to your route over HTTPS on port 443. It uses the URL your server received the upload request on. If your public address differs, for example behind a proxy, set UPLOADFILE_CALLBACK_URL to the full route URL, such as https://example.com/api/uploadfile.