Install
$ agentstack add skill-brettatoms-agent-skills-alpinejs ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
AlpineJS Best Practices
Golden Rule: Keep Attributes Short
Never put complex logic in HTML attributes. If your x-data, x-init, or any directive exceeds ~50 characters, extract it.
Directive Cheatsheet
| Directive | Purpose | Example | |-----------|---------|---------| | x-data | Declare reactive component state | x-data="{ open: false }" | | x-init | Run code on component init | x-init="fetchData()" | | x-show | Toggle visibility (CSS display) | x-show="open" | | x-if | Conditional rendering (must wrap `) | | | x-for | Loop (must wrap ) | | | x-bind: / : | Bind attribute to expression | :class="{ active: isActive }" | | x-on: / @ | Listen to events | @click="open = !open" | | x-model | Two-way bind form inputs | x-model="email" | | x-text | Set text content | x-text="message" | | x-html | Set inner HTML | x-html="htmlContent" | | x-ref | Reference element via $refs | x-ref="input" | | x-cloak | Hide until Alpine initializes | x-cloak (add CSS: [x-cloak] { display: none; }) | | x-transition | Apply enter/leave transitions | x-transition or x-transition.duration.300ms | | x-effect | Run reactive side effects | x-effect="console.log(count)" | | x-ignore | Skip Alpine initialization | x-ignore | | x-teleport | Move element to another location | x-teleport="#modals" | | x-modelable | Expose property for external binding | x-modelable="value"` |
Magic Properties
| Property | Description | |----------|-------------| | $el | Current DOM element | | $refs | Access elements with x-ref | | $store | Access global Alpine stores | | $watch | Watch a property for changes | | $dispatch | Dispatch custom events | | $nextTick | Run after DOM updates | | $root | Root element of component | | $data | Access component data object | | $id | Generate unique IDs |
Patterns
❌ BAD: Long Inline JavaScript
✅ GOOD: Extract to Function
function itemList() {
return {
items: [],
loading: true,
error: null,
async fetchItems() {
this.loading = true;
try {
const res = await fetch('/api/items');
this.items = await res.json();
} catch (e) {
this.error = e.message;
} finally {
this.loading = false;
}
}
};
}
✅ GOOD: Simple Inline State
Toggle
Content
✅ GOOD: Global Store for Shared State
document.addEventListener('alpine:init', () => {
Alpine.store('cart', {
items: [],
add(item) { this.items.push(item); },
get total() { return this.items.reduce((sum, i) => sum + i.price, 0); }
});
});
✅ GOOD: Reusable Component with Alpine.data()
document.addEventListener('alpine:init', () => {
Alpine.data('dropdown', () => ({
open: false,
toggle() { this.open = !this.open; },
close() { this.open = false; }
}));
});
Menu
Item 1
✅ GOOD: Form with Validation
function contactForm() {
return {
email: '',
message: '',
errors: {},
validate() {
this.errors = {};
if (!this.email.includes('@')) this.errors.email = 'Invalid email';
if (this.message.length
Send
Event Modifiers
@click.prevent
@click.stop
@click.outside
@click.window
@click.document
@click.once
@click.debounce
@click.throttle
@keydown.enter
@keydown.escape
Transition Modifiers
x-transition
x-transition.duration.300ms
x-transition.opacity
x-transition.scale.90
x-transition:enter.duration.500ms
x-transition:leave.duration.200ms
Quick Decision Guide
- State is 1-3 simple properties? → Inline
x-data="{ open: false }" - Has methods or complex logic? → Extract to
function componentName() { return {...} } - Reused across pages? → Use
Alpine.data('name', () => ({...})) - Shared global state? → Use
Alpine.store('name', {...}) - Long attribute string? → You're doing it wrong. Extract it.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: brettatoms
- Source: brettatoms/agent-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.