AuraImage

Components

Shadcn/ui component registry — own the code, edit it freely.

AuraImage provides a Shadcn/ui component registry so you own the code. There is no black-box library to fight — add the component to your /components folder and edit it freely.

Installing from the Registry

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

This copies two components into src/components/aura/:

FilePurpose
image.tsxDisplay component with Triple-Stage Loading
uploader.tsxUpload widget with drag-and-drop, previews, and progress

Or install both at once via the CLI:

npx aura-cli add all

<AuraImage />

A drop-in replacement for Next.js <Image /> that implements Triple-Stage Loading to eliminate LCP jank.

Triple-Stage Loading

StageWhat the user seesHow it works
Stage 1 — InstantColorful blurred placeholderBlurHash decoded from a data-blurhash attribute — zero network requests
Stage 2 — FastLow-quality image preview?w=50&q=20 version loaded in parallel with the full image
Stage 3 — FinalFull-quality, crisp imageBrowser-optimal format (JXL/AVIF) fades in over the placeholder

Usage

import { AuraImage } from '@/components/aura/image';

export default function Hero() {
  return (
    <AuraImage
      src="narek/hero-photo"
      alt="Golden Gate Bridge at sunset"
      width={1200}
      height={800}
      priority           // Preload for above-the-fold LCP images
      placeholder="blur" // Enables Triple-Stage Loading
    />
  );
}

Props

PropTypeDefaultDescription
srcstringrequiredSlug path: "[user-slug]/[filename]" — no extension needed
altstringrequiredAlt text. Use the generate_alt MCP tool if needed.
widthnumberrequiredDisplay width in pixels
heightnumberrequiredDisplay height in pixels
prioritybooleanfalsePreloads the image. Set for the largest above-the-fold image.
placeholder"blur" | "empty""blur"blur enables Triple-Stage Loading
qualitynumber80Compression quality (1–100)
fit"cover" | "contain" | "face" | "auto""cover"Smart crop mode
format"auto" | "jxl" | "avif" | "webp" | "jpeg""auto"Output format

Environment Switching

The component uses NEXT_PUBLIC_AURA_URL for the base URL (defaults to https://auraimage.ai) and switches between your production and dev slugs based on NODE_ENV:

const baseUrl = process.env.NEXT_PUBLIC_AURA_URL ?? 'https://auraimage.ai';

<AuraUploader />

A full-featured upload widget. Includes drag-and-drop, file validation, client-side preview, upload progress, and error handling.

Usage

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

export default function ProfilePage() {
  return (
    <AuraUploader
      onUpload={(result) => {
        console.log(result.url);      // final CDN URL
        console.log(result.blurhash); // for storing in your DB
      }}
      maxSize="5mb"
      accept="image/*"
    />
  );
}

The uploader calls your backend (/api/get-upload-signature by default) to fetch a signature, then POSTs directly to cdn.auraimage.ai. Your backend never proxies the binary data.

You can override the signature endpoint:

<AuraUploader
  signatureEndpoint="/api/custom-upload-auth"
  onUpload={handleUpload}
/>

Props

PropTypeDefaultDescription
onUpload(result: UploadResult) => voidrequiredCalled with the CDN URL and metadata after a successful upload
onError(error: Error) => voidCalled on upload failure
maxSizestring"5mb"Max file size, e.g. "10mb"
acceptstring"image/*"MIME type filter
signatureEndpointstring"/api/get-upload-signature"Your backend route that returns { signature }
multiplebooleanfalseAllow uploading multiple files at once

No-Code Web Component

For projects not using React (plain HTML, vanilla JS, Astro islands), AuraImage provides a Web Component:

<script src="https://cdn.auraimage.ai/widget.js"></script>

<aura-upload
  api-key="pk_live_..."
  on-success="window.handleUpload"
  max-size="5mb"
  theme="dark"
></aura-upload>

The widget fires a aura:upload custom event with the result URL and BlurHash on success.


Smart Fallback

If AuraImage is unreachable or the user has exceeded their monthly limit, the components fall back gracefully:

  • <AuraImage /> renders a standard <img> tag using the original URL.
  • <AuraUploader /> falls back to a plain <input type="file">.

This prevents your app from breaking if our service has an incident.