mrkeyoor.com_
Thu 03 Sept 06:55 UTC
Webevaluationupdated 03 Sept 2026

alpine review

Alpine.js adds reactive state and event handling directly to HTML attributes, so a mostly server-rendered page can gain dropdowns, filters, and other small interactions without becoming a full client application. It solves the gap between plain DOM code and a larger component framework.

Verdict

Our Alpine install took 35 seconds and its build took 9 seconds, but tests stopped after 10 seconds because Cypress 15.18.0 could not find Xvfb. The runtime is an easy recommendation for modest interaction on server-rendered pages, especially when a script tag and HTML-first state are desirable. Contributors and strict-CSP teams should budget for the missing browser package and the CSP build's expression limits, while form-heavy apps should test the open dependent-select regression.

We ran it

Lab card: what happened when we ran alpineScreenshot of alpine (alpinejs.dev)
Install✓ · 35s622 packages · 145 MB
Build✓ · 9s
Tests✗ · 10sran, no count parsed
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)
Repo309 files~29,331 lines of source · 5.8 MB · 3 CI workflows · tests dir

Answers from our run

Does alpine build from source?

Dependencies installed in 35 seconds (622 packages), and the build succeeded in 9 seconds. We cloned commit 8579eab into a clean Debian container with 3 CPUs and no project-specific setup.

Do alpine's tests pass?

The test command failed in our container, and its output did not report a pass or fail count.

Does alpine have known vulnerabilities in its dependencies?

npm audit found none in the dependency tree at the time of our run.

Who should not use alpine?

Contributors expecting npm test to work in a fresh Debian container from the README alone: our run stopped because Cypress could not find Xvfb, which the contribution guide does not mention.

What are the alternatives to alpine?

htmx, Petite Vue, Stimulus. Our Alpine install took 35 seconds and its build took 9 seconds, but tests stopped after 10 seconds because Cypress 15.

Setup3/5Build passed in 9 seconds; Cypress needed undocumented Xvfb
Docs4/5User and CSP guides are clear; contributor setup misses Xvfb
Community5/531,902 stars, a fresh release, and only 4 open issues and PRs
Maturity4/5v3.17.1 is active, with one current select regression to watch

Who it’s for

Server-rendered sites that need small interactive pieces while keeping HTML in charge.
Developers who prefer declarative attributes such as x-data, x-show, and x-model over manual DOM wiring.
Teams that want a CDN script for simple pages and an npm module for bundled applications.
Plugin authors who need public directive, state, reactivity, and cleanup hooks.

Who it’s NOT for

Contributors expecting npm test to work in a fresh Debian container from the README alone: our run stopped because Cypress could not find Xvfb, which the contribution guide does not mention.
Storage-constrained contributors who read "minimal" as a description of the repository toolchain: our install pulled 622 packages and used 145 MB.
Strict-CSP applications that need arrow functions, destructuring, global browser objects, template literals, or x-html inside directives: the CSP build documents those as unsupported.
Forms that depend on unmatched values in linked selects without regression testing: open issue 4885 describes a visible option diverging from its x-model value.
Teams that prohibit executable expressions in HTML attributes: that pattern is central to Alpine's standard build and its x-on, x-data, and binding APIs.

Setup reality

Our sandbox installed 622 npm packages in 35 seconds and used 145 MB, then the build passed in 9 seconds. Tests failed after 10 seconds because Cypress 15.18.0 could not spawn Xvfb (ENOENT). The npm audit found 0 known vulnerabilities.

Using Alpine on a page needs no account, key, database, or hosted service. The docs support a deferred CDN script or an npm import, while repository work uses Node 22, npm workspaces, esbuild, Cypress, and Vitest.

The contributor README says to run npm install, build, and test, but it does not name Xvfb. The repo has no Dockerfile to supply browser dependencies. Strict content-security policies also require the separate CSP package, whose expression support is narrower.

Alpine 3.17.1 keeps state beside the HTML it changes

Alpine 3.17.1 lets a page declare local state with x-data, listen with x-on, bind form values with x-model, and show or repeat elements through directives. The result resembles a small template system embedded in ordinary markup. That is useful on a server-rendered product where a dropdown, search filter, or disclosure panel does not justify handing the entire page to a client router and component build. The browser remains the runtime, and the HTML remains readable as the interface.

The design is easy to see in the official counter example: one object holds a count, one click expression changes it, and one text directive displays it. commit 8579eab was the v3.17.1 version bump we tested. The repository around that small example is a 309-file npm workspace with roughly 29,331 source lines, because Alpine also carries its documentation, test suites, build tooling, and official plugins in the same checkout.

The 5.8 MB checkout installs 145 MB of tooling

