Alpine.store initialization patterns. Use when: creating global state stores, registering Alpine stores before Alpine.start(), initializing shared reactive state.
Register stores before Alpine.start() in base.html or a dedicated <script>:
<script>
document.addEventListener('alpine:init', () => {
Alpine.store('sidebar', {
open: false,
toggle() { this.open = !this.open; }
});
});
</script>
<script>
document.addEventListener('alpine:init', () => {
Alpine.store('user', {
isAuthenticated: {{ user.is_authenticated|yesno:"true,false" }},
username: '{{ user.username|escapejs }}',
});
});
</script>
<div x-data>
<button @click="$store.sidebar.toggle()">
<span x-show="!$store.sidebar.open" x-cloak>Open</span>
<span x-show="$store.sidebar.open" x-cloak>Close</span>
</button>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.store('theme', { current: 'dark' });
Alpine.store('notifications', { count: 0, items: [] });
Alpine.store('modal', { active: null, data: {} });
});
</script>
| Pattern | Problem | Fix |
|---|---|---|
Registering store after Alpine.start() | Store unavailable during init | Use alpine:init event |
| Storing ephemeral UI state in global store | Pollutes global namespace | Use x-data for local state |
Calling Alpine.start() twice | Duplicate bindings, errors | Remove extra calls — base.html calls it once |
Inline <script> outside alpine:init | Race condition with Alpine load | Always wrap in alpine:init listener |
Alpine.store(...) called outside alpine:init or after Alpine.start()x-cloak on elements reading from $store& .\.venv\Scripts\python.exe -m ruff check . --fix
& .\.venv\Scripts\python.exe -m ruff format .
& .\.venv\Scripts\python.exe manage.py check --settings=app.settings_dev