RSS

// Parametric UI

This is a work-in-progress exploration of a concept. Check back to see how it evolves.

For the last few years a lot of my work has been about using machine learning to make products better to use and better for the business at the same time.

Lately I've been interested in what happens when a large language model answers in UI. Layouts, components, whole screens, in the place you'd normally get a paragraph of chat.

This experiment carries on from that. It's a product listing where nothing is fixed except the core design system. Every part of it is set by JSON parameters. If a component is just a set of values, anything that can write JSON can design with it. Including a model.

Ecommerce

The test subject is a marketplace product listing. Image, title, stars, price, a crossed-out price, a badge, a delivery date, a button. Every platform uses roughly the same parts. What changes is which ones show and how loud each one gets.

Teams tune these endlessly for conversion. Every change means a designer, a developer and a release. What ships is one fixed layout or a few for broad segments, but hyper-personalisation requires smaller segments, heading towards a layout per person.

A parametric component turns that around. Build and deploy it once. After that every change is a new set of values, so you can run as many experiments as you like, per context, without the quick fixes that pile up tech debt and bugs.

This experiment is one small component. Apply the same idea to clusters of components, or whole pages, and you get a UI system with near-infinite flexibility, constrained only where it matters to the brand. For automated optimisation, that's hugely powerful.

What does this mean for design?

A lot of small UI decisions move out of the design file. Which badge shows. How big the price is. Whether the stock warning sits above the button or below it. In a parametric component the model makes those calls at runtime, for every context it detects.

That sounds like it should worry designers. I think it moves them further up the chain, to the decisions that shape all the others.

The job becomes designing the system the model works inside, and how the model thinks. How should the UI react to context? What should a first-time visitor on a phone see, compared with a returning customer with a full basket? Which parameters exist, and what range each one gets. What has to stay true for the brand in every version.

The designer ends up thinking across many contexts at once, and building systems flexible enough to cope with all of them. The model handles the last mile, which is the part nobody should be hand-tuning anyway.

Avoiding the dark side

Designing the system also means deciding what's off limits. A model rewarded for conversion will find dark patterns faster than any growth team. Fake scarcity, countdown timers, discounts that shout. The Urgency preset below is one, and it took seconds to make. Every metric is a proxy, and I've written about what happens when you forget that in Perverse Incentives. The guardrails are design work too.

The Demo

In the spirit of learning by making, Claude and I built this to see how far one component could stretch. Design is better when you make your own tools.

Every part of the listing has three controls: visibility, size and rank. Change one and the listing rebuilds. Under the controls is the whole config as JSON. That's what the model would send to the front end to set up the UI at runtime.

I added presets because I love presets. Minimal, Basic, Full, Price-led and Urgency. It opens on Minimal. Urgency is the one that shouts. Randomise does whatever it likes, which shows how much range there is.

Parameters Click the listing to jump to its controls
Presets

Config

One component, millions of permutations.


        

Using this

Visibility shows or hides an element. Hide one and the listing closes up around the gap.

Size scales the element from XS to XL, roughly 0.6 to 1.7 times. The image scales its height. Everything else scales its type.

Rank decides the stacking order. Highest sits at the top. Drag one past another and they swap.

Background tints the listing. All the way left is plain white.

The colour swatches and the save button on the listing work too. Their state ends up in the config.

Let the model decide

This demo connects to Pan, the LLM running in my homelab. It's a live LLM integration. The model runs on my home hardware, so nothing leaves the house. Once the model has generated a layout for a specific context, it is cached to speed things up next time.

Same listing, but here Pan sets every parameter. Pick a shopper and it sends back a config, with a line on why it made each choice.

Then switch the brand guardrails off. The model is told to get the sale at any cost, and the rules that normally overrule it step aside. Flip between the two and compare.

Shopper
Guardrails

The model's reasoning
    What the guardrails changed
      
              

      To do

      • Import. Paste a config back in and the listing rebuilds from it.
      • Compare two configs side by side.
      • A grid of twelve listings sharing one config, to see what a setting does to a whole results page.
      • Rank only sets order right now. It could also nudge size and contrast, the way a real visual hierarchy does.
      • Let visitors describe their own shopper in a sentence, rather than picking from four.

      Changelog

      2026-09-28

      • Initial release: fifteen listing elements, each with visibility, size and hierarchy sliders. Layout sliders for card width, density, corner radius and button hue. Four presets plus Shuffle. Live JSON config with copy.
      • Moved over from a standalone prototype onto the site, with the site's own sliders, buttons and panels for every control. The listing keeps its marketplace look.
      • Parameters now sit directly under the listing, with the config below them.
      • Parameters box is half its old height and scrolls inside.
      • Presets stay fixed at the top of the parameters box while the sliders scroll.
      • Added a Background slider for the listing. Far left is plain white, the rest of the range tints it.
      • Elements and Layout now sit on tabs under the presets, so you switch between them rather than scrolling past one to reach the other.
      • Layout is now the first tab, and the one that's open when the page loads.
      • Renamed the Shuffle button to Randomise.
      • Fixed hidden elements still taking up space. Anything set to zero visibility left an invisible gap behind, which made Minimal look mostly empty.
      • Tightened Minimal's spacing a little.
      • Layout and Elements tabs now look like tabs. The open one joins onto the panel below it.
      • Split Elements into four tabs: Product, Price, Persuasion and Conversion.
      • Minimal is now the first preset, and the one the listing opens on.
      • Rewrote the intro around where this comes from: AI that answers in UI, and a front end where everything but the design system is a parameter.
      • Added a wireframe animation of the listing moving through the presets at the top of the page.
      • Width and density are now S, M, L and XL buttons rather than sliders, and show up in the config as those sizes. Hue is now called CTA colour. Randomise now admits it's for fun.
      • Density now also scales the spacing inside each element: badge and pill padding, button padding, and the gaps in the rating, discount, voucher and colour rows.
      • Added an XS width. Density's L and XL steps are more dramatic now.
      • Marketplace is now Full. Added Basic in between Minimal and Full: image, title, stars, price, RRP, delivery and the button.
      • Visibility is now a pair of Visible / Hidden buttons on every element rather than a slider. The config drops opacity and keeps visible.
      • Element size is now XS, S, M, L and XL buttons rather than a slider, and the config shows the size name.
      • Added a "What does this mean for design?" section.
      • Took the wireframe animation off the top of the page.
      • Rewrote the text above the tool: the point up front, plainer ecommerce section, and a paragraph on dark patterns and guardrails.
      • Renamed the Hierarchy slider to Rank. In the config, hierarchy is now rank, and the old rank (where it ends up in the stack) is now position.
      • Added "Let the model decide": pick a shopper and a model running at home sets the whole listing, explains its choices, and brand guardrails overrule it where they need to. Switch the guardrails off to compare.

      I'd love to tell you more. Let's work together.