import { docsMetadata } from "@/lib/utils";
export const metadata = docsMetadata({ title: "TanStack Start Setup", description: "Learn how to set up a TanStack Start project with UploadThing", category: "Getting Started", });
npm install uploadthing @uploadthing/reactUPLOADTHING_TOKEN=... # A token for interacting with the SDKAll files uploaded to uploadthing are associated with a FileRoute. The following is a very minimalistic example, with a single FileRoute "imageUploader". Think of a FileRoute similar to an endpoint, it has:
- Permitted types ["image", "video", etc]
- Max file size
- How many files are allowed to be uploaded
- (Optional)
inputvalidation to validate client-side data sent to the route - (Optional)
middlewareto authenticate and tag requests onUploadCompletecallback for when uploads are completed
To get full insight into what you can do with the FileRoutes, please refer to the File Router API.
import { createUploadthing, UploadThingError } from "uploadthing/server";
import type { FileRouter } from "uploadthing/server";
const f = createUploadthing();
const auth = (req: Request) => ({ id: "fakeId" }); // Fake auth function
// FileRouter for your app, can contain multiple FileRoutes
export const uploadRouter = {
// Define as many FileRoutes as you like, each with a unique routeSlug
imageUploader: f({
image: {
/**
* For full list of options and defaults, see the File Route API reference
* @see https://docs.uploadthing.com/file-routes#route-config
*/
maxFileSize: "4MB",
maxFileCount: 1,
},
})
// Set permissions and file types for this FileRoute
.middleware(async ({ req }) => {
// This code runs on your server before upload
const user = await auth(req);
// If you throw, the user will not be able to upload
if (!user) throw new UploadThingError("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.ufsUrl);
// !!! Whatever is returned here is sent to the clientside `onClientUploadComplete` callback
return { uploadedBy: metadata.userId };
}),
} satisfies FileRouter;
export type UploadRouter = typeof uploadRouter;import { createFileRoute } from "@tanstack/react-router";
import { createRouteHandler } from "uploadthing/server";
import { uploadRouter } from "../../server/uploadthing";
const handler = createRouteHandler({ router: uploadRouter });
export const Route = createFileRoute("/api/uploadthing")({
server: {
handlers: {
GET: async ({ request }) => {
return handler(request);
},
POST: async ({ request }) => {
return handler(request);
},
},
},
});See configuration options in server API reference
We provide components to make uploading easier. We highly recommend re-exporting
them with the types assigned, but you CAN import the components individually
from @uploadthing/react instead.
import {
generateReactHelpers,
generateUploadButton,
generateUploadDropzone,
} from "@uploadthing/react";
import type { UploadRouter } from "../server/uploadthing";
export const UploadButton = generateUploadButton<UploadRouter>();
export const UploadDropzone = generateUploadDropzone<UploadRouter>();
export const { useUploadThing } = generateReactHelpers<UploadRouter>();<Tabs tabs={["Tailwind v3", "Tailwind v4", "Other"]}>
Wrap your Tailwind config with the withUt helper. You can learn more about our
Tailwind helper in the "Theming" page
```tsx
import { withUt } from "uploadthing/tw";
export default withUt({
// Your existing Tailwind config
content: ["./src/**/*.{ts,tsx,mdx}"],
...
});
```
</Tab>
<Tab>
If you're using Tailwind v4 with CSS configuration, you can use our plugin like this:
```css
@import "tailwindcss";
@import "uploadthing/tw/v4";
@source "../node_modules/@uploadthing/react/dist"; /** <-- depends on your project structure */
```
You can learn more about our Tailwind helper in the ["Theming" page](/concepts/theming#theming-with-tailwind-css)
</Tab>
<Tab>
Include our CSS file in the root layout to make sure the components look right!
```tsx {{ title: "src/routes/__root.tsx" }}
import uploadthingCss from "@uploadthing/react/styles.css?url";
export const Route = createRootRoute({
component: RootComponent,
links: () => [{ rel: "stylesheet", href: uploadthingCss }],
});
```
</Tab>
import { createFileRoute } from "@tanstack/react-router";
import { UploadButton } from "../utils/uploadthing";
export const Route = createFileRoute("/")({
component: Home,
});
function Home() {
return <UploadButton endpoint="imageUploader" />;
}Want to customize the components? Check out the "Theming" page
Want to make your own components? Check out our useUploadThing hook