Working with Alpine.js
yStore storefronts use Alpine.js v3 for all client-side reactivity. Alpine.js is initialized globally and yStore's templates are built around its directives.
Alpine.js version
yStore uses Alpine.js v3. If you are looking at external tutorials, make sure they target v3 — the API changed significantly from v2.
Core directives you'll use
| Directive | Purpose |
|---|---|
x-data | Define a component's reactive data and methods |
x-bind | Bind HTML attributes to data values |
x-on / @ | Listen for events |
x-show | Conditionally show/hide an element |
x-if | Conditionally render an element (no DOM node when false) |
x-for | Loop over arrays |
x-text | Set element text content |
x-model | Two-way bind form inputs |
x-ref | Get a reference to a DOM element |
x-effect | Run a side effect when data changes |
x-init | Run code on component initialization |
x-defer | yStore custom — lazy-load components (see below) |
A minimal Alpine component
<div x-data="{ open: false }">
<button @click="open = !open">Toggle</button>
<div x-show="open">
Hello from Alpine!
</div>
</div>
Calling a function on init
<div x-data="myComponent()" x-init="init()">
<p x-text="message"></p>
</div>
<script>
function myComponent() {
return {
message: '',
init() {
this.message = 'Loaded!';
}
};
}
</script>
Listening to yStore events
yStore dispatches custom window events that Alpine components can listen to:
<div x-data="{ count: 0 }"
@private-content-loaded.window="count = $event.detail.cart?.itemCount ?? 0">
<span x-text="count"></span> items in cart
</div>
See JavaScript Events for the full list of events yStore dispatches.
The x-defer directive
yStore ships a custom x-defer Alpine plugin for lazy-loading heavy components:
<!-- Load when element enters the viewport -->
<div x-data="heavyComponent()" x-defer="intersect">
...
</div>
<!-- Load after user first interacts with the page -->
<div x-data="heavyComponent()" x-defer="interact">
...
</div>
See x-defer Directive for all options.
Communication between Alpine components
Components cannot directly share state. Use window events instead:
<!-- Dispatcher -->
<button @click="$dispatch('cart-updated', { count: 3 })">Update</button>
<!-- Listener (different component on the same page) -->
<div x-data @cart-updated.window="count = $event.detail.count">...</div>
See Patterns → Communication Between Alpine Components for more examples.
Useful resources
- Alpine.js documentation — official docs
- Alpine.js v3 migration guide — if migrating from v2
- Awesome Alpine — community plugins and examples