Template extension order
When you extend a template with hw_extends, hostware builds a tree of every source that also defines that template, then walks the tree in a fixed priority order to decide which version wins.
{% hw_extends 'storefront::home.twig' %}Suppose one module and one theme both define a home.twig that extends the storefront home page:
custom/
├── modules/
│ └── DashservVps/
│ └── src/resources/views/home.twig
└── themes/
└── hw/
└── evolution/
└── resources/views/home.twigDuring compilation hostware collects every template with that logical path into an unsorted tree, keyed by namespace:
[
"storefront" => "resources/views/storefront/home.twig",
"dashservvps" => "custom/modules/DashservVps/src/resources/views/home.twig",
"theme.evolution" => "custom/themes/hw/evolution/resources/views/storefront/home.twig",
]The template finder then sorts the tree by priority:
Themes
Modules
Hostware core (
storefront::)
The theme's version is rendered first. Its unfilled blocks fall through to the modules layer next, and only the blocks nobody replaced ever reach the core storefront. This is what makes a theme's partial overrides "just work" without any wiring.
hw_include follows the same order
The include tag has a hostware equivalent, hw_include, that walks the exact same three-source chain. So when a core template includes a component with hw_include 'storefront::component/product/card.twig', a theme that ships its own card.twig at the matching path replaces the component wherever it is included, without you having to override the parent template too.
Practical consequences
A theme's file always wins over a module's file at the same path. If your theme's changes are being ignored, verify a module is not shipping a version of the same template that is missing your block.
Modules extend the storefront the same way themes do, so a theme built on top of a module still overrides its templates.
Only Twig blocks at the root level of a file get overridden. Nested blocks live inside their parent and only get reached when that parent block is not itself overridden.