Alpine.js guidelines
Publica.la currently uses Alpine.js v2 (2.8.2)—see the official README for full API reference.
Folder structure
resources/js/alpine/
alpine-components/
history-back-action.js
summary-cart-component.js
alpine-dashboard.js
alpine-storefront.js
alpine-magic-properties.js
- alpine-dashboard.js: registers stores and components used only by the Dashboard.
- alpine-storefront.js: logic for the Storefront.
- alpine-components/: tiny reusable pieces imported by the previous files.
In Blade:
@push('scripts')
<script type="module" src="{{ mix('js/alpine/alpine-storefront.js') }}"></script>
@endpush
General conventions
- Use
x-on:clickinstead of@click(Vue conflict). - Avoid
x-forwhile the page still loads Vue; loop with Blade or Livewire instead. - Keep as little data as possible in the DOM; store big lists in Livewire.
Example: summary cart component
File summary-cart-component.js:
export default () => ({
items: [],
get subtotal() {
return this.items.reduce((t, i) => t + i.price, 0);
},
add(item) {
this.items.push(item);
this.$dispatch('cart-updated', { count: this.items.length });
},
});
Usage in Blade:
<div x-data="summaryCartComponent()" class="tw-flex tw-gap-2">
<button x-on:click="add({ price: 9.99 })">Add</button>
<span x-text="subtotal.toFixed(2)"></span>
</div>
Accessibility with Alpine
- Sync states with
aria-expanded,aria-pressedvia:aria-expanded="open". - For modals use
x-trap.noscrolland return focus to the invoker button. - Update live regions with
x-effectandaria-live="polite".
Livewire integration
Livewire re-renders DOM fragments:
- Keep Alpine logic outside the area Livewire swaps, or use
wire:key. - In Alpine v3 you can bind to Livewire with
@entangle('property'); in v2 callwindow.livewire.find(componentId).get('property').
Debugging
Install Alpine DevTools. Make sure APP_DEBUG=true in local .env to get stack traces.
We also have access to the UI components created by Caleb (v3 Alpine), which are available in 1Password.
Last updated: 2025-07-14