Colophon
How this site and the mark at the top of it are made.
The mark is a picture of my voice
Not a font, not a shape drawn in Figma, not stock soundwave clip art. It is the amplitude envelope of me speaking, measured sample by sample and drawn as vector art. Press play and you hear the recording the bars are drawn from.
The pipeline is four steps and lives in a separate repo. Read the WAV, take the absolute value, crop the dead air, smooth, downsample to a fixed number of points, normalize to 0 through 1. That is the loudness curve. Turn the curve into centered mirrored bars in a unit box, with no color and no pixels yet. Draw those same numbers as SVG and as PNG, so the vector and the raster are the same shape rather than one being a screenshot of the other. Because the math is pure and the output carries no timestamps, the same WAV always produces the same file. A test builds it twice and compares hashes.
The site does not redraw any of that. It imports the envelope as data and ports one function, the bar geometry, to TypeScript. Signal processing stays in Python where it has numpy and a test suite.
Nine bars is a barcode
Drag this down and watch the waveform stop being a waveform. Around nine or ten bars it flattens into a picket fence: every bar is roughly the same height and the shape that made it read as audio is gone.
hover a bar
That is not a styling problem, it is aliasing. Each bar is the loudest sample in its slice of the recording, and speech chopped into nine slices is close to uniformly loud. The dynamics that make a waveform legible live at a finer resolution than nine bars can hold. The square glyph in the wavemark repo has exactly this problem, and the fix is not fewer bars, which is what the README used to suggest.
Turn on show the dead air and the greyed bars are what the trim step removes: 0.89 seconds of near silence before I start talking. The bars describe the trimmed window, so the audio has to be cut to the same window or playback drifts almost a full second ahead of the highlight.
One caveat, since the whole point of this thing is that nothing is faked: the slider downsamples a 512-point envelope in your browser. The committed marks are generated from the raw PCM, and the two are very close but not bit-identical, because bin boundaries do not always line up and the smoothing was applied at this resolution. The mark you see at the top of the site is the real one, at 64 bars.
Color, with the red-green axis left out
I am red-green colorblind, so the palette never leans on hue to carry meaning. The whole thing sits on the blue axis plus neutrals, and contrast is carried by brightness, which is the channel I read reliably.
#3B9EFF
Signal Blue. The flat waveform, and the accent in dark mode
#1A4A80
Gradient base. Bottom of the large-asset gradient, and the accent in light mode
#9CCBFF
Gradient tip. Top of the gradient on banners and the wide lockup
#0A0A0B
Near black. Asset background, and the ink knockout on light surfaces
Signal Blue is the mark everywhere, but it cannot be the link color on a light background. Measured against this site's backgrounds, #3B9EFF lands at 2.7:1 on light, which fails WCAG AA for text, and 6.9:1 on dark, which passes. So light mode uses the gradient base instead, at 8.6:1. Two blues, one palette, picked by contrast rather than taste.
Small assets get the flat accent and large ones get the gradient, because a gradient is invisible at 24px. That 24px square is also the gate the glyph has to survive, and the repo renders a preview at exactly that size to check.
The site
Next.js 16 with the App Router, React 19, TypeScript, and Tailwind CSS v4. Posts are MDX compiled at build time, highlighted by Shiki through rehype-pretty-code. Type is Inter, self-hosted by next/font. Hosted on Vercel, deployed by GitHub Actions on every push to main. Icons are inline SVG with paths from simple-icons, because lucide does not ship Mastodon, Bluesky, or Threads.
Every string of personal copy lives in a typed data module rather than in JSX, which is how the mark, the homepage, and the meta description all read from the same source instead of drifting apart.
Regenerate it
The identity is one recording. Swap the file and rebuild, and the glyph, the banners, the favicon, and the mark on this page all change together.
make decode SRC=audio/new-take.m4a # → audio/source.wav make all # every asset, then the tests make export-web # the envelope this page draws
Which is also why the recording here says something slightly different from the line on the homepage. The bars are a picture of whichever take is current, and this one is already the mark on every social profile. Re-recording to match the copy would change the shape everywhere and invalidate all of them, so the clip stays put.