Installation

pnpm add @drgd/aura sharp

Server-side usage requires the peer dependency sharp to be installed as shown above.

client

Usage

Use the useAura hook to extract colors on the client.

It accepts a remote image URL or a local static path (e.g., from your public folder).

"use client";
import { useAura } from "@drgd/aura/client";
export function Colors({ imageUrl }: { imageUrl: string }) {
// e.g., "/assets/my-image.webp" or "https://picsum.photos/200"
const { colors, isLoading, error } = useAura(imageUrl, {
paletteSize: 4,
onError: (err) => console.error(err.message),
});
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<ul>
{colors.map((color) => (
<li key={color.hex}>
{color.hex} - {Math.round(color.weight * 100)}%
</li>
))}
</ul>
);
}

Parameters

  • imageUrl?: string | null
    • URL of the image or a local static path
    • Uses default fallbackColors if not provided
  • options?: object
    • paletteSize?: number - Number of colors to extract (default: 6, range: 1-12)
    • fallbackColors?: AuraColor[] - Custom fallback colors array
    • onError?: (error: Error) => void - Error callback function

Returns

  • colors: AuraColor[] - Array of extracted (or fallback) colors, sorted by weight
  • isLoading: boolean - Boolean indicating extraction status
  • error: Error | null - Error object if failed, null otherwise otherwise

Demo

Asset 1
server

Usage

Use the getAura function inside an async Server Component. It accepts a remote image URL or a Buffer.

To prevent blocking the initial page load while colors are extracted, wrap getAura call in <Suspense>.

We use sharp under the hood to process the image. Check out the sharp ↗ documentation for more information.

Example with an image URL
import { Suspense } from "react";
import { getAura } from "@drgd/aura/server";
// Server Component that gets the colors
async function Colors({ imageUrl }: { imageUrl: string }) {
const colors = await getAura(imageUrl, {
paletteSize: 8, // Optional: Specify number of colors (1-12, default: 6)
// quality: 'high', // Optional: 'low' (200px), 'medium' (400px), 'high' (800px)
// timeout: 5000, // Optional: Max processing time in ms (default: 10000)
// validateUrl: false, // Optional: Disable internal URL checks (default: true)
// fallbackColors: [{ hex: '#...', weight: 1 }], // Optional: Custom fallbacks
});
return (
<ul>
{colors.map((color) => (
<li key={color.hex} style={{ backgroundColor: color.hex }}>
{color.hex} - {Math.round(color.weight * 100)}%
</li>
))}
</ul>
);
}
// Parent Server Component
export default async function Page() {
const imageUrl = "https://picsum.photos/200";
return (
<div>
<h1>Image Colors</h1>
<Suspense fallback={<p>Loading colors...</p>}>
<Colors imageUrl={imageUrl} />
</Suspense>
</div>
);
}
Example with a local image
import fs from "fs";
import path from "path";
import { Suspense } from "react";
import { getAura } from "@drgd/aura/server";
// Server Component that gets the colors
async function LocalColors({ imageFileName }: { imageFileName: string }) {
const imagePath = path.join(process.cwd(), "public", "assets", imageFileName);
let colors;
try {
const imageBuffer = await fs.readFile(imagePath);
colors = await getAura(imageBuffer, { paletteSize: 8 });
} catch (error) {
console.error("Failed to process image", error);
colors = await getAura(Buffer.from(""), { paletteSize: 5 });
}
return (
<ul>
{colors.map((color) => (
<li key={color.hex} style={{ backgroundColor: color.hex }}>
{color.hex} - {Math.round(color.weight * 100)}%
</li>
))}
</ul>
);
}
// Parent Server Component
export default async function Page() {
return (
<div>
<h1>Image Colors</h1>
<Suspense fallback={<p>Loading colors...</p>}>
<LocalColors imageFileName="/assets/1.webp" />
</Suspense>
</div>
);
}

Parameters

  • imageUrlOrBuffer: string | Buffer
    • The URL of the image or a Buffer containing image data
  • options?: object
    • paletteSize?: number - Number of colors to extract (default: 6, range: 1-12)
    • quality?: "low" | "medium" | "high" - "low" (200px) | "medium" (400px) | "high" (800px)
    • timeout?: number - Maximum processing time in milliseconds (default: 10000)
    • fallbackColors?: AuraColor[] - Custom fallback colors array
    • validateUrl?: boolean - Enable URL validation (default: true)

Returns

  • Promise<AuraColor[]> - Array of extracted (or fallback) colors, sorted by weight

Error handling & Fallbacks

Both implementations include built-in error handling with fallback colors:

  • Invalid image URLs
  • Network errors
  • Timeout errors (10s default)
  • Invalid image types
  • CORS errors
// Custom fallback colors
const fallbackColors = [
{ hex: "#FF0000", weight: 0.4 }, // Red
{ hex: "#00FF00", weight: 0.3 }, // Green
{ hex: "#0000FF", weight: 0.3 } // Blue
];
// Server-side usage
const colors = await getAura(imageUrl, {
paletteSize: 3,
fallbackColors
});
// Client-side usage
const { colors } = useAura(imageUrl, {
paletteSize: 3,
fallbackColors,
onError: (error) => console.error(error)
});