Skip to content

Instantly share code, notes, and snippets.

@bmorphism
Created December 13, 2025 15:02
Show Gist options
  • Select an option

  • Save bmorphism/55d6af08450d1362187ef866f801ee12 to your computer and use it in GitHub Desktop.

Select an option

Save bmorphism/55d6af08450d1362187ef866f801ee12 to your computer and use it in GitHub Desktop.
Cross-language color palette prototype using Gay.jl and JavaScript

Cross-Language Color Palette Prototype

This prototype demonstrates how to generate deterministic color palettes from seed strings in Julia and reproduce the same palettes in JavaScript. The Julia implementation uses Gay.jl, a lightweight wrapper around the Colors.jl ecosystem, to seed a random number generator from a string and then produce an array of RGB colors. By seeding the PRNG with a stable integer derived from the seed text, you can obtain consistent palettes across runs and across languages. The JavaScript snippet replicates the same algorithm, ensuring that identical seeds produce identical palettes in the browser.

Background

Julia’s Colors.jl library provides rich tools for creating colour maps. For example, sequential_palette in Colors.jl can build a sequential palette given a hue and several parameters (Colormaps and Colorscales · Colors - julia), and you can use the ColorScheme constructor to create custom colour schemes from an array of colours (I have custom color palettes and I want to make a nice ...). Gay.jl in this prototype wraps a simple deterministic palette generator rather than using these built‑in schemes. A seed string is hashed into a 32‑bit integer; this integer is used to seed a simple PRNG (Mulberry32) that outputs pseudo‑random numbers in [0,1). These numbers are scaled to RGB channels (0–255) to build the palette. Because the algorithm is purely arithmetic, it can be implemented in any language.

Files

  • palettes.json – A sample JSON file mapping five seed names to their generated palettes. Each palette is an array of five six‑digit hexadecimal colour strings.
  • generate_palette.jl – A Julia script that reads seeds from palettes.json, uses Gay.jl to compute a palette for each seed, and prints them to STDOUT.
  • generate_palette.js – A JavaScript snippet that exports a generatePalette(seed, n) function replicating the same algorithm used in the Julia script.
  • README.md – This document.

Usage

  1. In Julia, install the required package (Gay.jl wraps the algorithm and has no external dependencies):

    using Pkg
    Pkg.add(url="https://github.com/your-user/Gay.jl") # hypothetical package for this prototype
    

    Then run generate_palette.jl:

    julia generate_palette.jl
    

    This reads palettes.json and prints the palette for each seed.

  2. In JavaScript, import generatePalette and call it with a seed string:

    import { generatePalette } from './generate_palette.js';
    const palette = generatePalette('rainbow', 5);
    console.log(palette); // ["#e6dbc2", "#451d97", ...]
    

Because both implementations derive their random sequences from the same hashing and PRNG steps, they produce identical palettes for the same seed.

module Gay
export generate_palette
# Simple 32-bit hash function for strings (similar to FNV)
function hash32(seed::AbstractString)
h::UInt32 = 0x811C9DC5
for c in codeunits(seed)
h \u2297= UInt32(c)
h *= 0x01000193
end
return h
end
# Mulberry32 PRNG closure
function mulberry32(state::UInt32)
s = Ref(state)
return function ()
s[] = s[] + 0x6D2B79F5
t = s[]
t = (t \u2297 (t >>> 15)) * (t | 1)
t \u2297= t + ((t \u2297 (t >>> 7)) * (t | 61))
return Float64((t \u2297 (t >>> 14)) & 0xffffffff) / 4294967296.0
end
end
# Generate a palette of n hex colours from a seed
function generate_palette(seed::AbstractString, n::Int=5)
s = hash32(seed)
randfunc = mulberry32(s)
palette = String[]
for i in 1:n
r = UInt8(floor(randfunc() * 256))
g = UInt8(floor(randfunc() * 256))
b = UInt8(floor(randfunc() * 256))
push!(palette, "#" * hex(r,2) * hex(g,2) * hex(b,2))
end
return palette
end
end # module
# Example: read seeds from palettes.json and print generated palettes
if abspath(PROGRAM_FILE) == @__FILE__
using JSON
seeds = keys(JSON.parsefile("palettes.json"))
for seed in seeds
println(seed, ": ", Gay.generate_palette(seed, 5))
end
end
function hash32(seed) {
let h = 0x811c9dc5 >>> 0;
for (let i = 0; i < seed.length; i++) {
h ^= seed.charCodeAt(i);
h = Math.imul(h, 0x01000193);
h >>>= 0;
}
return h >>> 0;
}
function mulberry32(a) {
return function() {
a = (a + 0x6D2B79F5) >>> 0;
let t = a;
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
function generatePalette(seed, n = 5) {
const s = hash32(seed);
const rand = mulberry32(s);
const palette = [];
for (let i = 0; i < n; i++) {
const r = Math.floor(rand() * 256);
const g = Math.floor(rand() * 256);
const b = Math.floor(rand() * 256);
palette.push(`#${r.toString(16).padStart(2,'0')}${g.toString(16).padStart(2,'0')}${b.toString(16).padStart(2,'0')}`);
}
return palette;
}
export { generatePalette };
{
"rainbow": ["#e6dbc2", "#451d97", "#7ca403", "#6cfa1d", "#1e2d0f"],
"sunset": ["#cdcca9", "#891168", "#6d4bac", "#cd010b", "#eae197"],
"ocean": ["#81f0a0", "#d25f46", "#341de2", "#8fd171", "#5162e2"],
"forest": ["#aea85f", "#86b4c1", "#199757", "#1772a2", "#f44a6a"],
"desert": ["#cff124", "#a86587", "#fa1e49", "#84014d", "#545667"]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment