# Components (https://auraimage.ai/docs/components)





Rendering images is `<AuraImage />`. Accepting them is `<AuraUploader />`. Neither depends on the other, and both read your CDN base URL from `NEXT_PUBLIC_AURA_CDN_URL`.

Installing either one copies a single `.tsx` file into your repo. There is no `@auraimage/react` package to pin, and no component API you have to wait on us to extend — edit the file, delete half of it, restyle it; it's yours.

## AuraImage [#auraimage]

<ImageSpecimen />

A drop-in replacement for `<img>` that paints a placeholder on mount and crossfades into the full image once it decodes — the box is reserved from the start, so nothing reflows and the LCP element never flashes empty. The three placeholder modes — `blurhash`, `lqip`, and `empty` — trade payload against fidelity; the demo above switches between them live, and the URL under the frame is the exact request the component makes.

Transform options travel in the URL path, so a resize is a different URL rather than a different build. With the default `format="auto"` the extension is omitted entirely and the edge negotiates AVIF, WebP, or JPEG per request.

The `w=1536,h=1024` above is not arbitrary: the edge rounds both dimensions up to a fixed [dimension ladder](/docs/url-api#the-dimension-ladder), and those two values sit on it exactly. Ask for `w=800,h=533` instead and you'd be served a 1024×768 box — larger than requested, and cropped to a different aspect ratio. Open the network tab and check this one; the URL under the frame is what arrives.

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

Writes `components/aura/image.tsx`, installs `blurhash` from npm, and pulls in the [config module](#the-config-module). No Next.js import and no Tailwind requirement.

[Every `<AuraImage />` prop →](/docs/image)

## AuraUploader [#aurauploader]

<UploaderSpecimen />

Drag-and-drop, click-to-browse, and paste-from-clipboard, backed by a multi-file queue: per-row thumbnail and progress bar, cancel and retry, drag-reorder of files still waiting, and a copy-URL pill on each finished row. Uploads run in parallel up to `concurrency` (default `8`).

Bytes go straight from the browser to `cdn.auraimage.ai`. Your backend only mints a short-lived signature — it never proxies the file. The demo above signs through the shared demo project; in your app you'd pass `project="my-app"`, a pre-computed `signature`, or your own `getSignature` function.

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

Writes `components/aura/uploader.tsx` and installs `lucide-react`, `@auraimage/sdk`, the shadcn `cn()` helper, and the [config module](#the-config-module). One command, nothing left to wire.

To see an uploaded image go straight into a transform pipeline, the [home page](/#realtime-demo) pairs the same uploader with a live playground for width, quality, format, and fit.

[Full props reference →](/docs/uploader)

## Installing [#installing]

### The config module [#the-config-module]

Both components resolve the CDN origin through `@/lib/config.public`, which the registry installs alongside them as a dependency. You don't need to create it — but you should know what it is, because it's the one file you'll edit if your setup differs:

```ts title="src/lib/config.public.ts"
export const publicConfig = {
  NEXT_PUBLIC_AURA_CDN_URL: (process.env.NEXT_PUBLIC_AURA_CDN_URL ?? '').replace(/\/+$/, '')
};
```

That single field is all either component reads. On a bundler that doesn't expose `process.env` — Vite, where it's `import.meta.env` — change this line and both components follow.

### From a URL [#from-a-url]

Every registry item has a stable JSON endpoint. This is the copy-paste form used above and it needs no configuration:

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

### As a named registry [#as-a-named-registry]

If you install from AuraImage more than once, register the namespace in your `components.json` and refer to items by short name:

```json title="components.json"
{
  "registries": {
    "@aura": "https://auraimage.ai/registry/{name}.json"
  }
}
```

```bash
npx shadcn@latest add @aura/image @aura/uploader
```

### What lands in your repo [#what-lands-in-your-repo]

| Item       | Files written                                                          | npm packages installed                                     |
| ---------- | ---------------------------------------------------------------------- | ---------------------------------------------------------- |
| `image`    | `components/aura/image.tsx`, `lib/config.public.ts`                    | `blurhash`                                                 |
| `uploader` | `components/aura/uploader.tsx`, `lib/config.public.ts`, `lib/utils.ts` | `lucide-react`, `@auraimage/sdk`, `clsx`, `tailwind-merge` |

Paths follow your `components.json` aliases, so the files land wherever the rest of your components live. Installing both items writes `lib/config.public.ts` once, not twice.

## Requirements [#requirements]

* **React 18 or newer.** Both are client components (`'use client'`) built on hooks and plain DOM APIs. Neither imports from `next/*`, so they run under Vite or Remix as readily as Next.js — the `NEXT_PUBLIC_` prefix is a naming convention here, not a framework dependency.
* **`NEXT_PUBLIC_AURA_CDN_URL`** in your environment, read through the [config module](#the-config-module). `aura init` writes it to `.env.local` alongside your project name and public key; see [Getting Started](/docs/getting-started). This is the only thing the installer can't do for you.
* **Tailwind CSS** — `<AuraUploader />` only, for its styling. `<AuraImage />` uses inline styles and passes `className` straight through, so it drops into any styling approach.

## Why source instead of a package [#why-source-instead-of-a-package]

A CDN component is exactly the kind of code you end up wanting to change: a different placeholder ramp, your own loading skeleton, an extra `sizes` attribute, a wrapper your design system already has. Shipping it as a dependency means every one of those is a feature request. Shipping it as source means it's a diff.

The tradeoff is upgrades: re-running the add command overwrites the file, so your edits are yours to reconcile. Both components are single files under 500 lines, which is the point — you can read the whole thing before you accept it.


## Related

- [Image](https://auraimage.ai/docs/image)
- [Uploader](https://auraimage.ai/docs/uploader)
- [Getting Started](https://auraimage.ai/docs/getting-started)