Astro Setup

You can use Astro with any of the frontend frameworks we support. This guide will walk you through setting it up using React, but the steps will be near identical for other frameworks too.

Setting up your environment

Install the packages

npm install uploadthing @uploadthing/react

Add env variables

UPLOADTHING_TOKEN=... # A token for interacting with the SDK

Set Up A FileRouter

Creating your first FileRoute

All 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
  • (Optional) middleware to authenticate and tag requests
  • onUploadComplete callback for when uploads are completed

To get full insight into what you can do with the FileRoutes, please refer to the File Router API.

src/server/uploadthing.ts

import { createUploadthing, 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 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 }) => {
      // 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 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 Astro API route using the FileRouter

src/pages/api/uploadthing.ts

import { createRouteHandler } from "uploadthing/server";

import { ourFileRouter } from "~/server/uploadthing";

// Export routes for Next App Router
const handlers = createRouteHandler({
  router: ourFileRouter,
  config: {
    token: import.meta.env.UPLOADTHING_TOKEN,
  },
});
export { handlers as GET, handlers as POST };

See configuration options in server API reference

Create The UploadThing Components

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.

src/utils/uploadthing.ts

import {
  generateUploadButton,
  generateUploadDropzone,
} from "@uploadthing/react";

import type { OurFileRouter } from "~/server/uploadthing";

export const UploadButton = generateUploadButton<OurFileRouter>();
export const UploadDropzone = generateUploadDropzone<OurFileRouter>();

Add UploadThing's Styles

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

import { withUt } from "uploadthing/tw";

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

Mount A Button And Upload!

src/components/image-uploader.tsx

import { UploadButton } from "~/utils/uploadthing";

export function ImageUploader() {
  return (
    <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}`);
      }}
    />
  );
}

src/pages/index.astro

---
import Layout from "~/layouts/root.astro"
import { ImageUploader } from "~/components/image-uploader";
---
<Layout>
    <ImageUploader client:load />
</Layout>
💡 Optional

Improving SSR

Without SSR Plugin
With SSR Plugin
Allowed content

UploadThing needs to get info from your server to get permissions info. Normally this means a loading state, but you can inject the router config from server-rendered Astro components:

src/components/uploadthing-ssr.astro

---
import { extractRouterConfig } from "uploadthing/server"
import { uploadRouter } from "~/server/uploadthing";

/**
 * This you only need to do once in your app to enable
 * server side rendering of the uploadthing component.
 * No data will be fetched on the client.
 */
const routerConfig = extractRouterConfig(uploadRouter);
(globalThis as any).__UPLOADTHING ??= routerConfig;
---

<script define:vars={{ routerConfig }}>
    /**
     * Injecting config to the client. This prevents the client from fetching
     * the configuration from the server, since we already have it.
     */
    globalThis.__UPLOADTHING ??= routerConfig;
</script>

Then render this component in your layout:

src/layouts/root.astro

---
import UploadThingSSR from "~/components/uploadthing-ssr.astro";
---
<html lang="en">
    <head>
        <title>My App</title>
    </head>
        <UploadThingSSR />
    <body>
        <slot />
    </body>
</html>

🎉 You're Done!

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

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

Was this page helpful?