Getting Started
Templates
Blocks
Components
For solo developers, indie hackers, and freelancers shipping their own products. Pay once, keep everything forever.
Instant download · No subscription · Lifetime access
For small teams, agencies, and freelancers shipping multiple client products. Lifetime access for everyone on your team.
Instant CLI token for 5 seats · Onboarding included · Invoice on request
A social-proof CTA block that scatters a pool of customer avatars across a tight cell grid to form an organic silhouette, then settles into a centered two-line headline and a primary / secondary CTA pair. Built for "trusted by thousands" moments at the bottom of a marketing page.
Key Features:
seeddata-cta-mosaic="in" attribute toggle — no JS animation runtime, no motion dependencyname · role as a muted caption beneathmix-blend-luminosity over a pale slate gradienttitle + titleAccent) in matching sans-serifmin(20px, calc(...)), so the mosaic always fits its container without overflowprefers-reduced-motion| Prop | Type | Default | Description |
|---|---|---|---|
avatars | (string | { src: string; name?: string; role?: string; quote?: string })[] | 40 named placeholder avatars | Pool of avatars. Object form enables the message-bubble tooltip on hover. |
title | string | "The CRM behind" | Leading headline line. |
titleAccent | string | "thousands of companies." | Trailing line that wraps beneath the title in the same font. Pass empty string to omit. |
description | string | undefined | Optional supporting copy beneath the headline. |
primaryCta | { label, href? } | null | Start for free | Primary CTA. Pass null to hide. |
secondaryCta | { label, href? } | null | Talk to sales | Secondary CTA. Pass null to hide. |
rows | number | 11 | Number of mosaic rows. |
cols | number | 56 | Number of mosaic columns. Cell size scales fluidly to fit the container, capped at 20px. |
density | number | 0.99 | Density of the solid top mass (0..1). At 0.99 only ~5 random patches appear across the wall; lower values dial up patch count. |
taperStart | number | 0.5 | Fraction of rows (0..1) before the edge-tail taper begins. |
seed | number | 7 | Deterministic seed — change to reshuffle the silhouette. |
className | string | undefined | Additional CSS classes on the outer <section>. |
Each avatar tile is interactive. On pointer enter the tile scales up by ~12% so the user has clear feedback — but the tile stays grey; we never flash to full color. When the avatar was supplied with a quote and/or name, a single shared chat-bubble tooltip anchors above the hovered tile (or below if there isn't enough room above the section's padding):
name · roleThere is exactly one tooltip DOM node serving every tile, controlled by a single piece of state. Position math anchors it to the hovered tile's getBoundingClientRect, with horizontal clamping against the section width and automatic above/below flipping. The bubble itself uses max-width instead of fixed width so short quotes stay tight and long quotes wrap to the cap.
The mosaic is generated from a deterministic PRNG (mulberry32(seed)). Two regimes:
Top mass (rows above taperStart): uniform density with a sharp cNorm^7 * 0.55 edge fray confined to the last few columns.
Edge-tail taper (rows below taperStart): density at column c, normalized to cNorm ∈ [0,1] (0 at center, 1 at edges), is a mix of two falloffs:
centerFalloff = max(0, 1 - fade - 0.25)^5 + 0.015 // shifted curve + 1.5% baseline
edgeFalloff = (1 - fade)^0.7 + cNorm^6 * 0.05 // dies slowly + tiny floor
edgeWeight = cNorm^4 // edge curve dominates only outside cNorm ~0.7
probability = density * (centerFalloff * (1-edgeWeight) + edgeFalloff * edgeWeight)
Two structural choices in centerFalloff:
-0.25 shift kills the bulk of the middle scatter. Without it, the row directly under the wall still has ~33% center probability, producing a visible scatter band.+ 0.015 baseline keeps a slight 1.5% probability of center tiles all the way to the last row, so the middle is sparse rather than literally empty. The baseline is multiplied by (1 - edgeWeight) downstream, which goes to zero at the edges — so it only adds scatter to central columns, never the tails.This produces the two organic "tails" that drape down at the left and right while the middle hollows out into the masked bottom.
Every tile shares the same paint trick: parent has a slate gradient background, image uses mix-blend-luminosity. The image contributes only its lightness; hue and saturation come from the parent. Result: every face — regardless of source skin tone, lighting, or saturation — settles into the same monochromatic family.
taperStart to ~0.4. More rows participate in the edge-vs-center split, so the tails extend further down.density to ~0.85. A few visible holes in the dense mass.cols to ~72. The mosaic gets wider in proportion to its container.seed; the layout is stable per seed so server and client render identically.Drop this near the bottom of a marketing or pricing page where you'd otherwise reach for a logo cloud. It works best when you have access to a real avatar set (customers, design partners, beta users) — the more varied the avatars, the more organic the silhouette feels.