dimah-s3v1.5.11

Quickstart

A working S3 upload in minutes — new app or existing project.

Create a new project

Scaffold a full-stack project with preconfigured S3 routes and UI:

npx @dimah-s3/cli@latest create

Manual installation

Install dependencies

npm i @dimah-s3/server @dimah-s3/react @aws-sdk/client-s3

Configure S3 and routes

.env
S3_ENDPOINT="https://your-endpoint.example.com"
S3_REGION="auto"
S3_ACCESS_KEY_ID="your-access-key-id"
S3_SECRET_ACCESS_KEY="your-secret-access-key"
S3_BUCKET="your-bucket-name"
lib/s3.ts
import { S3Client } from "@aws-sdk/client-s3";
import { dimahS3, route } from "@dimah-s3/server";

export const awsS3 = new S3Client({
  region: process.env.S3_REGION,
  endpoint: process.env.S3_ENDPOINT,
  credentials: {
    accessKeyId: process.env.S3_ACCESS_KEY_ID!,
    secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,
  },
});

export const s3 = dimahS3({
  client: awsS3,
  bucket: process.env.S3_BUCKET!,
  routes: {
    avatar: route({
      upload: {
        fileTypes: ["image/*"],
        maxFileSize: 2 * 1024 * 1024, // 2MB
      },
      download: true,
    }),
  },
});

Set bucket CORS for your origin — Amazon S3, Cloudflare R2, or MinIO.

Cloudflare R2

Set upload.method to "PUT". See Cloudflare R2.

Mount the route handler

app/api/s3/[...s3]/route.ts
import { toNextJsHandler } from "@dimah-s3/server/next";
import { s3 } from "@/lib/s3";

export const { GET, POST, PUT, PATCH, DELETE } = toNextJsHandler(s3);

Cache Components

Next.js 16.4 enables Cache Components on new apps. This handler reads the request, so it runs on each request. Keep the handler as written. Server Setup explains why it must stay uncached.

Other runtimes: Server Setup.

Create the client and provider

lib/s3-client.ts
"use client";

import { createS3Client } from "@dimah-s3/react";

export const s3Client = createS3Client();
export const S3Provider = s3Client.Provider;

Wrap your application

npm i @dimah-s3/ui shadcn
app/globals.css
@import "shadcn/tailwind.css";
@import "@dimah-s3/ui/styles.css"; 

/* shadcn theme variables (`--primary`, `--muted`, …) */
app/layout.tsx
import { Toaster } from "@dimah-s3/ui"; 
import { S3Provider } from "@/lib/s3-client"; 

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

Add an upload button

app/page.tsx
"use client";

import { useUpload } from "@dimah-s3/react";
import { UploadButton } from "@dimah-s3/ui";

export default function Page() {
  const upload = useUpload({ route: "avatar" });

  return <UploadButton upload={upload} />;
}

Selecting a file presigns a secure URL and uploads directly to your bucket.

Frequently asked questions

On this page