Palette Generator Template
- Next.js
- TypeScript
Pick one color and get a named palette, with copyable hex codes and CSS variables.
A Next.js color palette app. Pick a base color, a harmony (triad, analogous, tetrad, contrast or mono) and a mood such as pastel, soft or hard, and get a palette of named colors with hex and RGB codes. Click any swatch to copy it, copy the palette as CSS variables, and save favorites on the device. Use it as a design tool, or lift the route to theme a site or app from a brand color.

What it does
- Five harmonies, six moods
- Triad, analogous, tetrad, contrast and mono schemes, each in balanced, soft, pastel, light, hard or pale.
- Named colors
- Every swatch has a name, hex and RGB, drawn in its own color with a text color that stays readable.
- Copy as CSS
- Copy one hex with a click, or the whole palette as CSS variables named after each color.
- Saved palettes
- Keep palettes you like in the browser on that device, and reopen any of them in one tap.
- Keeps your key private
- The browser only calls your own API route, which checks the inputs, caches palettes for a day and limits each visitor to 10 a minute.
How it works
The API route: it checks the color, scheme and mood, answers from the cache when it can, and calls Color Palette Generator.
/** GET /api/palette?color=2A9D8F&scheme=triade&variation=soft: a palette from Color Palette Generator. */
export async function GET(request: Request) {
const params = new URL(request.url).searchParams;
const color = (params.get('color') || '').replace('#', '').toUpperCase();
const scheme = params.get('scheme') || 'triade';
const variation = params.get('variation') || 'default';
if (!/^[0-9A-F]{6}$/.test(color)) return fail('Pick a color as a 6-digit hex code, like 2A9D8F');
if (!SCHEMES.includes(scheme)) return fail(`Scheme must be one of: ${SCHEMES.join(', ')}`);
if (!VARIATIONS.includes(variation)) return fail(`Variation must be one of: ${VARIATIONS.join(', ')}`);
const key = `palette:${color}:${scheme}:${variation}`;
const hit = fromCache(key, TTL_MS);
if (hit) return Response.json(hit);
const blocked = guard(request);
if (blocked) return blocked;
return respond(async () => {
const data = await callApi('colorpalette', { query: { color, scheme, variation } });
toCache(key, data);
return data;
});
}Deploy it
- Get a free API key
The free plan includes 200 credits a month, no card needed. Create your key.
- Deploy it
Click Deploy to Vercel. Vercel copies the repo to your GitHub account and asks for
APIVERVE_API_KEY: paste your key there. - Open your app
Vercel builds it and gives you a live URL, usually in about a minute. Every push to the repo redeploys it.
Try the Color Palette Generator API — the call this template makes
No key required to try it. Get a key to use it in your app.
{
"status": "ok",
"error": null,
"data": {
"source": "#FF5733",
"sourceName": "Outrageous Orange",
"hue": 11,
"scheme": "triade",
"variation": "soft",
"distance": 0.5,
"colorCount": 5,
"colorPalette": [
{
"hex": "#CC988F",
"name": "Oriental Pink",
"rgb": {
"r": 204,
"g": 152,
"b": 143
},
"hsl": {
"h": 9,
"s": 37,
"l": 68
},
"luminance": 0.373,
"isDark": true,
"textColor": "#FFFFFF",
"accessibility": {
"contrastWithWhite": 2.48,
"contrastWithBlack": 8.46,
"wcagAANormal": false,
"wcagAALarge": false,
"wcagAAA": false
}
},
{
"hex": "#805F59",
"name": "Russett",
"rgb": {
"r": 128,
"g": 95,
"b": 89
},
"hsl": {
"h": 9,
"s": 18,
"l": 43
},
"luminance": 0.135,
"isDark": true,
"textColor": "#FFFFFF",
"accessibility": {
"contrastWithWhite": 5.68,
"contrastWithBlack": 3.7,
"wcagAANormal": true,
"wcagAALarge": true,
"wcagAAA": false
}
},
{
"hex": "#E6D2CF",
"name": "Dust Storm",
"rgb": {
"r": 230,
"g": 210,
"b": 207
},
"hsl": {
"h": 8,
"s": 32,
"l": 86
},
"luminance": 0.674,
"isDark": false,
"textColor": "#000000",
"accessibility": {
"contrastWithWhite": 1.45,
"contrastWithBlack": 14.48,
"wcagAANormal": true,
"wcagAALarge": true,
"wcagAAA": true
}
},
{
"hex": "#BF6E60",
"name": "Contessa",
"rgb": {
"r": 191,
"g": 110,
"b": 96
},
"hsl": {
"h": 9,
"s": 43,
"l": 56
},
"luminance": 0.231,
"isDark": true,
"textColor": "#FFFFFF",
"accessibility": {
"contrastWithWhite": 3.74,
"contrastWithBlack": 5.61,
"wcagAANormal": false,
"wcagAALarge": true,
"wcagAAA": false
}
},
{
"hex": "#A2CC8F",
"name": "Pine Glade",
"rgb": {
"r": 162,
"g": 204,
"b": 143
},
"hsl": {
"h": 101,
"s": 37,
"l": 68
},
"luminance": 0.529,
"isDark": false,
"textColor": "#000000",
"accessibility": {
"contrastWithWhite": 1.82,
"contrastWithBlack": 11.57,
"wcagAANormal": true,
"wcagAALarge": true,
"wcagAAA": true
}
}
],
"colorPaletteRaw": [
"cc988f",
"805f59",
"e6d2cf",
"bf6e60",
"a2cc8f"
],
"css": ":root {\n --primary: #CC988F;\n --primary-rgb: 204, 152, 143;\n --secondary: #805F59;\n --secondary-rgb: 128, 95, 89;\n --tertiary: #E6D2CF;\n --tertiary-rgb: 230, 210, 207;\n --quaternary: #BF6E60;\n --quaternary-rgb: 191, 110, 96;\n --quinary: #A2CC8F;\n --quinary-rgb: 162, 204, 143;\n}",
"image": {
"imageName": "6ee29826-a52f-4c87-86f5-bef3b49f0dbb_palette.png",
"format": ".png",
"downloadURL": "https://storage.googleapis.com/apiverve/APIData/colorpalette/6ee29826-a52f-4c87-86f5-bef3b49f0dbb_palette.png?GoogleAccessId=635500398038-compute%40developer.gserviceaccount.com&Expires=1766010083&Signature=Boef5OapaNmcyp0F8bGmf%2BVfQk3zQkiWcw1THBfbsevtYGZnOuzr7xKDRlk9FYiHidSoMz6wjody2ymL7GzUoHkDvA8PEdSERhAq2z9St5yWlaX1c87KoNh%2FtCQEJqHixYk039NuYyb%2FhJu18JFY1RNrOfo8OPZEn9a3ICQdTDL0fYQEZEBxnDuc%2B7wvn4q9UFWhCJcf302HcoZoCw76AzrgVRu%2FazuahqHdVWMR1K5QTV3U51lSoqC23ERHjRZ6uZB8W0bCO65qBFrRNzWEPSVCC%2F8oafvvitZwB1YCG674q3MbtRhWXIhX2zdoPCT%2BgxL7E4fgIyXDtDLm5%2Bm%2Fsg%3D%3D",
"expires": 1766010083748
}
}
}