# Colophon

How henri.dev is made: the technologies, typefaces, design decisions, and principles behind this site.
## Why

I started tinkering with web dev in the early 2000s. The golden age of Java applets, blogrolls, and hand-curated RSS feeds. Then MySpace exploded, Facebook followed, and the open web quietly gave way to walled gardens. By 2010, I had traded my RSS collection for podcasts ([The B\&B Podcast](https://shawnblanc.net/2011/02/thebbpodcast/), [ATP](https://atp.fm/), [The Prompt](https://www.relay.fm/prompt), [The Talk Show](https://daringfireball.net/thetalkshow/)…) and Twitter, consumed through apps like [Twitterrific](https://en.wikipedia.org/wiki/Twitterrific), [Tweetbot](https://en.wikipedia.org/wiki/Tweetbot), and later [Spring](https://apps.apple.com/app/spring-for-twitter/id1508706541). These third-party clients had pulled Twitter's entire ecosystem upward, pioneering patterns like the sidebar navigation and [pull-to-refresh](https://en.wikipedia.org/wiki/Pull-to-refresh) (introduced by Tweetie) that Apple itself would eventually adopt.

The decline was slow, then sudden. API restrictions gradually crippled third-party clients, reserving features like polls for the official app. Then the acquisition happened, and the shit show began: walking into HQ carrying a sink (“let that sink in”), the glowing 𝕏 sign on the roof keeping neighbors awake, blue checkmarks force-gifted to [people like Stephen King and LeBron James](https://ktla.com/entertainment/elon-musk-pays-for-lebron-james-stephen-king-and-william-shatners-twitter-check-marks/) who had publicly announced they wanted nothing to do with them. Then API pricing went through the roof, killing third-party clients for good and forcing everyone onto the dreadful official app. What had been my primary tech discovery tool turned into a swamp of OnlyFans bots, clickbait trends and engagement farming, and unabashed fascist rhetoric.

Everyone scattered: some to Mastodon, others to Threads, others to Bluesky. Some influencers, regrettably, stayed on Twitter, while the rest split between Fediverse advocates and AT Protocol converts. Out of the wreckage, a collective realization emerged: no matter how much you love a platform, owning your data and controlling your own distribution is priceless. Personal websites started making a comeback.

> The best time to buy a domain was 20 years ago. The second best time is today.
>
> — Jim Nielsen

Owning a personal site had always been a fantasy. I could never quite find the legitimacy to publish. But what was once a daydream became a necessity. An intrinsic need to write took hold, and to do it properly, I needed a medium that my perpetually unsatisfied temperament could be proud of.

## Technology

This site is built with [Next.js](https://nextjs.org/) (App Router) and [TypeScript](https://www.typescriptlang.org/). Content is authored in [MDX](https://mdxjs.com/): Markdown with embedded React components.

MDX is what makes this site more than a blog. Every page can mix prose with custom React components. Here are a few, rendered live with their props:

The markdown processing pipeline is built on [unified](https://unifiedjs.com/) with [remark](https://github.com/remarkjs/remark) (parsing, GFM, math) and [rehype](https://github.com/rehypejs/rehype) (KaTeX rendering, slug generation, autolinked headings, smart quotes, em dash handling). MDX rendering is handled by [next-mdx-remote-client](https://github.com/ipikuka/next-mdx-remote-client), and syntax highlighting by [Sugar High](https://github.com/huozhi/sugar-high).

Code quality is enforced by [Oxlint](https://oxc.rs/) and [Oxfmt](https://oxc.rs/) (Rust-based linting and formatting that run in milliseconds) with [Husky](https://typicode.github.io/husky/) pre-commit hooks to keep things honest.

## Typography

Three typefaces, each with a role:

* **[Roobert](https://displaay.net/typeface/roobert/)** for headings. A geometric sans-serif with personality.
* **[PP Neue Montreal](https://pangrampangram.com/products/neue-montreal)** for body text. A neo-grotesque. I've always been drawn to grotesques, and this one strikes the right balance: clean and legible, but quietly distinctive.
* **[Geist Mono](https://vercel.com/font)** for code. Designed for terminals and editors.

## Design

Dark theme, always. The layout is built on a CSS Grid breakout pattern inspired by [Ryan Mulligan](https://ryanmulligan.dev/blog/layout-breakouts/) and [SmolCSS](https://smolcss.dev/#smol-breakout-grid). Instead of wrapping content in a constrained container and then fighting to let certain elements escape it, every child sits on a grid with named columns (`content`, `popout`, `feature`, `full`) and picks the width it needs. Code blocks pop out to `popout`, hero visuals stretch to `full`, and prose stays in `content`. No max-width hacks, no negative margins. Styled with [Tailwind CSS](https://tailwindcss.com/) and [shadcn/ui](https://ui.shadcn.com/).

Every visual on this site is pure code: CSS, [Three.js](https://threejs.org/), Canvas. No AI-generated images, no stock photography. Animations are handled by [Motion](https://motion.dev/) with a custom staggered animation system.

## Content

Every piece is hand-written, in both English and French. AI is used for proofreading, never for drafting or actual writing. The full reasoning behind this is on the [/ai](/ai) page.

The site supports bilingual content with locale-based routing, language switching, and alternate `hreflang` tags. Syndication is available via Atom feeds in both languages ([English](/feed.xml) and [French](/fr/feed.xml)).

Every page also responds to the `Accept` header: request `text/markdown` or `text/plain` and you'll get a clean markdown version instead of HTML, with custom components converted to plain-text equivalents through a dedicated remark plugin.

## Hosting and privacy

Hosted on [Vercel](https://vercel.com/). Analytics are provided by [Vercel Web Analytics](https://vercel.com/docs/analytics) and [Speed Insights](https://vercel.com/docs/speed-insights): anonymous, cookie-free, and compliant by design. No personal data is collected. Full details on the [/privacy](/privacy) page.

> This is a [/colophon page](https://slashpages.net/#colophon). [See all slash pages](/slashes).
