← Back to blog

Hyvä Compatibility Modules: Make Luma Extensions Work

Rodrigo Biazzi

On almost every Hyvä project the theme is the easy part. The real work is the list of third party extensions that add something to the storefront and were written for Luma. Each of them ships RequireJS modules, jQuery widgets or Knockout templates that do nothing on a Hyvä page. This article explains how compatibility modules work, how to decide between using one, writing one, or falling back to Luma, and how to write your own when nothing exists.

Why Luma extensions break on Hyvä

An extension usually has two halves. The backend half (models, plugins, observers, admin configuration, cron, API) does not care about the theme and works on Hyvä unchanged. The frontend half is the problem. It typically includes:

  • Templates that use data-mage-init or x-magento-init to start a JavaScript widget.
  • RequireJS modules and requirejs-config.js mixins.
  • Knockout templates and UI components, especially for anything in the mini cart or checkout.
  • LESS files that hook into the Luma style pipeline.

Hyvä does not load RequireJS, jQuery or Knockout, and does not compile LESS. So the HTML renders but nothing reacts to the user, and the styling is missing. Sometimes the template itself is fine and only the script is dead. Sometimes the template contains Knockout bindings and renders raw.

The three options for each extension

  1. Use an existing compatible version. Many vendors now ship Hyvä support, either inside the main package or as a separate compat package. There is also a community maintained set of compatibility modules for popular extensions. Check the Hyvä compatibility information on hyva.io and ask the vendor before doing anything else.
  2. Write a compatibility module. A small module that replaces the frontend templates of the original extension with Alpine.js and Tailwind versions.
  3. Use a Luma fallback for the route. Render specific routes with a Luma based theme. This is appropriate for complex pages that are not worth rebuilding yet, typically checkout or a heavy custom configurator.

And a fourth option that people forget: remove the extension. A migration is the right moment to ask whether every module still earns its place. An extension audit before estimating the Hyvä work often removes several items from the list. If you remove one, do it properly, as described in removing a Magento module safely.

How a compatibility module works

A Hyvä compatibility module is a regular Magento module. What makes it special is that it is registered as the compat module for an original module. When a Hyvä theme is active, Magento looks for templates of the original module in the compat module first. So a template referenced as Vendor_Module::widget.phtml is served from your compat module's view/frontend/templates/widget.phtml if it exists there. The original module's layout XML, blocks and view models keep working, only the templates are swapped.

This mechanism lives in the Hyvä compat module fallback package. The registration is a di.xml entry.

<?xml version="1.0"?>
<!-- app/code/Hyva/VendorModule/etc/frontend/di.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Hyva\CompatModuleFallback\Model\CompatModuleRegistry">
        <arguments>
            <argument name="compatModules" xsi:type="array">
                <item name="hyva_vendor_module" xsi:type="array">
                    <item name="original_module" xsi:type="string">Vendor_Module</item>
                    <item name="compat_module" xsi:type="string">Hyva_VendorModule</item>
                </item>
            </argument>
        </arguments>
    </type>
</config>

The naming convention for compat modules is Hyva_ followed by the vendor and module name of the original. You can use your own vendor namespace for private compat modules. What matters is the registration, not the name.

The module's module.xml should declare a sequence on the original module and on Hyva_CompatModuleFallback, and its composer.json should require both packages.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Hyva_VendorModule">
        <sequence>
            <module name="Vendor_Module"/>
            <module name="Hyva_CompatModuleFallback"/>
        </sequence>
    </module>
</config>

Writing the compat templates

Start by finding every template the original module renders on the storefront. The quickest way is to enable template path hints on a development store, or search the module's view/frontend/layout folder for template= attributes and setTemplate calls.

For each template:

  1. Copy it into the compat module at the same relative path.
  2. Remove every data-mage-init, x-magento-init script and Knockout binding.
  3. Rebuild the interaction with an Alpine component in the same template. The patterns for that are in writing Alpine.js components in Hyvä.
  4. Replace the LESS styling with Tailwind utility classes.
  5. Keep the block methods the original template called. If logic in the original JavaScript should really be on the server, add a view model in the compat module.

