Grab colors from any image.
Works on both server and client, supporting remote URLs, local files, and raw image data.
To get started, install the required dependencies:
pnpm add @drgd/aura sharp
Server-side usage requires the peer dependency sharp
to be installed as shown above.
Import the desired function/hook from the appropriate entry point.
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).
Example with an image URL or local path:
"use client";
import { useAura } from "@drgd/aura/client";
export function Colors({ imagePath }: { imagePath: string }) {
// e.g., "/assets/my-image.webp" or "https://picsum.photos/200"
const { colors, isLoading, error } = useAura(imagePath, {
paletteSize: 4, // Optional: Specify number of colors (1-12, default: 6)
onError: (err) => console.error(err.message), // Optional: Error callback
});
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
// On error, 'colors' will contain the fallback palette
return (
<ul className>
{colors.map((color) => (
<li
key={color.hex}
style={{
backgroundColor: color.hex,
}}
>
{color.hex} -{Math.round(color.weight * 100)}%
</li>
))}
</ul>
);
}
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 the colors are being extracted, wrap the 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 Buffer
:
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 }) {
// Construct the full path to the image in your public directory or elsewhere
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);
// getAura returns fallback colors on processing errors, but file read might fail
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>Local Image Colors</h1>
<Suspense fallback={<p>Loading colors...</p>}>
<LocalColors imageFileName="/assets/1.webp" />
</Suspense>
</div>
);
}
React hook for client-side color extraction.
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 arrayonError?: (error: Error) => void
- Error callback function
colors: AuraColor[]
- Array of extracted (or fallback) colors, sorted by weightisLoading: boolean
- Boolean indicating extraction statuserror: Error | null
- Error object if failed,null
otherwise
Async function for server-side color extraction.
imageUrlOrBuffer: string | Buffer
- The URL of the image or aBuffer
containing image dataoptions?: 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 arrayvalidateUrl?: boolean
- Whether to perform internal URL validation checks (protocol, type, size). Recommended to leave enabled unless URLs are pre-validated (default: true)
A promise resolving to the array of extracted (or fallback) colors, sorted by weight. Throws an error only for invalid paletteSize
. Other errors (network, processing) result in fallback colors being returned.
type AuraColor = {
hex: string; // Hexadecimal color code (e.g., "#FF0000")
weight: number; // Color prevalence/importance (0-1)
};
Both implementations include built-in error handling with fallback colors:
- Invalid image URLs
- Network errors
- Timeout errors (10s default)
- Invalid image data
- CORS errors
- David Dragovacz (@dragidavid)
MIT License.