$ show alpinejs/alpine
Alpine.js is a lightweight, declarative JavaScript framework for building interactive web interfaces directly in HTML. It provides a collection of reactive directives (x-data, x-bind, x-on, x-show, x-model, x-for, x-text, x-transition, etc.) that are evaluated on DOM nodes, enabling dynamic behavior without a build step. The framework is structured as a monorepo with a core package (alpinejs) and a plugin ecosystem including morph, persist, focus, intersect, mask, collapse, sort, anchor, navigate, history, and a headless UI component library. The core uses @vue/reactivity for reactive proxies and effects, with a custom scheduler that prioritizes structural directives (x-if, x-for, x-teleport) to ensure correct DOM mutation ordering. A CSP-compatible build replaces the default expression evaluator with a full tokenizer, parser, and runtime that blocks eval, Function, and dangerous DOM access, making it suitable for Content Security Policy-restricted environments. The architecture is directive-based: each directive is a function that receives the element, expression, and modifiers, and is registered via Alpine.directive(). Magics ($el, $refs, $store, $watch, $id, etc.) provide reactive access to framework internals. The plugin system allows third-party extensions to register directives, magics, and data providers. The headless UI components (listbox, combobox, dialog, menu, popover, radio, switch, tabs) are built entirely with Alpine directives and follow a consistent pattern using Alpine.bind for attribute/event binding and Alpine.magic for exposing component state. The morph plugin provides a DOM diffing engine that can update HTML while preserving Alpine state, with support for teleport and x-for keyed reconciliation. Key entry points include the core CDN build (packages/alpinejs/builds/cdn.js), the CSP build (packages/csp/builds/cdn.js), and individual plugin builds. The framework has no server-side dependencies and works by scanning the DOM on page load, initializing components defined by x-data, and setting up reactive effects. Data flows from component data (defined in x-data or Alpine.data()) through reactive proxies to DOM updates via directives. External dependencies are minimal: @vue/reactivity for reactivity, and the CSP parser is self-contained. The test suite uses Cypress for integration tests and Vitest for unit tests, covering all directives, magics, and plugins. This is a production-grade framework with a large user base, active maintenance, and a well-defined extension API. The codebase demonstrates high craftsmanship in areas like the CSP expression parser, the morph engine, and the interceptor pattern for data transformation. Some legacy code (old_morph.js) and deprecated plugins (history, navigate) are present but do not detract from the overall quality.
The LLM identified 3 files worth highlighting for reuse:
A standalone, security-hardened expression parser that tokenizes, parses, and evaluates JavaScript expressions without using eval or Function. It implements a full tokenizer (with keywords, operators, literals), a recursive descent parser producing an AST, and a runtime evaluator that walks the AST. The evaluator includes a blacklist of dangerous properties and global variables (document, window, innerHTML, etc.) and blocks access to DOM manipulation APIs. This component is fully self-contained and could be extracted and reused in any CSP-restricted environment that needs safe expression evaluation.
A DOM diffing and patching engine that updates HTML while preserving Alpine.js component state. It implements keyed reconciliation (similar to React's diff algorithm) with support for teleport, x-for, and comment markers. The morph algorithm walks two DOM trees, matches elements by key or position, and applies minimal mutations (insert, remove, update attributes, text). It includes lifecycle hooks (before/after morph, before/after update) and handles edge cases like nested Alpine components and cloned state. This is a reusable pattern for any framework needing efficient partial DOM updates.
A middleware pattern for intercepting reactive data access. It allows wrapping a reactive property with custom getters and setters that can transform values on read/write, and supports nesting interceptors. Used internally by $persist (localStorage sync) and $mask (input formatting). The interceptor is registered via Alpine.interceptor() and returns a function that, when called on a reactive property, installs the interceptor. This pattern is self-contained and could be reused in any reactive system to add cross-cutting concerns like persistence, validation, or formatting.