Read the original JavaScript carefully before rewriting it. Often it contains business logic that is not obvious from the template: an AJAX endpoint, a price recalculation, a dependency on a customer data section. Every one of those has to be reproduced or the feature silently changes behavior.

Layout changes only for Hyvä

Sometimes a template is not enough and you need to remove a block or move it on Hyvä only. Use the hyva_ prefixed layout handles, which the Hyvä theme module adds alongside the normal handles when a Hyvä theme is active. A file named hyva_catalog_product_view.xml in the compat module applies only on Hyvä product pages, so the same code base can still serve a Luma store view without side effects.

<?xml version="1.0"?>
<!-- view/frontend/layout/hyva_catalog_product_view.xml -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="vendor.module.product.legacy.js" remove="true"/>
    </body>
</page>

Registering the module for the Tailwind build

Your compat templates use Tailwind classes, so the theme build must scan them. Modules register their path through an observer on the hyva_config_generate_before event, and bin/magento hyva:config:generate writes the result to app/etc/hyva-themes.json. The observer adds an entry to the extensions list of the config object passed in the event.

<?php
declare(strict_types=1);

namespace Hyva\VendorModule\Observer;

use Magento\Framework\Component\ComponentRegistrar;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

class RegisterModuleForHyvaConfig implements ObserverInterface
{
    public function __construct(
        private readonly ComponentRegistrar $componentRegistrar
    ) {
    }

    public function execute(Observer $observer): void
    {
        $config = $observer->getData('config');
        $extensions = $config->hasData('extensions') ? $config->getData('extensions') : [];

        $path = $this->componentRegistrar->getPath(ComponentRegistrar::MODULE, 'Hyva_VendorModule');
        $extensions[] = ['src' => substr($path, strlen(BP) + 1)];

        $config->setData('extensions', $extensions);
    }
}

Check the Hyvä documentation for the version you run to confirm where the event observer must be declared and whether your module also needs its own Tailwind config file. Rebuild the theme CSS after adding the module.

Using the Luma fallback

The fallback package can render selected routes with a Luma based theme. It is configured in the admin under the Hyvä settings, where you enable it, choose the fallback theme and list the route paths. Checkout is the common case. Other good candidates are pages from an extension with a lot of Knockout code that few customers use, for example a returns portal in the customer account.

Keep in mind what you pay for each fallback route:

  • A second theme to maintain, with its own styling that has to look close enough to the Hyvä theme.
  • Full Luma JavaScript on those pages, which means slower loads there.
  • Static content deploy for both themes, which makes deploys longer.

Treat fallback routes as temporary unless there is a good reason. Put them in the backlog with a plan.

Estimating compatibility work

For a migration estimate, build a table with one row per extension with frontend output. For each one record whether a compatible version exists, how many templates it renders, how much JavaScript it has, and which pages it affects. A module with one template and a toggle is an hour. A module with a Knockout driven product configurator can be weeks. Most estimate overruns on Hyvä projects come from underestimating this list, not the theme itself. The migration side of this is covered in the Luma to Hyvä migration plan.

Maintaining your compat modules

A compat module copies templates from another vendor. When that vendor releases a new version, their templates may change and yours will not. Pin extension versions in composer.json, and on every update diff the original module's frontend templates against the previous version. If something changed, port it to your compat template. If you publish a compat module for a public extension, consider contributing it to the community set so others can share the maintenance.

FAQ

Do I need a compatibility module for extensions with no frontend?

No. Admin only and backend extensions such as ERP connectors, cron jobs and API integrations work on Hyvä without changes.

How does Magento know to use my compat module templates?

The compat module is registered in Hyva\CompatModuleFallback\Model\CompatModuleRegistry through di.xml. When a Hyvä theme is active, templates of the original module are looked up in the compat module first.

Is a Luma fallback a long term solution?

It can be, especially for checkout, but every fallback route means a second theme to style and maintain and slower pages on those routes. Most teams treat it as a step in the migration.

Where can I find existing compatibility modules?

Ask the extension vendor first, then check the Hyvä compatibility information and the community compat modules linked from hyva.io.

I am available for freelance Magento and Hyvä work, including compatibility modules. If you need help with this, get in touch.

Related articles