Develop and debug a theme locally
The dev loop for a hostware theme is: run the SCSS watcher, edit twig or SCSS, refresh the storefront. Cache issues, silent overrides and wrong template paths cover roughly all of the "why is my change not showing" questions, and every one of them has a quick check.
Keep the SCSS watcher running
The per-sales-channel theme CSS is compiled by the admin's Save button, not by file edits. Run the watcher in a terminal for the duration of your session and it will rebuild whenever any SCSS file changes:
php artisan theme:watch # poll every 1s
php artisan theme:watch --interval=2 # slower cadence
php artisan theme:watch --initial # compile every sales channel once on startupThe watcher walks every installed theme's public/css/ tree and recompiles every sales channel using the affected theme when a file changes. A syntax error surfaces in the watcher's output.
Clear caches when twig changes stop landing
Twig template changes should be picked up on the next request. When they are not, the Twig cache is stale:
UI: Administration > Settings > Debug has a "Clear cache" button.
CLI:
php artisan twig:clean.
Adding a new file under resources/views/ occasionally needs the theme cache too. Run php artisan theme:cache.
Find out which template is actually rendered
The template resolver walks theme -> modules -> core, so when your override does not fire, either the file is at the wrong path or a module is winning. Two ways to trace it:
Search the source tree for a class or attribute you see in the rendered HTML. Run
grep -rn "class-name" resources/views custom/themes custom/modules. Every hit is a candidate; the one that actually wins is the highest one in the priority order.Enable the Debug Bar (Administration > Settings > Debug). The Views tab lists every twig template rendered for the current request, with its full absolute path. If your theme's file is not in the list but the core's is, your override's path is wrong.
Common mistakes
Almost every "the change is not showing" issue is one of these.
Wrong path in the override. Your override must sit at the exact same relative path under
resources/views/storefront/as the core template it replaces. Off-by-one on a folder (storefront/component/productvsstorefront/components/product) makes the resolver never find it.Overriding an outer block. When you re-declare a block that contains inner blocks, those inner blocks are gone unless you call
{{ parent() }}or invoke them by name. Override the innermost block that fits, not its parent.Missing
!defaultin SCSS. Brand-tied variables that do not use!defaultignore the admin's branding form, because your line re-assigns the value that the compile pipeline had already prepended.Asset path without the vendor segment.
/themes/mytheme/...always 404s. Use/themes/<vendor>/<name>/....Twig extending a bare path.
{% hw_extends 'home.twig' %}is rejected by the resolver. Always use the namespace form:storefront::home.twig.CMS element namespace mismatch. The PHP namespace on a
Cms/Elements/*.phpfile must be exactlycustom\themes\<vendor>\<name-lowercased>\Cms\Elements. Any typo and the class is silently skipped during discovery.
Cross-testing on multiple sales channels
Theme CSS is per sales channel, so a compile on the wrong channel does not update the one you are viewing. If a sales channel is not picking up your changes, check its assigned theme (Administration > Sales Channels > Theme). The watcher only recompiles channels currently using the theme you are editing.
When something works on one sales channel but not another that uses the same theme, the second channel usually just needs a branding save (or $sc->compileTheme() from tinker) to catch up.