Note · · 4 min
The fonts nobody saw
For weeks, every visitor to this site rendered in fallback fonts, and every check I had said the fonts were fine. How a curl that returns 200 can lie to you, and what I verify now.
This site is built around three typefaces. For a few weeks after launch, not one visitor saw any of them. Every check I had told me the fonts were fine. They were not, and the reason they looked fine is the whole point of this note.
The symptom I could not see
The site loads its fonts from its own server, no third party. Locally it looked exactly right. After I shipped it, I ran the check I thought closed the question: I requested one of the font files over the network and got back a clean 200 OK. The file was there, the server served it, done. Except a visitor on the live site was reading everything in their system default font, and had been the whole time.
I only found out because I opened the deployed site in a real browser and looked at the console, where a stack of Content Security Policy violations was quietly refusing to load every font file.
Trap one: a 200 is not a render
A command-line request for a file asks one question: is this file here. The answer was yes. But a browser asks a second question the command line never does: am I allowed to use this file, under this page's security policy. The Content Security Policy is enforced by the browser and nothing else. So my request could sail through with a 200 while a real browser, holding the same file, threw it on the floor for a policy reason my check had no way to see.
The lesson is narrow and permanent: to know a font renders, you have to watch a browser render it. Nothing short of that is evidence.
Trap two: the fix was in a file that does nothing
The security policy lived, correctly, in a config file in the repo. The catch is how this site deploys. It ships as a Cloudflare Worker serving static assets, and that particular config file is a feature of a different Cloudflare product. On a Worker deploy it is not wrong, it is ignored. The real policy the browser enforced came from a rule in the Cloudflare dashboard, and that rule still carried an older policy that never allowed the fonts. I had been editing a file with no effect and trusting it because it said the right thing.
What I do now
Two habits came out of this, and I apply them to anything that reaches production:
- Verify the deployed thing, in a browser, as a user sees it. For fonts specifically I read
document.fontson the live domain and confirm every entry saysloaded, noterror, and I check the console for policy violations. A file returning200is not on the list of things I will accept as proof. - Know which config your host actually reads. A file that is authoritative on one platform can be dead weight on another. If a setting matters, I confirm it is live where the request is actually served, not where it looks tidy in the repo.
The bug was invisible because every tool in my loop agreed with me. The fix was to add the one check that could disagree.