Image Upload Guide
Add image uploads to your app — file route config, dropzone component, client-side preview, and saving the URL.
This guide shows how to accept image uploads (JPEG, PNG, WebP, GIF) with a 4 MB limit — a common configuration for profile photos, product images, and content attachments.
1. Configure the file route
Define which file types and sizes your route accepts. In Next.js, this goes in your UploadKit route handler:
import { createUploadKitHandler } from '@uploadkitdev/next';
import type { FileRouter } from '@uploadkitdev/next';
const router = {
imageUploader: {
maxFileSize: '4MB',
maxFileCount: 10,
allowedTypes: ['image/jpeg', 'image/png', 'image/webp', 'image/gif'],
middleware: async ({ req }) => {
// Attach auth context — returned value becomes `metadata`
const session = await getSession(req);
return { userId: session.user.id };
},
onUploadComplete: async ({ file, metadata }) => {
// Save the URL to your database
await db.images.create({
url: file.url,
userId: metadata.userId,
});
},
},
} satisfies FileRouter;
export const { GET, POST } = createUploadKitHandler({ router });// No file router needed — validation happens in the UploadKit API
// Set UPLOADKIT_API_KEY in your server environment and expose /api/uploadkitWhen using the React SDK directly with an endpoint, file type and size limits are configured in your project's file routes in the dashboard.
2. Add the dropzone component
'use client';
import { UploadDropzone } from '@uploadkitdev/react';
export default function UploadPage() {
return (
<UploadDropzone
route="imageUploader"
onUploadComplete={(files) => {
console.log('Uploaded:', files[0].url);
}}
onUploadError={(error) => {
console.error('Upload failed:', error.message);
}}
/>
);
}'use client';
import { UploadDropzone } from '@uploadkitdev/react';
export default function UploadPage() {
return (
<UploadDropzone
route="imageUploader"
onUploadComplete={(files) => {
console.log('Uploaded:', files[0].url);
}}
onUploadError={(error) => {
console.error('Upload failed:', error.message);
}}
/>
);
}Ensure UploadKitProvider endpoint="/api/uploadkit" wraps this component. The endpoint is your own backend server, which holds UPLOADKIT_API_KEY server-side.
3. Show a client-side preview
Use the FilePreview component to display thumbnails before and after upload:
'use client';
import { useState } from 'react';
import { UploadDropzone, FilePreview } from '@uploadkitdev/react';
export default function UploadPage() {
const [imageUrl, setImageUrl] = useState<string | null>(null);
return (
<div>
<UploadDropzone
route="imageUploader"
onUploadComplete={(files) => {
setImageUrl(files[0].url);
}}
/>
{imageUrl && (
<div className="mt-4">
<p className="text-sm text-muted-foreground">Uploaded image:</p>
<img src={imageUrl} alt="Uploaded" className="mt-2 rounded-lg max-w-sm" />
</div>
)}
</div>
);
}For in-progress thumbnail previews (before the upload completes), use the FilePreview component from @uploadkitdev/react — it generates thumbnails client-side via canvas.
4. Handle the upload result
The onUploadComplete callback receives an array of uploaded files:
onUploadComplete={(files) => {
const file = files[0];
// file.url — CDN URL (permanent, use this in your database)
// file.key — Storage key (for deletion via API)
// file.name — Original file name
// file.size — File size in bytes
// file.type — MIME type
// Save to your database
await updateUserAvatar(userId, file.url);
}}Save file.url to your database — this is the permanent CDN URL. The file.key is useful if you need to delete the file later via the Files API.