Skip to main content
Alpine.js is a minimal JavaScript framework for adding interactivity to server-rendered HTML. Think of it as β€œjQuery for the modern web” or β€œTailwind for JavaScript.”

Comparison with Other Approaches

Quick Start

Why Alpine.js?

The Sweet Spot

Alpine occupies the perfect middle ground between vanilla JavaScript and heavy frameworks. It gives you reactive components without the build step or complexity. Vanilla JS:
Alpine:
React (requires build step):

Key Benefits

  • Tiny: ~15kB minified and gzipped
  • No Build Step: Include via CDN and start using
  • Declarative: Write reactive code in HTML
  • Progressive: Add to existing HTML pages
  • Familiar: Syntax inspired by Vue and Angular
  • Composable: Works great with HTMX and other libraries
  • Powerful: Includes directives, magic properties, and plugins

When Alpine Shines

Alpine is perfect when you want:
  • Interactive widgets without a build step
  • Dropdowns, modals, tabs, accordions
  • Form validation and dynamic inputs
  • Progressive enhancement of server-rendered pages
  • To complement HTMX for client-side interactivity
  • Rapid development with minimal JavaScript

Installation

Via CDN

Or use a specific version:
The defer attribute ensures Alpine loads after the DOM is ready.

Via npm

Then import and initialize:

With a Bundler

Architecture

Development Mode

Production Mode

Core Directives

x-data

Declares a new Alpine component with reactive state:

x-show

Toggle visibility with CSS display:

x-if

Conditionally add/remove element from DOM:
x-show vs x-if:
  • x-show: Fast toggle, element stays in DOM, uses CSS display
  • x-if: Slower, removes from DOM, better for heavy components

x-for

Loop over arrays:

x-model

Two-way data binding:

x-on (@)

Event listeners:

x-bind (:)

Bind attributes:

x-text

Set text content:

x-html

Set HTML content (use with caution):
Warning: Only use x-html with trusted content to avoid XSS attacks.

x-init

Run code when component initializes:

x-effect

Re-run code when dependencies change:

x-cloak

Hide element until Alpine initializes:
Prevents flash of unstyled content (FOUC).

x-ignore

Prevent Alpine from initializing:

Magic Properties

$el

Reference the current element:

$refs

Reference elements marked with x-ref:

$watch

Watch for property changes:

$dispatch

Dispatch custom events:

$nextTick

Wait for DOM updates:

$root

Reference root element of component:

$data

Reference component data:

$id

Generate unique IDs:

$store

Access global stores (covered in Stores section).

Advanced Patterns

Reusable Components

Extract components into functions:
Use in HTML:

Stores (Global State)

Create global reactive stores:
Access in components:

Transitions

Built-in transition directives:

Fetching Data

Form Handling

Common Components

Tabs

Accordion

Tooltip

Notification Toast

Autocomplete

With Mizu Backend

API Integration

Backend handler:
Alpine frontend:

With HTMX

Alpine and HTMX work great together. Use HTMX for server interactions and Alpine for client-side UI state:

Alpine Plugins

Persist

Persist state to localStorage:
Values persist across page reloads.

Collapse

Smooth height transitions:

Focus

Manage focus within elements:

Intersect

Trigger when element enters viewport:

Morph

Morph DOM elements (useful with HTMX):

Complete Application Example

Let’s build a complete Todo app with Mizu backend and Alpine frontend.

Backend

app/server/handlers.go:
app/server/routes.go:

Frontend

views/pages/home.html:

Performance

Lazy Initialization

Defer Alpine initialization for better initial load:

Debouncing and Throttling

Reduce unnecessary updates:

Virtual Scrolling

For very long lists, use virtual scrolling (requires plugin or manual implementation).

Minimize Re-renders

Use x-show instead of x-if when toggling frequently:

Security

XSS Protection

Never use x-html with user content:

CSRF Protection

Include CSRF tokens in requests:

Sanitize User Input

Always validate and sanitize on the server:

Testing

Unit Tests

E2E Tests

Troubleshooting

Alpine Not Working

Check:
  1. Alpine script is loaded: <script defer src="..."></script>
  2. Using defer attribute
  3. No JavaScript errors in console
  4. x-data is on parent element

Data Not Updating

Check:
  1. Data property is reactive (defined in x-data)
  2. Modifying data correctly (this.count++ not count++)
  3. No typos in property names
  4. Using Alpine’s reactivity (not vanilla JS)

Events Not Firing

Check:
  1. Event name is correct (@click not @onclick)
  2. Element can receive events
  3. No @click.stop preventing propagation
  4. Handler function exists

Transitions Not Working

Check:
  1. Element uses x-show not x-if (or use x-transition on template parent)
  2. Tailwind classes available
  3. No conflicting CSS

Debug Mode

Enable Alpine devtools:
Then use browser devtools to inspect window.Alpine.

When to Use Alpine

Perfect For

  • Interactive Widgets: Dropdowns, modals, tabs, accordions
  • Form Enhancement: Validation, dynamic inputs, autocomplete
  • Progressive Enhancement: Add interactivity to server-rendered pages
  • Prototypes: Rapid development without build tools
  • Small to Medium Apps: Todo apps, dashboards, admin panels
  • With HTMX: Client-side UI state + server interactions

Not Ideal For

  • Large SPAs: Complex routing and state management
  • Heavy Computation: Better suited for backend or Web Workers
  • Offline-First: No built-in offline support
  • Complex Data Flow: Redux-like patterns harder to implement

Hybrid Approach

Use Alpine for UI state, backend for business logic:

Next Steps

HTMX Guide

Combine with HTMX for server interactions

View Engine

Server-rendered templates with Mizu

Alpine Docs

Official Alpine.js documentation

Alpine Toolbox

Component library and examples

Alpine Examples

Official examples and patterns

Tailwind CSS

Perfect CSS companion for Alpine