The image was cached, but it still disappeared
The Binderdex homepage loads card art and feature screenshots through a shared image component. After shipping CDN caching for optimized images, I noticed something odd: warm reloads still showed empty gray surfaces for a split second before the art appeared. The bytes were already in the browser cache. The image was just refusing to paint.
The culprit was a loading-state class. The component hid every image with opacity-0 until an onLoad handler flipped it to opacity-100. That works fine on a cold load. But on a warm reload, React hasn’t hydrated yet when the browser paints the server-rendered <img> tag. The browser has the bytes in memory cache, but the onLoad handler that would reveal them hasn’t run, because React isn’t ready. So you get a flash of nothing for cached content.
Fix: trust the paint until it fails
Instead of hiding images by default and revealing them on load, keep them visible and only hide on error. Here’s the heart of the change in a shared LoadAwareImage component:
// Before: hide until onLoad confirms the load
status === "loaded" ? "opacity-100" : "opacity-0"
// After: trust the browser paint, hide only on failure
status === "error" ? "opacity-0" : "opacity-100"
That one-line flip fixed the flash. The server-rendered image paints immediately from cache, and React’s onLoad only matters if something goes wrong. The feature-deck screenshots also got fetchPriority="low" with loading="eager" so they start downloading right away without competing with the hero, and the hero switched from priority to a dedicated preload flag.
The broader lesson: a loading state that hides content is a liability on cached navigations. If your cache hit rate is high, you’re penalizing the common case to prettify the rare cold load. Default to visible, and let errors opt out.