Alpine.js coupling
Brew’s browser runtime is built on Alpine.js. You do not install Alpine separately when you load the default /brew/brew.min.js (or brew.js) script — Alpine ships inside that bundle.
Confirmed relationship
Section titled “Confirmed relationship”| Fact | Detail |
|---|---|
| Bundles | Alpine 3.17.x is a direct dependency of @konaframework/brew and is compiled into the IIFE/ESM/CSP builds |
| Globals | window.Alpine and window.Brew are both assigned |
| Plugins registered at start | morph, intersect, sort, resize, collapse, anchor, focus, persist, mask |
| Starts Alpine | Brew.start() calls Alpine.plugin(...), registers Brew interceptors, then Alpine.start() |
| Not a peer-only dep | Apps using the default script do not npm install alpinejs; custom ESM bundlers import from @konaframework/brew which re-exports Alpine |
CSP-oriented pages can load brew.csp.min.js when brew.csp_safe is enabled — same Brew behaviour with an Alpine CSP-safe build path.
$wire magic
Section titled “$wire magic”Brew registers an Alpine magic named wire:
<div x-data> <button type="button" @click="$wire.increment()">+</button> <span x-text="$wire.count"></span></div>Inside a component root (wire:id), $wire is a proxy over that component’s reactive state and server actions. See the JavaScript runtime for the full $wire API ($set, $get, $errors, $refs, $dispatch, …).
How wire:* uses Alpine
Section titled “How wire:* uses Alpine”Most Brew directives compile into Alpine bindings:
| Directive | Alpine bridge |
|---|---|
wire:model |
Alpine x-model against $wire (with Brew modifiers) |
wire:show / wire:text / wire:bind:* |
x-show / x-text / x-bind against $wire |
wire:click and other wire:<event> |
Alpine x-on listeners that fire Brew actions |
| Morph | Alpine Morph plugin with Brew key / ignore / replace hooks |
| Component state | Alpine.reactive(...) ephemeral + server snapshot |
Root elements with wire:id are Alpine root selectors (Alpine.addRootSelector(() => '[wire\\:id]')).
Coexistence with x-*
Section titled “Coexistence with x-*”You can mix Alpine UI with Brew state on the same tree:
<div wire:id="…" x-data="{ open: false }"> <button type="button" @click="open = !open">Menu</button> <div x-show="open" x-cloak> <button type="button" wire:click="save">Save on server</button> </div></div>Rules of thumb:
- Server state — put it on the component (
var/ public field) and bind withwire:modelor$wire. - Ephemeral UI — open/close, hover chrome, client-only animations — use Alpine
x-data. - Name clashes — Brew’s expression evaluator prefers
$wiretargets for action expressions so Alpine keys with the same name do not steal server method calls. x-modelable— custom Crema/Alpine controls that exposex-modelablework withwire:model.
Entangle
Section titled “Entangle”Keep an Alpine value and a Brew property in sync:
<div x-data="{ local: @entangle('count') }"> <input x-model="local" /></div>Or from JS: $wire.$entangle('count') / .live variants. See @entangle in templates and the entangle feature in the runtime.
Events across Alpine and Brew
Section titled “Events across Alpine and Brew”- Brew
dispatch('saved')becomes a browserCustomEventthat Alpine can hear withx-on:saved.window. - Alpine
$dispatch('saved')can be listened to withwire:savedor Brew JS listeners. - Global:
Brew.on('saved', …)/Brew.dispatch('saved', …).
Avoiding double Alpine
Section titled “Avoiding double Alpine”If another script also loads Alpine onto window.Alpine after Brew’s bundle, Brew logs a warning (Detected multiple instances of Alpine running). Prefer:
- Default: only
@brewScripts/ injected Brew script, or - Custom: set
window.brewScriptConfig, import{ Brew, Alpine }from@konaframework/brew, register your plugins, then callBrew.start()once.
import { Brew, Alpine } from '@konaframework/brew'// optional: Alpine.plugin(yourPlugin)Brew.start()When window.brewScriptConfig is defined, Brew skips the automatic DOMContentLoaded start so your bundle owns boot order.
@script and component modules
Section titled “@script and component modules”Component scripts run with $wire in scope:
@script<script> $wire.$watch('count', value => console.log(value))</script>@endscriptMulti-file components may ship a sibling .js module (export default function ($wire) { … }) loaded through effects.
Practical checklist
Section titled “Practical checklist”- Load one Alpine (Brew’s) unless you intentionally replace it via ESM.
- Use
wire:*for server round-trips; usex-*for local UI. - Register hooks on
brew:init(before Alpine finishes starting). - For CSP apps, enable
brew.csp_safeand serve the CSP bundle.
- JavaScript runtime — hooks, morph, interceptors
- Examples → Alpine UI — worked patterns
- Actions — calling methods from Alpine