Generate username-based gradient

import color from "tinycolor2"; async function hash(str: string): Promise<number> { let sum = 0; const buffer = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(str)) for (const n of new Uint8Array(buffer)) { sum += n; } return sum; } async function hue(str: string): Promise<number> { const n = await hash(str); return n % 360; } export async function generateGradient(username: string) { const h = await hue(username); const c1 = color({ h, s: 0.95, l: 0.5 }); const second = c1.triad()[1].toHexString(); return { fromColor: c1.toHexString(), toColor: second, }; } explain this code to me

Sure! This TypeScript code defines an asynchronous function that generates a color gradient based on a username string. Here's a breakdown of what each part does:


1. Importing tinycolor2

ts
import color from "tinycolor2";
  • This imports the tinycolor2 library, which simplifies color manipulation (e.g., changing hues, converting formats, generating color schemes like triads, etc.).


2. hash(str: string) function

ts
async function hash(str: string): Promise<number> { let sum = 0; const buffer = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(str)) for (const n of new Uint8Array(buffer)) { sum += n; } return sum; }
  • This function:

    • Uses SHA-1 hashing to convert a string (e.g., a username) into a cryptographic hash (a sequence of bytes).

    • Sums all the bytes in the hash to get a single number.

  • This number becomes a consistent but unique "signature" for the input string.


3. hue(str: string) function

ts
async function hue(str: string): Promise<number> { const n = await hash(str); return n % 360; }
  • This converts the hash value into a hue value (0–359), suitable for HSL (Hue, Saturation, Lightness) color models.

  • It ensures that each string maps to a unique hue on the color wheel.


4. generateGradient(username: string) function

ts
export async function generateGradient(username: string) { const h = await hue(username); const c1 = color({ h, s: 0.95, l: 0.5 }); const second = c1.triad()[1].toHexString(); return { fromColor: c1.toHexString(), toColor: second, }; }

This is the main function. Here's what it does:

  • await hue(username): Generates a hue based on the username.

  • color({ h, s: 0.95, l: 0.5 }): Creates a bright, colorful base color in HSL format.

  • c1.triad(): Generates a triadic color scheme based on the base color (three colors evenly spaced 120° apart on the hue wheel).

  • second = c1.triad()[1]: Picks the second color from that triad.

  • Returns an object with two hex color codes:

    • fromColor: The base color.

    • toColor: The secondary triad color.


✅ What It's For

This can be used to:

  • Generate consistent but visually diverse color gradients for different usernames.

  • Assign avatars, profile themes, or background gradients uniquely per user.


Would you like me to show a sample usage or visual example of how this gradient would look for a specific username?

Is the color guaranteed to be unique?

Great question. No, the color is not guaranteed to be unique per username, but it's very likely to be distinct for most usernames. Here's why:


🔑 How Uniqueness Works in This Code

  1. Hashing step:

    ts
    const buffer = await crypto.subtle.digest('SHA-1', new TextEncoder().encode(str))
    • SHA-1 produces a 160-bit (20-byte) hash — a large space that reduces the chance of collision.

    • But the next step reduces this space drastically:

  2. Hash sum:

    ts
    let sum = 0; for (const n of new Uint8Array(buffer)) { sum += n; }
    • This adds up all 20 bytes, yielding a number between 0 and 20 * 255 = 5100.

  3. Hue range limitation:

    ts
    return n % 360;
    • This reduces the sum to a number between 0 and 359.

    • So only 360 possible hue values exist.


🎨 Color Collisions Are Possible

  • There are far more than 360 possible usernames, so many usernames will map to the same hue.

  • Even though the hues may be spread out, collisions are inevitable when the domain of inputs is much larger than the output range (pigeonhole principle).


🟨 Is That a Problem?

Not necessarily:

  • The goal is to have visually diverse gradients — not strict uniqueness.

  • It works well for UI personalization, where it's acceptable if two users occasionally get the same gradient.


✅ How to Improve Uniqueness (If Needed)

If you want to reduce the chance of color collisions:

  • Use more of the SHA-1 hash (e.g., extract multiple properties from different bytes: hue, saturation, lightness).

  • Use multiple HSL properties:

    ts
    const h = hash1 % 360; const s = 0.5 + (hash2 % 50) / 100; // 0.5–1.0 const l = 0.4 + (hash3 % 20) / 100; // 0.4–0.6
  • This expands the number of distinct colors significantly (not just 360 hues).

Let me know if you’d like a version that increases uniqueness or minimizes collisions.