Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
292 commits
Select commit Hold shift + click to select a range
4c1605f
Develop (#19)
wpoortman Dec 20, 2021
3e4661d
Develop (#20)
wpoortman Dec 20, 2021
3cbf14a
[master]:+ Set nested property value via magic action bugfix
wpoortman Dec 21, 2021
adc46e0
[main]:+ Lifecycle booted() method
wpoortman Dec 27, 2021
e0f42ad
[main]:+ Appending component DOM end marker
wpoortman Dec 28, 2021
1e1b67c
[main]:+ Appending component DOM end marker (StyleCI fix)
wpoortman Dec 29, 2021
c83b3bb
[main]:+ Base url for M2 setup is not applied properly #21
wpoortman Jan 17, 2022
a06307a
[main]:+ Upgrade JS to Livewire from 2.8.0 to 2.9.0
wpoortman Jan 19, 2022
a9b406e
[main]:+ Composer preps for v1.2.1
wpoortman Jan 19, 2022
317af7c
[main]:+ Composer preps for v1.3.0
wpoortman Jan 19, 2022
ee46b0f
Improvement/property binding (#22)
wpoortman Feb 6, 2022
3a0b64f
Automatically assign $magewire as template variable (#23)
Vinai Feb 20, 2022
64dff69
[feature/js-improvements]:+ New magewire:available Document event (#24)
wpoortman Mar 4, 2022
f38aaec
[feature/phpsevenfour]:+ PHP7.4 compatibility (#25)
wpoortman Mar 4, 2022
24a4c90
[main]:+ PHP74 upgrades
Mar 15, 2022
629e6ee
[master]:+ v1.4.0 release preps
Mar 25, 2022
602b38d
[main]:+ Wire ID hashing removal (has no security impact)
Mar 30, 2022
939a012
[improvement/exception-handling]:+ Large exception handling overhaul …
wpoortman Mar 31, 2022
5a4bc08
[bugfix/form-property-types]:+ Removed the property types (will retur…
wpoortman Apr 1, 2022
86c018c
[main]:+ Documentation fixes
Apr 1, 2022
cfc2f66
[main]:+ Documentation fixes
Apr 3, 2022
e90b108
[main]:+ Catching global form exceptions + new clearErrors method
Apr 3, 2022
f978bd9
[main]:+ v1.5.0 release
Apr 3, 2022
cb97244
Tools.md creation for collection of development tools (#28)
ryanhissey Apr 3, 2022
bb00382
[main]:+ Component name property deprecation
wpoortman Apr 8, 2022
e40b4bd
[main]:+ Component exception handling UX improvements
wpoortman Apr 8, 2022
3bda7c4
[main]:+ Component exception handling UX improvements
wpoortman Apr 8, 2022
4d0d6c9
[improvement/form-key-expiration]:+ 419 HttpException on form-key exp…
wpoortman Apr 14, 2022
7676a13
Feature/parent children (#31)
wpoortman Apr 14, 2022
ede0f7f
[main]:+ Subsequent request exception handling and logging improvements
wpoortman Apr 19, 2022
e3e3127
[main]:+ Application URL issue fix for specific domain use cases
wpoortman Apr 19, 2022
a73321d
[main]:+ Minor event listener Hydrator enhancement
wpoortman Apr 19, 2022
daa7640
Improvement/component lifecycle (#33)
wpoortman Apr 20, 2022
bbe5c52
Improvement/component lifecycle (#34)
wpoortman Apr 20, 2022
2f9b4e6
[main]:+ Custom 419 response code fix
Apr 20, 2022
d2f3cb1
[main]:+ Fix for Http Response code missing exception
May 5, 2022
37f7bb8
[main]:+ Skip render false empty shell render without the body
May 5, 2022
5a7ecdb
[main]:+ Skip render false empty shell render without the body (Style…
May 5, 2022
8e83b3e
Fix Component-Based Restricted Methods Definition (#37)
pykettk Jun 5, 2022
d5c9bdc
Docs: Add Component Array Property Access Example (#38)
pykettk Jun 6, 2022
85ae719
Bugfix/auto template binding (#40)
wpoortman Jun 11, 2022
f66d239
[main]:+ 1.6.2 preps
Jun 11, 2022
972c75e
fix: type annotations for dispatchBrowserEvent (#41)
kolaente Jun 14, 2022
0124e8e
Docs: Update PHP Lifecycle Notes (#39)
pykettk Jun 14, 2022
48ad7a7
[Docs] Update Message Dispatch Documentation (#44)
pykettk Jun 16, 2022
0b88ba0
[main]:+ JS lib upgrade from 2.6.7 to 2.10.5
Jun 24, 2022
b86971a
[main]:+ What developers day (Kiel from Fisheye)
Aug 4, 2022
a581843
[main]:+ Deprecated Livewire vintage controller
Aug 4, 2022
7155cd5
[main]:+ Git ignore
Aug 4, 2022
a433241
[main]:+ Controller in_array strict improvement
Aug 4, 2022
32d6adc
[main]:+ Include Magewire CSS into head
Aug 10, 2022
3bca8d7
[main]:+ Developer quote Ryan Copeland
Aug 10, 2022
933425e
[main]:+ 1.6.3 preps
Aug 10, 2022
2f3d222
[main]:+ Hyva Tailwind compatiblity
Aug 15, 2022
cb5a5bf
[main]:+ Minor style changes
Aug 15, 2022
31effec
[main]:+ Replaced deprecated .createEvent('Events') with .dispatchEve…
Sep 9, 2022
443a30c
[main]:+ Replaced deprecated .createEvent('Events') with .dispatchEve…
Sep 9, 2022
287d665
[main]:+ Moved styling from the .css file into a tailwind-source.css …
Sep 14, 2022
b6160b7
Feature/offload (#55)
wpoortman Sep 15, 2022
958fee5
[main]:+ Offload feature JS improvements
Sep 15, 2022
cd90525
[main]:+ Update JS lib from version 2.10.5 > 2.10.7
Sep 22, 2022
7d37e45
Bugfix/component without children (#56)
wpoortman Sep 30, 2022
551e6e6
Feature/magewire var children (#57)
wpoortman Sep 30, 2022
6c7f8e0
[main]:+ 1.6.4 release preps
Sep 30, 2022
71f0703
Remove outdated docs on component id hashing (#58)
Vinai Oct 5, 2022
7fc5992
Correct call to `getFoo()` in example (#60)
Vinai Oct 5, 2022
6689d7e
Avoid Alpine.deferLoadingAlpine conflicts (#59)
Vinai Oct 5, 2022
4aa1495
[main]:+ Wrapped executions of boot, mount & booted with a try-catch …
Oct 6, 2022
1cbda5e
[main]:+ Dont set child(ren) on parent when parent has throw an excep…
Oct 10, 2022
10b468b
[main]:+ Replaced PHP's htmlspecialchars() with Magento\Framework\Esc…
Oct 10, 2022
3ddc641
[main]:+ Minor typo improvement on the Magewire processing exception …
Oct 10, 2022
f0b8f24
[main]:+ 1.6.5 preps
wpoortman Oct 12, 2022
6c50c56
[main]:+ Bugfix for updates on component during subsequent requests
Oct 18, 2022
9e0bc28
[main]:+ Bugfix on properties merging for subsequent update requests
Oct 20, 2022
49d64a0
[main]:+ Twitter social button
Oct 20, 2022
5b4c166
Alpine v2 and v3 compatibility (#61)
Vinai Oct 25, 2022
0c3acab
[main]:+ 1.7 release preps
wpoortman Oct 25, 2022
1d10c48
[main]:+ 1.7 release preps
wpoortman Oct 25, 2022
4d5b11a
Enforce lowercase layout handle names (#62)
Vinai Oct 27, 2022
50ac816
[bugfix/propper-prop-binding]:+ Fixed issue by adding the refreshing …
wpoortman Oct 31, 2022
1e14d13
[feature/validate-only]:+ Feature implementation (#65)
wpoortman Oct 31, 2022
216abc5
[main]:+ 1.7.1 release preps
wpoortman Oct 31, 2022
f9461d3
[bugfix/refresh-event]:+ Adding a extra if condition where the update…
wpoortman Nov 3, 2022
97cfe8d
[feature/redirect-to-external]:+ redirect hydrator improvement for ex…
wpoortman Nov 9, 2022
b61c61e
[main]:+ 1.7.3 release preps
Nov 9, 2022
dc260ac
Include all emits also become a observable ManagerInterface event (#69)
wpoortman Nov 18, 2022
2ec745b
Changed @apply styles into plain css for the error iframe (#70)
wpoortman Nov 18, 2022
bd9f8df
v1.7.4 release preps
Nov 18, 2022
e31d412
Merge branch 'main' of https://github.com/magewirephp/magewire
Nov 18, 2022
7cd306b
Dispatch magewire:available event when it actually is available (#73)
Vinai Jan 11, 2023
7ab9023
Release 1.7.5 prep
Jan 11, 2023
74a57a0
New quotes Vinai Kopp and Kiel Pykett
Jan 11, 2023
fba460d
New quote from Jesse de Boer from Elgentos
Jan 11, 2023
614b2ba
Feature/loader message (#74)
wpoortman Jan 31, 2023
85ce1aa
1.8.0 release prep
Jan 31, 2023
811b7d8
Minor loader fixes before the 1.8.0 release
Jan 31, 2023
988cbec
1.8.0 release bugfix where emitted requests doesnt show the loader
Jan 31, 2023
ea311d2
Bugfix/loader missing effects (#75)
wpoortman Feb 12, 2023
575e7ef
Bugfix/loader missing effects (#76)
wpoortman Feb 13, 2023
23a6389
Magewire onError implementation for M2 production mode (#84)
magewirephp Mar 14, 2023
38ba496
Kickstarter course README banner
wpoortman Mar 15, 2023
78034d7
Added Marcus Venghaus to the "Developer say" quote section
wpoortman Mar 15, 2023
68379bc
Release prep 1.8.3
Mar 20, 2023
ae985c2
Improved Error plugin docs
Mar 21, 2023
dc6ce0d
Added a custom onPageExpired handler callback
Mar 21, 2023
e632d1b
Fixed a small Style CI issue
Mar 21, 2023
81d85c6
New wire:select directive (incl. optional modifiers .defer + .debounc…
wpoortman Mar 22, 2023
c56fff1
Added wire:select directive documentation
Mar 27, 2023
58afd8f
1.8.4 release preps
Mar 27, 2023
ede70c2
README modifications including a Premier Sponsors section
Mar 27, 2023
2bc6773
Added Hyvä Themes as Premier Sponsor
wpoortman Mar 27, 2023
54b61d6
Linked feature list wire:select to #wire-select section
Mar 27, 2023
8c8d762
Merge remote-tracking branch 'origin/main' into main
Mar 27, 2023
f4bc3f3
Fix return type of getErrors (#86)
Tjitse-E Mar 27, 2023
1076ed5
Funding YML
Mar 30, 2023
ad57541
Funding YML
Mar 30, 2023
d9b1cc6
Added Vendic [NL] as sponsor
wpoortman Mar 30, 2023
49fc82e
Component resolvers (#90)
wpoortman Apr 3, 2023
276a198
Component resolvers (#91)
wpoortman Apr 3, 2023
ff7fc83
Removed some unrequired tmp files
Apr 3, 2023
639933b
PHTML-PHP echoing JS without line closing issue bugfix (#92)
wpoortman Apr 3, 2023
432f929
Layout component resolver fingerprint not found issue fix
Apr 3, 2023
ad05ac9
Magewire cache type + caching resolvers for blocks
Apr 6, 2023
ea2a207
Wrote docs on how to extend the Magewire onError callback
Apr 7, 2023
45ffbcc
Resolver architecture improvements
Apr 7, 2023
421612a
Minor Resolver improvements before release
Apr 7, 2023
2c4b57f
Resolver documentation
Apr 7, 2023
8316cda
Release 1.9.0 preps
Apr 7, 2023
a0f196e
Reconstruct component during subsequent request security and code imp…
Apr 7, 2023
3acf592
Resolvers cache section load failure bugfix
Apr 11, 2023
43a1dea
1.9.1 release preps
Apr 11, 2023
594f3d5
Fix AlpineJS errors when HTML minification is enabled (#94)
Tjitse-E Apr 19, 2023
bf1d9f0
Add docs on AlpineJS/Magewire entangle (#95)
Tjitse-E Apr 26, 2023
acac8f6
form validation - added use of aliases and the translation (#82)
mvenghaus Apr 26, 2023
f4c16c5
Avoid 'Alpine is not defined' errors (#97)
Vinai May 10, 2023
685611b
fix: adding symfony/http-foundation require (#98)
adamzero1 May 16, 2023
f8c986a
Independency note
May 28, 2023
86930fd
Independency note
May 28, 2023
7e2ba6a
README modifications
May 28, 2023
cf518bf
README modifications
May 28, 2023
324f0ab
README modifications
May 28, 2023
81d8af1
README modifications
May 28, 2023
14d5b80
patch: data patch to enable magewire cache after installation (#100)
speedupmate Jun 1, 2023
e75a738
New overhauled loader implementation (#101)
wpoortman Jun 1, 2023
90a9d0b
Prep version 1.10.0
Jun 2, 2023
56666f0
Loader documentation improvements
Jun 2, 2023
969c7bd
Add MagewireSystemConfig property to avoid dynamic property warning i…
peterjaap Jun 6, 2023
529f398
Fix loader issues (#103)
Vinai Jun 6, 2023
91b6691
Allow passing an assoc as an emit param (#104)
Vinai Jun 6, 2023
d10f794
Prep 1.10.1 release
Jun 6, 2023
518825e
Loader improvements based on some specific flow issues (#108)
wpoortman Jun 13, 2023
9cf7cfa
Prep 1.10.2 release (#109)
wpoortman Jun 13, 2023
a66ec49
Loader bugfixes (#110)
wpoortman Jun 14, 2023
43a20aa
Prep 1.10.3 release (#111)
wpoortman Jun 14, 2023
de4b1b1
Revert code from #104 because it breaks stuff, need to re-look into t…
wpoortman Jun 15, 2023
36d1a11
Check if loader still exists in the queue
Jun 17, 2023
91b58d6
Fix loader clearing (#113)
Vinai Jun 18, 2023
eebce5e
Release prep 1.10.4
Jun 18, 2023
ca932a2
Removed visible email addresses
Jun 19, 2023
47bf37d
Removed visible email addresses
Jun 19, 2023
5f23839
Improvements/subsequent requests (#115)
wpoortman Jul 4, 2023
a626f5d
Improvements/subsequent requests (#116)
wpoortman Jul 5, 2023
0299dfe
Preping release 1.10.5
Jul 5, 2023
5740e9f
Improvements/subsequent requests (#117)
wpoortman Jul 5, 2023
971abf9
Update Sponsor section in main markdown
wpoortman Jul 10, 2023
9f282a3
Update README.md
wpoortman Jul 10, 2023
d726957
Improvements/nested input sync methods (#119)
wpoortman Aug 3, 2023
cf44969
Prep 1.10.6 release (#120)
wpoortman Aug 3, 2023
6eb623c
Added invite to Discord
wpoortman Aug 4, 2023
75e3c86
Option to start the loader without the component requirement (#121)
wpoortman Aug 8, 2023
2da2646
Release 1.10.7 prep
Aug 8, 2023
14b59f4
Emit param handling: allow assoc arrays and multiple emit arguments (…
Vinai Aug 22, 2023
e8d85b7
Added a More heading to the README
wpoortman Aug 26, 2023
6d92981
Sprintf issues for CorruptPayloadException exception messages (#124)
wpoortman Sep 21, 2023
3209a0a
Call to undefined function Magewirephp\Magewire\Model\Action\__sprint…
adamzero1 Sep 21, 2023
b62c097
Release prep 1.10.8
Sep 24, 2023
4d42551
Fix typo in error message (#130)
Tjitse-E Oct 18, 2023
cf8b0bb
Fix missing sprintf in layout reconstruct (#131)
psopacua Oct 20, 2023
816d752
Hydrator positioning feature improvements (by di) (#132)
wpoortman Oct 21, 2023
c2c1fa6
1.10.9 release prep
Oct 21, 2023
8bd856a
WIP: layer to extend the Magewire object (#133)
wpoortman Oct 25, 2023
70d5ef6
Update composer.json
wpoortman Oct 25, 2023
01b92ff
Update composer.json to working with magento 2.4.7 (#134)
quanghien95 Oct 27, 2023
554603e
Fix magewire compatible with MageOs (#138)
MartinNguyen211 Nov 10, 2023
ae2ff1b
Input sync nested data bugfix for updating* (#140)
wpoortman Nov 15, 2023
8e0e45a
Release 1.11.0 preps
wpoortman Nov 16, 2023
a0c1182
Added a common separate issues section in the docs directory (#144)
wpoortman Dec 12, 2023
40cc7cc
Avoid TypeError in bussy queue (#143)
KamilBalwierz Dec 18, 2023
55a10e0
Added Zero-1 as sponsor
wpoortman Feb 5, 2024
27c680a
Update README.md
wpoortman Feb 5, 2024
3dec156
Update README.md
wpoortman Feb 5, 2024
c4071a9
Add Info for JS-Based Emit Message Listeners (#149)
pykettk Apr 15, 2024
c7f610e
Kickstarter course removal
wpoortman Jul 6, 2024
e26823f
Fix Loader Stop Event Name (#155)
pykettk Jul 17, 2024
abf60a9
Prevent modal from closing when clicking on overlay (#156)
jeroennoten Jul 20, 2024
cb0ed5a
Update version from 1.11.0 - 1.11.1
wpoortman Jul 26, 2024
176ddb2
Fix: catch any serialisation related error and return/response as jso…
wpoortman Jul 26, 2024
8e39f68
Typo
Jul 26, 2024
e5d4ecf
Fix Livewire Browser Plugin component updates (#136)
jissereitsma Jul 29, 2024
1291fc8
Minor controller code improvements before release 1.11.1
Jul 29, 2024
ffab4ba
Add missing parenthesis (#159)
mehmetuygun Aug 22, 2024
e1e5fff
Added M.acadamy as a sponsor
wpoortman Sep 10, 2024
b246362
Update README.md
wpoortman Sep 10, 2024
c3839fa
Update README.md
wpoortman Sep 26, 2024
54dd735
Update overlay.phtml (#160)
rossmc Oct 15, 2024
838a3fe
Removing a sponsor
wpoortman Dec 9, 2024
ede4a91
Feature/component loader overlay (#162)
wpoortman Dec 9, 2024
ab3d547
Fix Livewire Devtools URL (#163)
markshust Jan 17, 2025
ac24a2b
Content Security Policy (CSP) Support
JeroenBoersma Feb 20, 2025
c3aceee
Release: preps for the 1.12.0 release (#168)
wpoortman Feb 20, 2025
8ee559c
Update LoaderOverlay for dynamic property issue (#169)
alucardatem Feb 21, 2025
7db48f9
Improvements on component based loader (#170)
wpoortman Feb 21, 2025
140b521
Made component loader overlay a little smaller
Feb 21, 2025
3f392d7
Release: preps for the 1.12.1 release (#171)
wpoortman Feb 21, 2025
84a1b18
Update README.md
wpoortman Feb 21, 2025
00adeaa
Fix docs/Features.md Markdown header anchor links (#174)
angelvilaplana Mar 28, 2025
842bda5
Fixed implicitly declared nullable arguments, improves compatibility …
hostep Apr 22, 2025
662abdc
PHP 8.1 and up dependency
wpoortman Apr 30, 2025
327a221
Compatibility with Magento 2.4.8 and Mage-OS 1.1.1 (#177)
Vinai May 16, 2025
1229934
Update composer.json
wpoortman May 16, 2025
122637e
Prepping release 1.3.1
wpoortman May 16, 2025
e13d99d
Farewell V1
Jun 2, 2025
2b15358
Hello V3
Jun 2, 2025
f764b9c
Remove old magewire-three repo instructions guideline
Jun 2, 2025
912c908
Beta warning for main branch
wpoortman Jun 2, 2025
5715152
Hello Dependabot
Jun 2, 2025
2b7e650
Portman Github Workflow
Jun 2, 2025
4cda666
Release Please Github Workflow
Jun 2, 2025
3c315d2
Moved the Discord button and updated the invite URL for README
wpoortman Jun 3, 2025
67f1e26
chore: fragment modifier output limitations
Jun 5, 2025
f885b42
chore: view fragment modifier architectural improvements
Jun 6, 2025
032a47c
feat: added the developer view fragment modifier
Jun 6, 2025
662537a
feat: notification option to keep it visible for a day when duration …
Jun 9, 2025
38de7d0
feat: Include Tailwindcss (minimum)
Jun 11, 2025
d75957b
chore: Include Developer fragment modifier (developer mode only)
Jun 11, 2025
6a311d1
chore: Modifiers array became readonly for HTML fragments
Jun 11, 2025
cf28c76
feat: DOM, Loader and Str utilities
Jun 11, 2025
2851093
feat: Notifier refactor
Jun 11, 2025
c11f48d
Miscellaneous 0001 (#183)
wpoortman Sep 5, 2025
483379a
Improvements/style ci fixes before first beta (#188)
wpoortman Sep 6, 2025
682cf1f
Remove DS Store (#193)
ryanhissey Oct 10, 2025
cab63b4
Update MagewireUpdateRoute.php (#207)
ryanhissey Mar 27, 2026
c274980
Revert "Update MagewireUpdateRoute.php (#207)" (#208)
ryanhissey Mar 27, 2026
9b9a521
Upgrade/hc (#214)
wpoortman Apr 23, 2026
06bd961
3.0.0 release changelog
Apr 23, 2026
7535eae
3.0.0 release preps (contribution, upgrading, release-please etc.)
Apr 23, 2026
527dc3c
3.0.0 release - Claude MD removal
Apr 23, 2026
b8beec4
chore(deps): bump stefanzweifel/git-auto-commit-action from 5 to 7 (#…
dependabot[bot] Apr 23, 2026
d25acdb
chore(deps): bump actions/checkout from 4 to 6 (#200)
dependabot[bot] Apr 23, 2026
e25fe9f
chore(deps): bump googleapis/release-please-action from 4 to 5
dependabot[bot] Apr 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .claude/skills/hyva-alpine-component
1 change: 1 addition & 0 deletions .claude/skills/hyva-internal-coding-standard
1 change: 1 addition & 0 deletions .claude/skills/hyva-internal-skill-security-review
1 change: 1 addition & 0 deletions .claude/skills/hyva-playwright-test
596 changes: 596 additions & 0 deletions .claude/skills/magewire-architecture/SKILL.md

Large diffs are not rendered by default.

183 changes: 183 additions & 0 deletions .claude/skills/magewire-backwards-compatibility/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
---
name: magewire-backwards-compatibility
description: "Reference for Magewire's framework-level backwards compatibility system. Use when migrating Magewire v1 (Livewire v2) code to v3, enabling BC on components, understanding wire:model / entangle / hook behavioral changes between v2 and v3, or working with the BC memo flag, deprecated v1 component APIs, and the #[HandleBackwardsCompatibility] attribute. Theme-agnostic — BC applies to any Magewire component in any Magento theme. For theme-specific BC JS implementations (e.g. Hyvä Checkout), see the matching theme's BC skill."
license: MIT
metadata:
author: Willem Poortman
---

# Magewire Backwards Compatibility

Magewire v3 is built on Livewire v3, which introduced breaking changes from v2. The BC system lets existing v1 components keep working without code changes while providing a migration path to v3 conventions.

Magewire is **not tied to any specific theme**. The BC system is a framework concern — any component, in any theme, can opt into BC. Individual themes may ship their own JS-layer BC implementations on top of this core (see the theme's BC skill for details).

---

## The Two BC Layers

### 1. Core BC (`lib/MagewireBc/`) — theme-agnostic

Framework-level compatibility that applies to all Magewire components regardless of theme.

**PHP trait** — `HandlesComponentBackwardsCompatibility` is mixed into the base `Component` class. It provides deprecated v1 APIs: `$this->id` (public), `getPublicProperties()`, and concerns for Emit, Error, BrowserEvent, and Request. The `Component\Form` base class uses this trait via `HandlesFormComponentBackwardsCompatibility` (a deprecated pass-through that exists for potential form-specific BC, currently empty).

**Feature** — `SupportMagewireBackwardsCompatibility` (sort order 99100):
- Pushes BC effects into the snapshot during `dehydrate()`: property path mappings (`data` → `$wire`, `__livewire` → `queuedUpdates`) and preferences
- These effects are read by JS to proxy old property access patterns

### 2. Theme-specific BC layers

Some themes need additional BC on top of core — wire directive rewriting, entangle live-by-default, deprecated JS hook/event re-triggering. Those live in the theme's own module under `themes/{Theme}/` and are documented in that theme's BC skill. The pattern is always the same:

- A theme-scoped Feature manages a `memo.bc.enabled` flag on the snapshot
- JS templates read the flag and apply migrations to components that have it set
- The flag is resolvable per-component via the `#[HandleBackwardsCompatibility]` attribute, data store, or theme-defined layout rules

---

## The `memo.bc.enabled` Flag

The BC flag is the single signal a theme's BC JS uses to decide whether to apply v2→v3 shims to a component. Resolution priority:

1. `#[HandleBackwardsCompatibility]` attribute on the component class
2. Previously hydrated value from the component's data store
3. Theme-specific defaults (e.g. "all components under layout container X")

On `hydrate()`, the flag is restored from memo into the component's data store. On `dehydrate()`, it is pushed back into the snapshot memo.

---

## Wire Directive Changes (v2 → v3)

| Livewire v2 | Livewire v3 | Behavior |
|---|---|---|
| `wire:model` | `wire:model.live` | Syncs on every input change (instant) |
| `wire:model.defer` | `wire:model` | Syncs on form submit / next request (now the default) |
| `wire:model.lazy` | `wire:model.blur` | Syncs when the field loses focus |

### Migrating your own code

Remove the old modifiers and use v3 syntax:

```html
<!-- Before (v1/v2) -->
<input wire:model="name"> <!-- instant sync -->
<input wire:model.defer="email"> <!-- deferred -->
<input wire:model.lazy="phone"> <!-- on blur -->

<!-- After (v3) -->
<input wire:model.live="name"> <!-- instant sync (opt-in) -->
<input wire:model="email"> <!-- deferred (now default) -->
<input wire:model.blur="phone"> <!-- on blur -->
```

A theme's BC JS may rewrite these directives automatically for components with `memo.bc.enabled` — see that theme's BC skill.

---

## Entangle Changes (v2 → v3)

| Livewire v2 | Livewire v3 |
|---|---|
| `$wire.entangle('prop')` — **live** by default | `$wire.entangle('prop')` — **deferred** by default |
| N/A | `$wire.entangle('prop').live` — opt-in to live |

### Migrating your own code

If you want instant sync (v2 default), add `.live` explicitly:

```javascript
// Before (v1/v2) — live by default
couponCode: this.$wire.entangle('couponCode'),

// After (v3) — must opt in to live
couponCode: this.$wire.entangle('couponCode').live,

// Or keep deferred (v3 default) — no .live needed
couponCode: this.$wire.entangle('couponCode'),
```

A theme's BC JS may restore the v2 live-by-default semantic for BC-enabled components via a `$wire` proxy — see that theme's BC skill.

---

## Hook / Event Changes (v2 → v3)

| Deprecated (v2) | Replacement (v3) |
|---|---|
| `component.initialized` | `component.init` |
| `element.initialized` | `element.init` |
| `element.updating` | `morph.updating` |
| `element.removed` | `morph.removed` |
| `message.sent` | `commit` |
| `message.failed` | `commit` → `fail()` |
| `message.received` | `commit` → `succeed()` |
| `message.processed` | `commit` → `succeed()` → `queueMicrotask` |

### Component property aliases

Old property names aliased on the component object by BC JS layers:

```javascript
// component.deferredActions → component.queuedUpdates
// component.data → component.$wire
```

---

## Enabling BC for a Component

### Explicit via PHP attribute

```php
use Magewirephp\Magewire\Features\SupportMagewireBackwardsCompatibility\HandleBackwardsCompatibility;

#[HandleBackwardsCompatibility]
class MyLegacyComponent extends Component
{
// This component gets BC behavior
}

#[HandleBackwardsCompatibility(enabled: false)]
class MyModernComponent extends Component
{
// Explicitly opt out, even if a theme would normally enable it
}
```

### Via data store (programmatic)

```php
use function Magewirephp\Magewire\store;

// In a Feature or hook:
store($component)->set('bc.enabled', true);
```

### Via theme defaults

A theme can decide to BC-enable components automatically based on its own rules (e.g. layout container membership). See the target theme's BC skill.

---

## Key Files

| File | Purpose |
|------|---------|
| `lib/MagewireBc/Features/SupportMagewireBackwardsCompatibility/SupportMagewireBackwardsCompatibility.php` | Core BC feature — pushes path mappings into effects |
| `lib/MagewireBc/Features/SupportMagewireBackwardsCompatibility/HandleBackwardsCompatibility.php` | PHP attribute for explicit BC opt-in/out |
| `lib/MagewireBc/Features/SupportMagewireBackwardsCompatibility/HandlesComponentBackwardsCompatibility.php` | Trait with deprecated v1 component APIs |

---

## Migration Checklist

When upgrading a v1 component to v3:

1. **wire:model** — replace `wire:model` with `wire:model.live` if you need instant sync, remove `.defer` (it's now the default), replace `.lazy` with `.blur`
2. **entangle** — add `.live` if you need instant sync, otherwise leave as-is (deferred is now default)
3. **JS hooks** — replace deprecated event names (see table above)
4. **Component properties** — replace `component.data` with `component.$wire`, `component.deferredActions` with `component.queuedUpdates`
5. **PHP APIs** — replace `$this->getPublicProperties()` with `$this->all()`, avoid public `$this->id` (use `$this->id()` or `$this->getId()`)
6. **Remove BC attribute** — once migrated, remove `#[HandleBackwardsCompatibility]` if present
140 changes: 140 additions & 0 deletions .claude/skills/magewire-best-practices/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
---
name: magewire-best-practices
description: "Use when writing, reviewing, or refactoring Magewire code for Magento 2 — components, PHTML templates, layout XML, DI configuration, Features, Mechanisms, synthesizers, lifecycle hooks, event handling, and JavaScript integration. Trigger phrases include: component design, property handling, security patterns, template rendering, DI registration, snapshot serialization, state management, architectural decisions. Also use for Magewire code reviews and refactoring. Covers any task involving Magewire PHP or JS patterns within Magento 2."
requires: magewire, magewire-architecture, magewire-javascript
license: MIT
metadata:
author: Willem Poortman
---

# Magewire Best Practices

Best practices for Magewire development in Magento 2, prioritized by impact. Each rule teaches what to do and why. For deeper API reference, load the `magewire`, `magewire-architecture`, or `magewire-javascript` skills.

## Consistency First

Before applying any rule, check what the codebase already does. Magewire bridges two ecosystems — Magento and Livewire — and both offer multiple valid approaches. The best choice is the one the codebase already uses, even if another pattern would be theoretically better. Inconsistency is worse than a suboptimal pattern.

Check sibling components, related Features, existing DI config, and neighboring templates for established patterns. If one exists, follow it — don't introduce a second way. These rules are defaults for when no pattern exists yet, not overrides.

## Quick Reference

### 1. Component Design → `references/components.md`

- Extend `Magewirephp\Magewire\Component`, not Magento block classes
- Keep public properties serializable — scalars, arrays, or types with a registered synthesizer
- Use typed properties with defaults — uninitialized properties break snapshot serialization
- Small, focused components — split large components into parent-child
- Never query the database in the constructor — use `mount()` for initialization
- Use `$this->skipRender()` when a method only changes state without needing a re-render

### 2. Properties & State → `references/properties.md`

- Scalar types and arrays for public properties — complex objects need synthesizers
- `wire:model` for form binding, `wire:model.live` only when instant feedback is required
- `fill()` accepts arrays and DataObjects — use it for bulk property assignment
- `reset()` and `resetExcept()` to restore initial state cleanly
- Dot notation (`address.city`) for nested array/object properties
- Never store sensitive data (passwords, tokens) in public properties — they travel to the client

### 3. Lifecycle Hooks → `references/lifecycle.md`

- `mount()` for initial setup — runs once, receives layout XML arguments
- `boot()` / `booted()` for every-request setup — use for authorization checks
- `hydrate()` / `dehydrate()` for request boundary logic, not business logic
- `updating()` / `updated()` for validation and side effects on property changes
- Property-specific hooks (`updatingName`, `updatedName`) over generic hooks when targeting one property
- Never call `$this->render()` manually — the framework handles the render cycle

### 4. Templates & Views → `references/templates.md`

- Single root element required in every component template
- `$magewire` is the component instance — access properties and methods directly
- `$escaper->escapeHtml()`, `$escaper->escapeUrl()`, `$escaper->escapeJs()` for all dynamic output
- `$block->getChildHtml()` for nested Magento blocks inside a Magewire template
- Never echo raw user input — use Magento's escaper, not PHP's `htmlspecialchars()`
- Keep templates thin — logic belongs in the component class, not in PHTML

### 5. Layout XML & Block Registration → `references/layout.md`

- Component class goes in `<argument name="magewire">` — Magewire can be bound to any block class
- Use `name` attribute for unique block identification — Magento merges by name
- Template path uses module notation: `Vendor_Module::template.phtml`
- Register blocks within the page layout handle where they're needed, not globally

### 6. Dependency Injection → `references/di.md`

- Features and Mechanisms in area-scoped DI only (`etc/frontend/di.xml`, `etc/adminhtml/di.xml`) — never global `etc/di.xml`
- Sort order determines boot sequence — check existing registrations before choosing a number
- Use `boot_mode` to control when a service boots: `10` (lazy), `20` (persistent), `30` (always, default)
- Constructor injection via Magento DI for component dependencies — not `ObjectManager::getInstance()`
- Virtual types for DI-only variations — don't create empty subclasses

### 7. Security → `references/security.md`

- CSRF is automatic — Magewire uses Magento's FormKey, no manual token handling needed
- Snapshot checksums prevent state tampering — never bypass checksum validation
- Escape all output in templates — `$escaper->escapeHtml()` is the default, use specific escapers for URLs, JS, attributes
- Public methods are callable from the frontend — never expose admin actions or destructive operations without authorization
- Public properties are visible to the client — never store secrets, API keys, or session data
- Rate limiting is handled by the `SupportMagewireRateLimiting` feature via configuration, not attributes

### 8. Events & Communication → `references/events.md`

- `$this->dispatch('event-name')` for cross-component communication
- `#[On('event-name')]` attribute for declarative listeners — preferred over `$listeners` array
- `->self()` to scope events to the dispatching component only
- `->up()` to dispatch to the parent component
- Kebab-case event names (`cart-updated`, not `cartUpdated`)
- Don't use events for parent-to-child — pass data via layout XML arguments or properties

### 9. JavaScript Integration → `references/javascript.md`

- CSP-compatible scripts only — use `$magewireFragment->make()->script()->start()/end()`, never raw `<script>` tags
- `magewire:init` for Magewire hooks, `alpine:init` for Alpine registrations, `magewire:initialized` for directives
- Always `{ once: true }` on registration event listeners to prevent double registration
- Access addons via `window.MagewireAddons`, utilities via `window.MagewireUtilities`
- Guard addon access with `addons.has('name')` — addons are optional
- Never depend on `window.Magewire` at registration time — it may not exist yet

### 10. Features & Extensions → `references/features.md`

- Extend `ComponentHook` for lifecycle-based extensions — implement only the hooks you need
- `SupportMagewire*` prefix for Magewire-specific features, `SupportMagento*` for Magento bridge features
- Feature-owned JS/templates live in the feature's folder, not in global `addons/` or `components/`
- Use `storeSet()` / `storeGet()` for component-scoped feature state — not class properties
- Push side effects via `$context->pushEffect()` during `dehydrate()` — never echo output from features
- Facades for public APIs — register with `facade` key in DI config

### 11. Performance → `references/performance.md`

- `$this->skipRender()` when a method call doesn't need to update the DOM
- Avoid `wire:model.live` on high-frequency inputs — use `wire:model.blur` or debounce
- Minimize public properties — every property is serialized on every request
- Lazy-load heavy dependencies — use `boot_mode: 10` for features not always needed
- `wire:loading` for user feedback instead of polling or repeated requests

### 12. Serialization & Synthesizers → `references/synthesizers.md`

- Built-in synthesizers handle: arrays, stdClass, enums, floats, ints, DataObjects
- Custom synthesizers for unsupported types — implement `match()`, `dehydrate()`, `hydrate()`
- Register synthesizers in area-scoped DI with a sort order — first match wins
- `dehydrate()` must return JSON-safe data — no objects, no resources
- Test round-trip serialization: `hydrate(dehydrate($value))` must produce the original value
- Avoid storing Magento models directly — extract needed data into scalar properties

### 13. Conventions & Style → `references/style.md`

- Component classes in `Vendor\Module\Magewire\` namespace — not in `Block\`, `Model\`, or `Controller\`
- One component class per file, named after the component
- `snake_case` for layout XML block names: `checkout.shipping.address`
- `kebab-case` for event names and wire directives: `cart-updated`, `wire:click`
- `PascalCase` for component class names, `camelCase` for methods and properties
- Template files match the component purpose, not the class name: `shipping-address.phtml`, not `ShippingAddress.phtml`
- Feature classes always prefixed with `Support`: `SupportMyFeature`

## How to Apply

1. Identify the file type and select relevant sections (e.g., component → 1, 2, 3; template → 4, 7; DI config → 6; JS → 9)
2. Check sibling files for existing patterns — follow those first per Consistency First
3. For API syntax, load the `magewire` skill for component API or `magewire-architecture` for internals
Loading