Studio Smith-Cordell
Studio Smith-Cordell
The colour you can't see (yet): engineering a Display P3 image pipeline

The colour you can't see (yet): engineering a Display P3 image pipeline

For a cocktail bar whose menu is called Colour Has Flavour, shipping images that quietly threw away a third of the visible colour spectrum wasn't an option. Here's how we built a pipeline that gives every supported screen the widest colour it can actually show.

Most websites lie to your screen a little. Not maliciously — just by default. Almost every image on the web is encoded in sRGB, a colour space designed in 1996 for CRT monitors. It was a sensible standard at the time, and it’s still a perfectly reasonable one for most sites. But it covers a noticeably smaller slice of colour than modern displays can actually produce.

Since around 2015, Apple has shipped Display P3 panels across iPhones, iPads and Macs, and P3-capable screens are increasingly common elsewhere too. P3 covers roughly 25% more visible colour than sRGB, mostly in the reds and greens — exactly the range that makes a slice of blood orange or a sprig of basil look alive rather than flat. If your image pipeline flattens everything to sRGB before it ever reaches the browser, none of that headroom gets used, no matter how good the display is.

For most projects, that’s a fine trade-off. Nobody’s cocktail order hinges on it. But Cato isn’t most projects.

Why this client, why this detail?

Cato is a high-end cocktail bar built almost entirely around colour. Their brand photography is vivid, close-up cross-sections of ingredients — the kind of shots where colour is the subject, not a supporting detail. Their current menu, Colour Has Flavour, is a synesthesia-inspired concept where the drinks are organised and described by colour and the sensations it evokes. If there was ever a brief where “the site should render the truest colour possible” was a legitimate technical requirement rather than an indulgence, this was it.

So we built something most sites don’t need: an image pipeline that unlocks the full P3 gamut on displays that support it, while still serving perfectly correct sRGB to everything else.

Getting P3 in at the source.

Colour management is only as good as its weakest link, and the weakest link is usually right at the start. It doesn’t matter how carefully you handle colour in code if the source image was already clipped to sRGB during export. So before writing a line of the pipeline, we spoke with Cato’s photographers and asked them to export their edited RAW files with a Display P3 profile rather than the sRGB default most editing software assumes. It’s a small workflow change — one export setting — but it’s the difference between capturing the wider gamut and inventing it after the fact, which doesn’t really work.

The pipeline.

The site itself is a SvelteKit application on Cloudflare’s edge network, with an R2 bucket for storage and a Postgres database. The upload flow is straightforward: an image lands in R2, a record is written to the database, and a request goes out to a separate image transformation service with the details of the original.

That service is a small Hono application running on a VPS. It fetches the original, and produces a full set of responsive variants — JPEG and WebP, each in both P3 and sRGB — before writing them back to R2 and marking the database record that transformation is complete. Generating both gamuts, rather than just P3, matters just as much as the P3 work itself: a P3 image sent to a display that doesn’t support it can render with dull or shifted colour, so the sRGB set isn’t a fallback in name only — it has to be a properly graded, correct version in its own right.

Because this transformation happens asynchronously, the site’s image component checks whether formatting is done. If it isn’t yet, it shows the original upload as-is, so editors see their image immediately rather than a broken state. Once processing completes, the component renders a full <picture> element with every variant available, and lets the browser choose.

Letting the browser decide.

The actual mechanism for gamut selection is a single CSS media feature: color-gamut. Inside the <picture> element, <source> tags carry a media="(color-gamut: p3)" query alongside the usual type and srcset attributes. A browser on a P3-capable display matching that query will pick the P3 source; everything else falls through to the sRGB sources, exactly as <picture> was always designed to work with format and resolution. No JavaScript, no user-agent sniffing, no risk of serving the wrong image to the wrong screen. The browser already knows what its display can do — the job was just giving it the option.


<picture>
  <!-- 1. Display P3 WebP (Best quality + Wide Color for modern displays) -->
  <source
    type="image/webp"
    media="(color-gamut: p3)"
    srcset="
      /images/hero-p3-400w.webp 400w,
      /images/hero-p3-800w.webp 800w,
      /images/hero-p3-1200w.webp 1200w
    "
    sizes="(max-width: 768px) 100vw, 1200px"
  />

  <!-- 2. Standard sRGB WebP (Modern format, standard color space fallback) -->
  <source
    type="image/webp"
    media="(color-gamut: srgb)"
    srcset="
      /images/hero-srgb-400w.webp 400w,
      /images/hero-srgb-800w.webp 800w,
      /images/hero-srgb-1200w.webp 1200w
    "
    sizes="(max-width: 768px) 100vw, 1200px"
  />

  <!-- 3. Display P3 JPEG (Legacy browser/device with wide-gamut screen) -->
  <source
    type="image/jpeg"
    media="(color-gamut: p3)"
    srcset="
      /images/hero-p3-400w.jpg 400w,
      /images/hero-p3-800w.jpg 800w,
      /images/hero-p3-1200w.jpg 1200w
    "
    sizes="(max-width: 768px) 100vw, 1200px"
  />

  <!-- 4. Default Fallback (sRGB JPEG for ultimate compatibility) -->
  <img
    src="/images/hero-srgb-1200w.jpg"
    srcset="
      /images/hero-srgb-400w.jpg 400w,
      /images/hero-srgb-800w.jpg 800w,
      /images/hero-srgb-1200w.jpg 1200w
    "
    sizes="(max-width: 768px) 100vw, 1200px"
    alt="Cocktail served at Cato bar"
    loading="lazy"
  />
</picture>

Was it worth it?

Almost certainly not, in any strict cost-benefit sense. It added a second full set of generated variants, extra transform time on every upload, and genuine complexity to a pipeline that could have shipped in an afternoon without it. Nobody visiting the site consciously notices “ah, wider gamut.” If anything, the win is invisible by design — which is either the best or worst kind of engineering effort, depending on your mood that day.

But invisible isn’t the same as unimportant. For a brand built entirely on the idea that colour carries meaning, serving a slightly duller version of every photograph would have been a small, constant betrayal of the concept — one nobody could quite put their finger on, but everyone would feel. Colour Has Flavour deserved to actually taste of something. The pipeline is a bit of engineering nobody will ever be told about, in service of a detail that, for this client, was never really optional at all.