How to Generate Contour SVG Logos Using SHA‑256 and a Seeded RNG

The woosal1337/blog repository provides a client-side algorithm that hashes any input string with SHA‑256, derives a seeded pseudo‑random number generator from π digits, and renders the result as a unique, deterministic SVG contour logo.

The generateContour function transforms arbitrary text—such as project names or UUIDs—into reproducible vector graphics without requiring server-side processing or external graphics libraries. By combining the Web Crypto API’s SHA‑256 implementation with a custom π‑stream randomness generator, the code ensures that identical seeds always produce identical visual outputs.

The Core Algorithm in lib/contour.ts

The entire generation pipeline lives in lib/contour.ts and executes in five distinct phases, from entropy extraction to SVG markup emission.

Step 1 – Hash the Input Seed with SHA‑256

Lines 21‑25 prefix the input string with "pi-scribble-logo:" and digest it using crypto.subtle.digest('SHA-256', ...). The resulting 32‑byte array serves as the entropy source for all subsequent randomness.

Step 2 – Derive the π‑Stream Randomness Generator

Lines 27‑44 implement a deterministic RNG by mixing the hash bytes with hard‑coded π digits. The Next function yields floating‑point values in the range [0,1) and accepts a length argument to provide arbitrary precision when needed.

Step 3 – Select Geometric Parameters

Lines 47‑53 use helper functions pick and pickInt to translate raw random values into bounded parameters. These include stroke width, harmonic frequencies, amplitudes, phases, and radial offsets that define the contour’s irregular shape.

Step 4 – Build Sinusoidal Contour Paths

Lines 86‑117 generate eight concentric loops. For each loop, a base radius is perturbed by a sum of sinusoidal harmonics calculated as a function of angle. The resulting (x,y) coordinate pairs are converted into an SVG path string via a polyline helper.

Step 5 – Emit the SVG Markup

Lines 119‑122 wrap the generated paths in an <svg> element with a 256×256 viewBox and return the complete markup as a string, ready for embedding or download.

Generating Logos Programmatically

Import generateContour to create logos in any TypeScript or JavaScript context. The function returns a Promise that resolves to an SVG string.

import { generateContour } from '@/lib/contour';

async function makeLogo(name: string) {
  const svg = await generateContour(name, '#ff6600', {
    strokeWidth: 1.8,
    nonScalingStroke: true,
  });
  console.log(svg); // Embed directly in HTML or save to file
}

makeLogo('OpenAI');

Interactive React Playground

The ContourPlayground component in components/blocks/contour-playground.tsx provides a live UI. It sanitizes and debounces user input, invokes generateContour, and renders the output using URL.createObjectURL for instant preview.

import { ContourPlayground } from '@/components/blocks/contour-playground';

export default function Demo() {
  return (
    <section className="max-w-xl mx-auto">
      <h2 className="text-xl mb-4">Contour Logo Generator</h2>
      <ContourPlayground />
    </section>
  );
}

Exporting to SVG or PNG

Download the generated vector client-side by constructing a Blob and triggering a download anchor.

const svg = await generateContour('my-seed');
const blob = new Blob([svg], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'my-seed-contour.svg';
a.click();
URL.revokeObjectURL(url);

Summary

  • Deterministic output: The same seed always produces the identical SVG because the algorithm uses SHA‑256 hashing and a seeded π‑stream RNG.
  • Zero dependencies: All calculations use the native Web Crypto API and standard TypeScript, requiring no external graphics libraries.
  • Configurable styling: Optional parameters control stroke width (strokeWidth), color, and scaling behavior (nonScalingStroke).
  • Client-side only: Generation happens entirely in the browser, making it suitable for offline applications and privacy-sensitive environments.

Frequently Asked Questions

What makes the contour generation deterministic?

The algorithm prefixes the input with "pi-scribble-logo:", hashes it with SHA‑256 in lib/contour.ts lines 21‑25, and uses those bytes to seed a custom RNG. Because the hash and the π digit sequence are constant for a given input, the resulting random numbers—and thus the geometry—remain identical across every execution.

Why use SHA‑256 and π digits for randomness?

SHA‑256 provides cryptographic-grade entropy distribution from arbitrary strings, ensuring that even similar inputs produce wildly different hashes. The π digits serve as a publicly verifiable, infinite source of pseudo‑randomness that remains consistent across platforms, eliminating the need for external randomness or stateful generators.

Can I customize the stroke width and colors?

Yes. The generateContour function accepts an optional configuration object where you can specify strokeWidth as a number and the stroke color as a hex string. Passing nonScalingStroke: true ensures the stroke width remains constant when the SVG is scaled in the viewport.

Is the generation truly client-side without external services?

Yes. All processing occurs in the browser using crypto.subtle.digest and the custom Next RNG implemented in lib/contour.ts. No network requests are made after the initial page load, and the ContourPlayground component even supports rasterizing to PNG entirely within the client using canvas APIs.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →