/writing
Replacing Astro Image for a Documentation Site
· 3 min read
I started a docs site with Astro’s Image component, because the defaults are good and the Sharp integration is already wired. After a few months at scale, I took it out.
The problems were not really Astro’s fault. They came from an abstraction that has to serve every kind of content site being applied to one with very specific needs. Working out the size of remote images was the slowest step in the build. Tables with images in them fought the wrapper’s layout. Adding width and height back so table cells rendered correctly became a recurring fix. The wrapper’s padding and aspect-ratio behavior made sense for a blog hero and no sense at all for a small inline diagram.
The scale is what turned an annoyance into a decision. Around fifteen hundred images sit across more than five thousand pages, and they are not one kind of image. Hero shots, screenshots pulled from remote URLs, diagrams inside table cells, and dozens of tiny inline icons all went through the same component with the same assumptions.
The custom wrapper
The replacement takes a source path, renders an image tag, and gets out of the way. Local images get their dimensions from Sharp’s metadata function, called once at build. Remote images skip the inference entirely and let the browser handle it, with explicit loading, decoding and fetch priority set so above-the-fold images still arrive fast.
The whole component ended up smaller than the configuration block I had been writing for Astro Image. It covers the cases the docs actually have and stops covering the ones they do not.
When generic costs more than specific
Every shared abstraction has a point where it stops paying for itself. The signal is that you start fighting it: overrides, workarounds, conditional imports. Each override is the abstraction telling you it does not fit. After the third or fourth, writing the small specific version is usually cheaper.
I am not against Astro Image. For a content site with a uniform shape it is the right default. For a docs site with mixed content, diagrams inside tables, remote screenshots and dozens of inline icons, bending it cost more than replacing it.
What I learned
The strength of an abstraction is that it handles many cases at once. The weakness is that it handles them all the same way. When your content varies more than the abstraction expects, stop fighting it and write the small thing that fits.
More writing
Caching Sharp-Processed Images in Static Builds
How I cut documentation build times by hashing image inputs, committing the preprocessed webp outputs, and skipping image work on every CI run.
· 3 min read
Cutting Backend CI by 76%
A Django test pipeline went from a median of 18.5 minutes to 4.5. Almost none of it came from making tests faster. The last part was a connection budget.
· 6 min read
Designing URLs for a Printed QR Code
A QR code printed in a book can never be reprinted. How that constraint shaped number-keyed routes, an owned domain, and QR codes pinned to a hardcoded origin.
· 2 min read