dimah-s3v0.4.1

Quickstart

Minimal setup for Next.js with server and client hooks.

Install

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

S3 client

.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_DEFAULT_BUCKET="your-bucket-name"
lib/s3-client.ts
import { S3Client } from "@aws-sdk/client-s3";

export const s3Client = 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 defaultBucket = process.env.S3_DEFAULT_BUCKET!;

Works with any S3-compatible provider. Setup may differ by provider — see Providers.

Server config and route

lib/s3.ts
import { dimahS3 } from "@dimah-s3/server";
import { s3Client, defaultBucket } from "@/lib/s3-client";

export const s3 = dimahS3({
  s3: s3Client,
  defaultBucket,
  upload: { enabled: true },
  download: { enabled: false },
  delete: { enabled: false },
  multipart: { enabled: false },
});
app/api/s3/[...s3]/route.ts
import { toNextJsHandler } from "@dimah-s3/server/next";
import { s3 } from "@/lib/s3";

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

More frameworks (Fastify, Elysia, Node, Workers): Server adapters.

Upload-only is now live on /api/s3.

Client provider (standard)

components/s3-provider.tsx
"use client";

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

export const { api, S3Provider, useApi } = createS3Client();

export function S3ClientProvider({ children }: { children: React.ReactNode }) {
  return <S3Provider>{children}</S3Provider>;
}

Mount once near your app root — provider for hooks/UI, toaster for feedback (same pattern as the examples):

app/layout.tsx
import { Toaster } from "@dimah-s3/ui";
import { S3ClientProvider } from "@/components/s3-provider";

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

Registry installs: import Toaster from @/components/ui/toast instead of @dimah-s3/ui.

UI setup

Theme variables and package install (toaster is already in the layout above):

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

/* + shadcn theme variables */

shadcn theme variables must be in globals.css.

Mount the toaster once in your root layout:

app/layout.tsx
import { Toaster } from "@dimah-s3/ui";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Toaster />
      </body>
    </html>
  );
}

Already using shadcn toast for your own messages? Mount both — rename one import (Toaster as DimahToaster). They are independent; your code keeps import { toast } from "@/components/ui/toast" and toast.add({ … }).

One upload button

app/page.tsx
"use client";

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

export default function Page() {
  return (
    <div>
      <UploadButton
        objectKey={(file) => `uploads/${Date.now()}-${file.name}`}
        accept={["image/*", ".pdf"]}
        maxFileSize={10 * 1024 * 1024}
        label="Upload file"
      />
    </div>
  );
}

At this point, selecting a file uploads directly to S3.

Need deeper setup details? See Server setup, Client setup, and UI setup.

Need custom auth/DB hooks or another framework? Continue with Server setup and Client setup.

On this page