Skip to content
Codense
Notes

Why this site draws its product UI instead of screenshotting it

We replaced every product screenshot on codense.eu with interface rendered in markup. What it cost, what it fixed, and where it is honest to do.

by Mathias Villadsen Decisions

Until this week the product pages on this site did what most product pages do: they showed screenshots. Five captures of Detectly, resized twice, lazy-loaded, and stacked one under another.

They were the weakest thing on the page, for reasons that took us a while to admit.

What was wrong with them

They existed for one product out of four. Detectly is live and has a UI to photograph. Diver, Deploy and Sentry are in various stages of build, so their pages had a heading that said "inside it" and nothing under it. A page that shows less for the products we are currently building is backwards.

They were already stale. The captures were taken from one release. Two releases later the incident timeline looked different, and the screenshot did not. A screenshot is a claim about how the product looks that stops being true on the next deploy — and nobody remembers to retake them.

They could not make the argument. Detectly's actual point is that an alert climbs the on-call chain by itself: warning, incident, escalation, recovery, without anyone driving. A still image of a timeline shows four dots. It cannot show the fourth one appearing.

They weighed something. 24KB each, times five, times two sizes. Not a disaster, but the only images on a page that is otherwise text and CSS.

What we did instead

Every product UI on the site is now markup. A live-panel component renders monitor rows with a breathing status dot and latency bars that fill. A status-strip draws seventy-odd uptime bars. An incident-timeline draws a spine and lights up four events in sequence. A terminal types out a deploy. A phone-frame wraps any of these in a CSS-drawn iPhone.

Two rules made this honest rather than decorative:

  1. Every figure that looks like data is either real content or explicitly labelled an illustration. The rows in the live panel come from the same content file that describes the product. The uptime percentage is computed from the bars, so the picture and the number cannot disagree. The aria-label on each panel says "an illustration of".

  2. Nothing moves unless the visitor is fine with movement. Every animation sits behind prefers-reduced-motion and behind a class the script adds only when it runs. With JavaScript off, or with reduced motion on, you get a finished, legible panel — never a hidden one.

What it cost

About two days. The components are roughly 400 lines of Blade and 200 of CSS between them, and they are reused: the same live-panel appears in the hero, inside product cards, inside the phone, and on the case study.

The screenshots are still on disk and the captions are still in the content files. Putting one back on a page is one line. We do not expect to.

Where this would be the wrong call

If the product's interface is the argument — a design tool, a dashboard whose layout is the point — a rendering in a different UI kit would misrepresent it. Ours are monitoring tools whose argument is behaviour over time, and behaviour is what markup can show and a screenshot cannot.

Next step

Tell us what is not working.

An hour on a call, no charge and no deck. We will tell you honestly whether this is work we are good at — and if it is not, who to talk to instead.

Reply within
One working day
First call
One hour, free
Notice period
One month, either way
Based in
Odense & Copenhagen