Designing in monospace: why this site uses Kode Mono
Why we set an entire website in a monospace font, what it costs in readability, how we compensate with size, spacing and line length, and why the font is self-hosted.
Every page on this site, including this one, is set in a monospace font called Kode Mono. Headings, body text, buttons, captions, the lot. Designing in monospace is an unusual choice for a website, and people ask about it, so here is why we did it, what it costs, and the small technical decisions that make it work.
The short version: we make desktop tools, security tools and apps for people who spend a lot of time in terminals and editors. A monospace face says that before you read a word. It also gives us a grid to design on for free. The price is some reading comfort, and we spend most of our design effort paying that price back.
What a monospace font actually gives you
In a monospace (or fixed-width) font every character has the same advance width. A lowercase i takes up exactly as much horizontal space as a capital M. Proportional fonts, which is almost everything you read, give narrow letters less room and wide letters more, because that is how our eyes like to see words.
Fixed width sounds like a limitation, and it is one, but it has side effects we like.
- Things line up without trying. If two lines have the same number of characters, they are the same length. Labels, numbers and short tables align in columns without any layout work, which is why programmers have always used these fonts for code.
- Numbers behave. Prices, dates, version strings and counters do not jitter when they change, because every digit is the same width. Proportional fonts need tabular figures switched on to do this. In a monospace font it is simply true.
- The page has a rhythm. Every line of text sits on an invisible character grid. You cannot see it, but you can feel the evenness, the way you feel the regularity of graph paper.
That last point is the one that sold us. The drawings in our journal use the same face, the same uppercase labels and the same dot grid as the pages around them, so a diagram and a paragraph feel like parts of one document rather than a picture pasted into an article.
Why Kode Mono
We tried a lot of monospace families. Many of them are designed for code first and look it: tall x-heights, very open shapes, sometimes a slashed zero and a dotted everything. They are excellent in an editor at 13 pixels and a bit clinical on a landing page at 70.
Kode Mono has a squarer, slightly engineered feel. The curves are tight, the capitals look good very large, and it has a variable weight axis from 400 to 700, so a single file covers both body text and bold headings. It is released under the SIL Open Font License, which means we can self-host it, subset it and ship it inside our own pages without asking anyone.
It is not perfect. The latin file we use has no glyph for a right arrow or an infinity sign, for example, so those characters fall back to whatever monospace font your system has. We mostly design around that by drawing arrows in SVG instead of typing them.
The readability trade-off
Here is the honest part. Monospace text is harder to read in long passages than a good proportional font. Words have less distinct shapes because every letter gets the same box. Narrow letters like i, l and t are surrounded by extra white space, and wide letters like m and w get squeezed. Over a few paragraphs your eye works slightly harder to group letters into words.
For a code listing that does not matter much, because you read code in small pieces. For a 1,500 word article it does. So we treat readability as a debt we took on deliberately, and we pay it down in four places.
Size
Body text on article pages is 16 pixels, dropping to 15 on small screens. Monospace fonts tend to look smaller than proportional fonts at the same size because the letters are narrower on average, so we would not go below that for running text. Captions and labels go smaller, but they are never more than a line or two.
Letter-spacing
Fixed-width fonts have generous spacing built in, since each glyph has to sit comfortably inside a box sized for the widest letter. Left alone, words start to fall apart into individual letters. We tighten body text slightly, by 0.03 em, and headings more, somewhere between 0.04 and 0.065 em depending on size. Big headlines need the most tightening. At 100 pixels the default gaps look like missing teeth.
Line length and line height
The body column is capped at 680 pixels, which works out to roughly 70 characters per line at our size and spacing. That sits in the range typographers usually recommend for comfortable reading, and in a monospace font it is easy to check: you can literally count. Line height is 1.7, a bit more open than we would use for a proportional face, because it gives the eye a clear path back to the start of the next line.
Uppercase for labels, sentence case for reading
Short labels, section markers, captions and navigation are set in uppercase. In monospace, capitals look precise and technical, and they are only ever a few words long. Anything you are meant to read at length is in normal sentence case, because a paragraph of monospace capitals is genuinely hard work. That split gives the page two voices: a terse one for finding your way around, and a normal one for reading.
Self-hosting the font
Early on the site loaded Kode Mono from Google Fonts with a link tag, like most sites do. It worked until it did not. One day the pages quietly rendered in the system monospace font instead, and because the fallback was also monospace, it was easy to miss. The site simply stopped looking like itself. That was the push to host the font ourselves, which we should have done from the start.
Now the font is one file served from our own domain. The setup is small enough to show in full:
@font-face {
font-family: "Kode Mono";
src: url("fonts/kode-mono-latin.woff2") format("woff2");
font-weight: 400 700;
font-style: normal;
font-display: swap;
}
A few details matter here.
WOFF2 only. Every browser we care about supports WOFF2, and it compresses much better than older formats. There is no reason to ship TTF or WOFF fallbacks in 2026.
One variable file. Because the font has a weight axis, the font-weight: 400 700 range lets one file serve regular, medium and bold. Separate static files would mean three downloads for the same letters.
Subsetting. The full family includes characters we never use. Cutting it down to the latin range brings the file to about 15 KB. If you want to do the same, the fontTools package has a subsetter that does it in one command, something like pyftsubset KodeMono.ttf --unicodes="U+0000-00FF,U+2018-201F" --flavor=woff2. Check the result carefully: subset too hard and a customer's name with an accent turns into a fallback glyph in the middle of a word.
font-display: swap. The browser shows text in a fallback font immediately and swaps in Kode Mono when it arrives. At 15 KB from the same server that usually happens before you notice. We prefer a brief flash of the wrong font to a blank page.
Caching. The font file is served with a one-year, immutable cache header. If we ever change the font, the file gets a new name.
Privacy and the content security policy
Self-hosting is also a privacy decision. When a page loads a font from a third-party service, the visitor's browser makes a request to that service, which sees their IP address and the page they are on. Whatever that service does with the data, it is a request our visitors did not ask for. Courts in Germany have ruled against sites for exactly this, and it was an easy thing to stop doing.
It also lets the site run a strict content security policy. Ours says font-src 'self', which means the browser will refuse to load a font from anywhere except our own domain. The same goes for styles and scripts. A site with no third-party requests is easier to reason about, which matters more to us than it might to most studios, given that we also build security tools. The CSP has one more effect on design: no inline style attributes are allowed, so even the SVG drawings on these pages use plain presentation attributes for colour and type.
Where monospace does not work
We would not recommend this for every site. A long-form publication, a shop with dense product descriptions, anything where people read thousands of words in one sitting: use a good proportional serif or sans and save monospace for code and small details. The personality you gain is real, but so is the reading cost, and that cost grows with the length of the text.
It also does not suit every language equally. Scripts with very wide or very narrow characters, or long compound words, can look uneven in a fixed-width grid, and our latin subset does not cover them anyway. If we ever translate the site, the font choice is one of the first things we would revisit.
For a studio site with short pages and a journal of posts around this length, it works. The same thinking carries over to how we like to design app interfaces, including our desktop apps: fixed-width type is good for paths, sizes and counts, and a system font is usually better for everything else. Numbers that line up are easier to compare, and a file path in monospace is easier to copy exactly.
If you are considering it, start with one test: set a full page of your real content in the font at your real sizes and read it on a phone. If you get to the bottom without noticing the font, the spacing is right.