# Uploader (https://auraimage.ai/docs/uploader)



`<AuraUploader />` is a [Shadcn-registry component](/docs/components) you copy into your project. It handles drag-and-drop, click-to-browse, paste-from-clipboard, a multi-file queue with per-row progress, cancel/retry, and drag-reorder of queued files.

Uploads go directly to `cdn.auraimage.ai` — your backend only mints the signature, never handles the bytes.

## Install [#install]

```bash
npx shadcn@latest add https://auraimage.ai/registry/uploader.json
```

This copies `src/components/aura/uploader.tsx` and pulls in its lucide-react and shadcn `cn()` deps. It reads your CDN base URL from `NEXT_PUBLIC_AURA_CDN_URL`.

## Usage [#usage]

```tsx
import { AuraUploader } from '@/components/aura/uploader';

export default function ProfilePage() {
  return (
    <AuraUploader
      project='my-app'
      onUpload={(result) => {
        console.log(result.url);      // final CDN URL
        console.log(result.name);     // store this for setVisibility / getSignedUrl
        console.log(result.blurhash); // store for placeholder rendering
      }}
      maxSize='30mb'
      multiple
    />
  );
}
```

## Signature delivery [#signature-delivery]

The component supports three ways to obtain a signature, resolved in this precedence order:

1. **`getSignature`** — async function. Highest precedence. Use for custom auth flows, signature caching, or refresh logic.
2. **`signature`** — pre-computed string. Useful from a Server Component that mints the signature at render time.
3. **`project`** — project name. The component POSTs `{ project, filename, contentType, size }` to `/api/aura/sign` on your own backend and expects `{ signature }` back.

You only need one. The most common pattern is `project="my-app"` + a small route handler:

```ts title="app/api/aura/sign/route.ts"
import { AuraImage } from '@auraimage/sdk';

const aura = new AuraImage({
  secretKey: process.env.AURA_SECRET_KEY!,
  projectName: process.env.NEXT_PUBLIC_AURA_PROJECT_NAME!
});

export async function POST() {
  const signature = await aura.signUpload({
    maxSize: '30mb',
    allowedTypes: ['image/*'],
    expiresIn: 3600
  });
  return Response.json({ signature });
}
```

For RSC-minted signatures:

```tsx
import { AuraUploader } from '@/components/aura/uploader';
import { aura } from '@/lib/aura';

export default async function Page() {
  const signature = await aura.signUpload({ maxSize: '30mb' });
  return <AuraUploader signature={signature} />;
}
```

For custom auth (Firebase, Clerk, …):

```tsx
<AuraUploader
  getSignature={async () => {
    const token = await getFirebaseIdToken();
    const res = await fetch('/api/sign', { headers: { Authorization: `Bearer ${token}` } });
    return (await res.json()).signature;
  }}
/>
```

## Props [#props]

| Prop           | Type                              | Default     | Description                                                                                   |
| -------------- | --------------------------------- | ----------- | --------------------------------------------------------------------------------------------- |
| `onUpload`     | `(result: UploadResult) => void`  | —           | Called once per successful file.                                                              |
| `onError`      | `(error: Error) => void`          | —           | Called on validation failure (size cap) or upload failure.                                    |
| `maxSize`      | `string`                          | `"30mb"`    | Client-side size cap. The edge enforces its own limit from the signature — keep them in sync. |
| `accept`       | `string`                          | `"image/*"` | MIME filter for the file picker.                                                              |
| `multiple`     | `boolean`                         | `false`     | Allow multiple files. When `false`, dropping a new file replaces the queue.                   |
| `concurrency`  | `number`                          | `8`         | Max simultaneous uploads.                                                                     |
| `className`    | `string`                          | —           | Extra classes merged onto the dropzone container.                                             |
| `getSignature` | `() => Promise<string> \| string` | —           | Async signature provider (highest precedence).                                                |
| `signature`    | `string`                          | —           | Pre-computed signature.                                                                       |
| `project`      | `string`                          | —           | Project name. Triggers the `/api/aura/sign` convention.                                       |

`UploadResult` shape (matches the [upload response](/docs/upload#upload-response)):

```ts
interface UploadResult {
  url: string;
  name: string;
  blurhash: string;
  width: number;
  height: number;
  format: string;
  size: number;
}
```

## Behavior [#behavior]

* **Drag-and-drop** with an outlined active state on the whole container.
* **Click to browse** — the container is keyboard-focusable (`Enter` / `Space` opens the picker).
* **Paste-from-clipboard** — while the uploader has focus, pasted images are queued automatically.
* **Per-row UI** — thumbnail, filename, byte size, 2 px progress bar, status, and per-row remove / cancel / retry.
* **Drag-reorder** of queued (not-yet-uploaded) items.
* **Concurrency** — uploads run in parallel up to `concurrency` (default `8`).
* **Copy-URL** pill on each successful row.

All thumbnails use object URLs that are revoked on unmount or removal — no leaks.

## Live demo [#live-demo]

The [home page](https://auraimage.ai/#realtime-demo) runs a real `<AuraUploader>` against production. Drop an image there to watch the queue, then transform the result with the playground next to it.


## Related

- [Upload Flow](https://auraimage.ai/docs/upload)
- [Components](https://auraimage.ai/docs/components)
- [AuraImage SDK v2 — Client-Side Uploads, Secret Key Rotation, and Armenian Language Support](https://auraimage.ai/blog/auraimage-sdk-v2-release)