Cover
moco/coverFreeComponent
Deterministic FNV-1a-seeded generative SVG cover art in three variants: curves, blocks, bars.
Live preview
live · rendered by the registry
Rendered by moco on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://mocoui.site/r/cover.jsonSource
1import * as React from "react";2import "./cover.css";34/**5 * Deterministic generative cover art. The same seed always draws the same6 * SVG — hashing is FNV-1a, randomness is a seeded PRNG, never Math.random.7 * Three variants: curves, blocks, bars. Strokes are non-scaling, so the same8 * artwork reads at 640px and at 150px.9 */1011const W = 640;12const H = 280;1314export interface CoverProps {15 /** Usually the post slug. The same seed always draws the same cover. */16 seed: string;17 alt: string;18 /** Force a variant (0 curves, 1 blocks, 2 bars). Defaults to seed-derived. */19 variant?: 0 | 1 | 2;20 className?: string;21}2223/** FNV-1a. Stable across builds, unlike anything involving Math.random. */24function hash(s: string): number {25 let h = 0x811c9dc5;26 for (let i = 0; i < s.length; i++) {27 h ^= s.charCodeAt(i);28 h = Math.imul(h, 0x01000193);29 }30 return h >>> 0;31}3233/** mulberry32 — tiny seeded PRNG, deterministic across engines. */34function rng(seed: number): () => number {35 let s = seed >>> 0;36 return () => {37 s = (s + 0x6d2b79f5) >>> 0;38 let t = Math.imul(s ^ (s >>> 15), 1 | s);39 t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;40 return ((t ^ (t >>> 14)) >>> 0) / 4294967296;41 };42}4344/* One accent stroke per composition; supporting strokes stay quiet. */45const TONES = ["var(--moco-faint)", "var(--moco-warn)", "var(--moco-ink)"];46const DASHES = ["2 4", "7 5", "12 4 3 4"];4748/** Smooth open path through points via quadratic midpoint segments. */49function smoothPath(pts: [number, number][]): string {50 const d = [`M${pts[0][0].toFixed(1)},${pts[0][1].toFixed(1)}`];51 for (let i = 1; i < pts.length - 1; i++) {52 const [x, y] = pts[i];53 const mx = (x + pts[i + 1][0]) / 2;54 const my = (y + pts[i + 1][1]) / 2;55 d.push(`Q${x.toFixed(1)},${y.toFixed(1)} ${mx.toFixed(1)},${my.toFixed(1)}`);56 }57 const last = pts[pts.length - 1];58 d.push(`L${last[0].toFixed(1)},${last[1].toFixed(1)}`);59 return d.join(" ");60}6162/** Variant 0 — gridlines and a family of drifting curves, one in accent. */63function Curves({ seed }: { seed: number }) {64 const r = rng(seed);65 const rules = 3 + (seed % 3);66 const curves = 3 + Math.floor(r() * 2); // 3–4 quiet curves + 1 accent67 const steps = 9;6869 const makeCurve = (drift: number) => {70 let y = 56 + r() * (H - 140);71 const pts: [number, number][] = [];72 for (let i = 0; i < steps; i++) {73 pts.push([32 + ((W - 64) * i) / (steps - 1), y]);74 y += (r() - 0.5 + drift) * 44;75// … truncated
What it pulls in
Other registry items
Files it writes
More from moco
All 20 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Codecode | moco | Components | Free | 1 dep · 3 files | |
| Comparecompare | moco | Components | Free | no deps · 2 files | |
| Count Upcountup | moco | Components | Free | no deps · 2 files | |
| Diagram Kitdiagram | moco | Components | Free | no deps · 2 files | |
| Dot Griddotgrid | moco | Components | Free | no deps · 2 files | |
| Figurefigure | moco | Components | Free | no deps · 2 files | |
| Hookshooks | moco | Components | Free | no deps | |
| Islandisland | moco | Components | Free | no deps · 2 files |
