How a Hyvä component is built.

How a Hyvä component is put together: the Alpine and Tailwind patterns the theme expects, and the ones that fight it.

The component generator is being rebuilt. Send a brief and the answer comes back written, with the workings.

Hyvä components are Alpine and Tailwind, and nothing else

A Hyvä storefront ships no jQuery, no Knockout, no RequireJS and no UI components. A component is a .phtml template with Tailwind utility classes for the styling and an Alpine.js x-data block for the behaviour, and that constraint is the whole point: the browser downloads a few kilobytes of Alpine instead of several hundred of Magento's frontend stack.

So the first question about any component is not how to build it but how little JavaScript it can carry. A disclosure, a tab set, a quantity stepper and a filter panel are all Alpine state and a class binding. Reach for a framework component and you have reintroduced the weight Hyvä exists to remove.

The four patterns that cover most of a storefront

State on the element that owns it. x-data goes on the outermost element of the component, not on a wrapper shared with its neighbours, so two instances on one page never share state. A product card with its own quantity field is its own x-data island.

Show and hide with x-show, not with a class you toggle by hand. x-show keeps the element in the DOM and flips display, x-if removes it. Use x-if only when the hidden branch is expensive or must not exist for accessibility.

Bind classes, never build class strings. :class with an object literal keeps the conditional styling readable and keeps Tailwind's scanner able to see every class name. A class assembled from string fragments at runtime is invisible to the build and gets purged.

Talk between components with events, not globals. $dispatch sends an event up, x-on listens for it, and Alpine's $store holds the handful of things that are genuinely page-wide, such as the cart drawer's open state.

What fights the theme

Arbitrary values everywhere. Tailwind lets you write a one-off pixel value in square brackets, and a component built entirely from them has opted out of the design system. Use the theme's scale, and extend the scale when the scale is wrong.

Layout XML doing a template's job. Hyvä keeps Magento's layout system, so it is tempting to solve a rendering problem by moving blocks in XML. A component that only makes sense after three layout instructions is a component nobody else on the team can move.

Server round-trips for state the page already has. Magento's default is a customer-data request for almost everything; Hyvä's private-content handling is deliberately narrower. Read from the section data you already loaded before adding a request.

Porting a Luma widget class for class. The markup Luma emits assumes Knockout bindings and its own CSS cascade. A port that keeps that structure inherits the weight without the behaviour. Rebuild the component from what it does, not from what it looked like.

Before it ships

Check it with JavaScript disabled: the content should still be there and readable, with only the interaction missing. Check it at 390 pixels, where most storefront traffic actually is. Check that every interactive element is reachable by keyboard and shows a focus ring, because Alpine will happily make a div behave like a button without making it one. And check the Tailwind build output for the classes you expect, so nothing was purged.

Send a brief. Get a written quote in 24 hours.

Two paragraphs is enough: scope, price and timeline come back in writing.