Multi-Theme Parity
A behavioural fix belongs in every theme that carries the same file, and a tool says which themes still lack it.
Overview
An installation ships several themes. They share a file layout and mostly the same markup. A defect found in one theme is rarely a defect of that theme: it belongs to the file, wherever that file was copied.
The rule is short. A fix made in one theme is made in every theme that carries the counterpart of that file. It works both ways, and memory does not keep it: the second theme lints clean on its own.
Prerequisites
- Two or more themes under templates/website. The tool finds them from the manifest in each directory.
- A finished change. Run the check after the fix: its input is what you touched.
- A place to record deliberate differences. An unexplained missing file is a bug.
Structure
Two Triggers, One Tool
| Situation | Direction | What you do |
|---|---|---|
| A bug, a behaviour, a security hole or an accessibility defect. | Outwards, to every other theme. | Apply the same fix to every theme with the counterpart file, then run the single-file check. |
| You are building a new theme, or adding a page or a component. | Inwards, from the other themes. | Run the inventory. Port every missing file, or write it down as intentionally absent. |
Whether a difference is deliberate depends on the nature of the change.
| Kind of change | Travels to | Why |
|---|---|---|
| Behaviour, correctness, security, accessibility, data handling | Every theme | None of this is visual identity. A theme may look different; it may not be less correct. |
| Colour, spacing, a structure from that theme's own design source | Only that theme | This is what makes a theme a theme. Copying it outwards erases the other theme's design. |
Why the Comparison Is Theme Neutral
Two copies of the same component are never byte-identical, because each theme owns its own prefixes. So each file is normalised first, and only real content differences survive:
- Custom property and data attribute prefixes fold together.
- The JavaScript namespace folds, so a call through one theme's global object equals another's.
- The bare theme name folds everywhere, class names included.
A reported difference is a difference in what the file does, not in what it is called.
Walkthrough
1. Run It After Every Fix
- Fix the file in the theme you were working in.
- Run the single-file check on the path you touched.
- If the round touched several files, use the changed-files mode.
php .claude/tools/theme-parity.php views/account/services.tpl # one file
php .claude/tools/theme-parity.php --changed # everything this round touched
2. Read the Verdict
Three outcomes; only one means you are finished.
| Output | Meaning | What to do |
|---|---|---|
| All equivalent | Same content everywhere, once prefixes are folded. | Nothing. The fix travelled. |
| Diverging, with theme names and a character delta | The named themes hold a different version. | Deliberate visual identity stays. Anything else has not reached those themes yet. |
| Missing, with theme names | The file does not exist in those themes. | Port it, or write down why it is absent. |
3. Close the Gap
- Port the file, or record the substitution.
- Verify by counting, not by loading.
- Count the marker it should have produced: a styled class, a preset wrapper, a layout shell.
| Missing piece | What the page does | How to catch it |
|---|---|---|
| A table preset | Loads. The component falls back to raw columns. | Count the preset's classes in the output; zero means it never loaded. |
| A stylesheet rule | Loads. The class matches nothing, so the block appears unstyled. | Compare the count of the styled class across themes. |
| A block override | Loads, inside the wrong shell. | Check what surrounds the content, not the content. |
Reference
Invocation
What Is Compared
Exit Codes
Usable as a gate, not only as a report.
0 nothing needs attention: present everywhere and equivalent everywhere
1 at least one file is missing somewhere, or one copy has diverged
(in the inventory mode, 1 simply means the tree still has unexplained gaps)
# Fewer than two themes is not a failure, it is a no-op: the tool says so and exits 0.
php .claude/tools/theme-parity.php views/account/services.tpl; echo "exit: $?"
Example
Real output, one block per verdict.
$ php .claude/tools/theme-parity.php components/news-newsletter.tpl
=== components/news-newsletter.tpl
var : Basic, WCOM, WStyle
✔ içerik: hepsi eşdeğer (tema-nötr karşılaştırma)
$ php .claude/tools/theme-parity.php views/account/services.tpl
=== views/account/services.tpl
var : Basic, WCOM, WStyle
⚠ içerik: Basic ile AYRIŞAN → WCOM
WCOM 124 karakter fark
All three themes have the file; one holds a version 124 characters apart. A layout decision stays. Your fix has not arrived yet.
$ php .claude/tools/theme-parity.php partials/client-subnav.tpl
=== partials/client-subnav.tpl
var : Basic
❌ YOK : WCOM, WStyle <-- ya taşı ya da tema-özel/ikame olarak belgele
This gap is legitimate only because it is written down: the other two themes navigate with a sidebar instead.
$ php .claude/tools/theme-parity.php
Tema (3): Basic, WCOM, WStyle
Basic 229 dosya
WCOM 514 dosya
WStyle 249 dosya
Tüm temalarda olan: 218 dosya
Bazılarında eksik : 321 dosya
--- eksik olanlar (dosya → hangi temalarda YOK) ---
assets/css/app-detail.css YOK: Basic, WStyle
...
assets/css/client-nav.css YOK: Basic, WCOM
...
assets/css/marketplace.css YOK: Basic, WStyle
...
Read the list for answers, not for a verdict: a large gap count is not alarming on its own. What matters is that every line has an answer.
Pitfalls
All three silent classes answer with a working page, so route tests and a quick look pass. Count the marker the missing piece should have produced.
First compare the two design sources. Same structure: copy and rename prefixes. Redrawn structure: fidelity to the source is the failure.
Copied markup brings the source theme's prefix along, and the selector then matches nothing. After any port, search the copied files for the source theme's name.
The inventory prints missing files, not reasons. A gap nobody wrote down looks like an oversight, and an unread gate is the same as no gate.
It reads the same with two themes as with ten.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.