kennwilson/colormap
kennwilson/colormap is a Laravel/PHP package for defining, generating, and working with color maps and palettes, providing a simple API to keep color schemes consistent across your application.
Install
composer require kennwilson/colormap
Laravel's package auto-discovery should register the service provider and a Colormap facade if the package ships one. If not, resolve the class manually via app(\KennWilson\Colormap\Colormap::class) or add your own alias in config/app.php.
Where to look first
README.md — the conversion API surface is the whole package; read this end-to-end before anything else.src/ — the class(es) doing hex ↔ RGB ↔ name translation. It's small enough to read in one sitting, which matters because the package has zero dependents and essentially no ecosystem validation — you need to know exactly what it does before trusting it.tests/ — check whether edge cases (short hex, uppercase, invalid names) are covered. If not, that's your first TODO.First use case
Normalizing user-supplied colors before persistence. A user submits #FFF, rgb(255,255,255), or white; you need one canonical form in the DB:
use KennWilson\Colormap\Colormap;
$hex = Colormap::toHex($request->input('brand_color')); // '#ffffff'
That single normalization step is the highest-value, lowest-risk adoption path — you're not replacing a dependency, just adding a thin translation layer.
Form request normalization
Wrap conversion in a prepareForValidation() hook so every downstream consumer sees canonical hex:
protected function prepareForValidation(): void
{
if ($this->filled('color')) {
$this->merge(['color' => Colormap::toHex($this->input('color'))]);
}
}
Pair it with a regex:/^#[0-9a-f]{6}$/i rule so invalid input fails validation after conversion attempts, not during.
Config-driven palette / theming
Store brand colors as named constants in config/theme.php, convert to hex once at boot, and expose them to Blade. This plays to the package's strength (name → hex) without coupling your views to the package API:
// config/theme.php
'primary' => 'cornflowerblue',
// AppServiceProvider::boot()
foreach (config('theme') as $key => $name) {
View::share("theme.$key", Colormap::nameToHex($name));
}
API resources
Cast to a consistent hex representation at the resource boundary so mobile/web clients aren't parsing three formats:
public function toArray($request): array
{
return [
'color' => Colormap::toHex($this->color),
];
}
Wrapping in your own service
Because the package has zero dependents and a single maintainer, don't let it spread across your codebase. Introduce App\Support\Color that delegates to Colormap internally. If the package gets abandoned (a real risk at 0 stars), you swap the body of one class instead of grepping for Colormap:: across 40 files.
Command/seeder helpers
For demo data and console output, the name-lookup is genuinely convenient:
$this->info(Colormap::toName('#ff0000')); // 'red'
Useful for readable test fixtures ('danger' => 'red') instead of magic hex strings.
Hex prefix assumptions. Most color packages assume a leading #; some strip it, some reject its absence. Verify both #ffffff and ffffff against the README/tests before shipping — a silent null return on a missing prefix is the #1 gotcha here.
Short-form hex. #fff vs #ffffff is a common divergence. Decide at your boundary whether you accept 3-digit input (expand it yourself) rather than depending on the package to do it.
No alpha channel. The description mentions hex, RGB, and names only — RGBA/8-digit hex is out of scope. If you need opacity, store it as a separate column; don't assume the package round-trips it.
Named color coverage. "Named colors" almost certainly means the CSS color keywords (rebeccapurple, chartreuse, …), not Tailwind or Material palettes. Don't wire it to design-system tokens and expect matches.
Invalid input behavior. Whether the package returns null, throws, or returns false on a bad value is critical and likely undocumented. Write a thin guard in your wrapper:
public static function toHex(string $color): ?string
{
try {
return Colormap::toHex($color) ?: null;
} catch (\Throwable) {
return null;
}
}
Then assert null in a feature test with 'not-a-color', '', and '#12345'.
Case sensitivity. RED, Red, and red should all resolve; hex output should be lowercased for consistent DB comparisons and unique indexes.
Zero-dependency, zero-ecosystem reality. No dependents means no battle-tested integration examples and no downstream bug reports. Pin the version in composer.json ("^1.0" or even a commit hash), and add your own tests around the specific conversions you rely on. Treat it as vendored utility code, not infrastructure.
Performance is a non-issue. Pure string/array manipulation — no I/O, no regex backtracking risk. Don't bother caching conversions unless you're in a tight loop over thousands of rows; even then, array_map once per request beats a cache round-trip.
Extension point. The named-color table is the natural thing to extend for custom brand names. If the class exposes it (protected array or a setter), subclass; otherwise build the mapping in your own App\Support\Color on top of the base conversions.
How can I help you explore Laravel packages today?