Our clean checkout occupied 5.8 MB before installation. npm then added 622 packages in 35 seconds and used 145 MB on disk. That is contributor tooling rather than a claim about Alpine's browser payload, which our lab did not measure. The distinction matters because the project's "minimal" positioning describes how developers add behavior to a page, while cloning and changing the framework still brings a normal JavaScript monorepo with browser tests and bundling dependencies.

The workspace contains Alpine core, docs, a CSP variant, and plugins for jobs such as focus, collapse, intersection observation, masking, morphing, and persisted state. esbuild handles the package bundles, with CDN, ESM, and CommonJS outputs described in the repository guide. Our scan found 3 CI workflow files, a tests directory, and no Dockerfile. That last absence became relevant when the 10-second test command reached a missing graphical-system dependency.

What happened when we ran it

Our sandbox installed 622 npm packages in 35 seconds, and the build completed successfully in 9 seconds. The test step then exited with code 1 after 10 seconds. Cypress 15.18.0 reported that the system dependency Xvfb was missing, followed by Error: spawn Xvfb ENOENT on Debian 12. The run used 3 CPUs, 8 GB of RAM, the lab-node:22 image, and an unprivileged container with no secrets.

The log tail does not show an Alpine assertion failure or a completed test count. It shows that Cypress could not start its display layer, so the fair finding is that the documented contributor commands were insufficient in our fresh environment. We did not install Xvfb and rerun because that result is outside the supplied lab record. The npm audit did complete and reported 0 known vulnerabilities at commit 8579eab, with 0 critical, high, moderate, or low findings.

Production setup is shorter than the repository test setup

Version 3.17.1 can be loaded with one deferred CDN tag or installed as the alpinejs npm package. The documentation recommends pinning the exact CDN version for production instead of following the floating 3.x line. Bundled applications import Alpine, optionally expose it on window, and call Alpine.start() once. Plugins and custom directives must register before that call, while script-tag extensions listen for the alpine:init event. None of those paths requires credentials or a backend service.

A consumer should not confuse that small adoption surface with our 622-package contributor install. Building the repository creates each workspace bundle, and npm test launches Cypress rather than the separate Vitest command. The README names both test tools but leaves the Linux display package implicit. Since the repo supplies no Dockerfile, a team standardizing contribution environments should record Xvfb in its own image or setup notes before expecting the 10-second failure to disappear.

Strict CSP uses a separate build with fewer expressions

Alpine 3.17.1 has a dedicated @alpinejs/csp package for sites that disallow unsafe-eval. The standard build evaluates attribute expressions through Function declarations, which still violate that policy even though the project says it does not call eval() itself. The CSP build interprets a supported subset instead. Basic object and array literals, comparisons, updates, method calls, and common bindings remain available, so a counter or menu does not automatically require relaxing the site's script policy.

The subset has real edges. The CSP guide says arrow functions, destructuring, template literals, spread syntax, browser globals, and HTML injection are unsupported in expressions. Complex logic belongs in registered Alpine.data() components. A recently closed 2026 report about escaped string literals in the CSP build received a fix, evidence that this path is maintained. Our 3-CPU sandbox did not execute either runtime because Cypress stopped at Xvfb, so teams with a strict policy should test their own directive expressions.

Four open items and a fresh release show active maintenance

GitHub showed 31,902 stars, 4 open issues and pull requests, and a last push on September 3, 2026. Release v3.17.1 was published on August 31 with an Intersect plugin addition, a dependency update, and a documentation correction. That tiny combined queue is not a bug count, but recent closed items show the repository is processing fixes and contributions. The same week included work on CSP string parsing and a new deferred tree-initialization hook.

One open item deserves attention from form builders. Issue 4885 reports that a dependent select can display its first enabled option while the x-model value remains null, a regression introduced in v3.16.0. Pull request 4888 proposes a fix and Cypress coverage, but it remained open when fetched. Alpine is a good fit for restrained page behavior; compare that exact form pattern before adopting the current line for linked selects.

Alternatives

ProjectWhat it isPick it when
htmx gh↗An HTML-attribute library centered on server requests and swapping returned fragments.pick this instead when the server should own state and return HTML for most interactions.
Petite VueA small Vue subset made for progressive enhancement in existing HTML.pick this instead when Vue-style templates and reactivity are already familiar to the team.
StimulusA modest framework that attaches JavaScript controllers to server-rendered HTML.pick this instead when behavior belongs in controller modules rather than inline expressions.

What people are saying

  1. [velocity-scout] alpinejs/alpine

Sources

  1. Alpine.js README
  2. Alpine.js repository
  3. Alpine.js installation guide
  4. Alpine.js CSP guide
  5. Alpine.js v3.17.1 release
  6. Dependent select model regression
  7. Proposed dependent select fix

More web reviews

drawio · carbon · lexical · spring-framework · livewire · axios · the whole board →