Alpine.js V3: A Mono-Repo Tour of Plugins Built With ESBuild
You've probably used Alpine.js at some point—that lightweight JavaScript framework that lets you sprinkle interactivity into your HTML without reaching for a full SPA setup. But have you ever wondered how the project itself is organized behind the scenes? The Alpine.js repository isn't just the core library anymore. It's a mono-repo of plugins, all bundled together with ESBuild, and it's worth a look if you're curious about how modern JavaScript projects structure themselves.
What It Does
At its core, this repository is the home of Alpine.js V3. But the README makes it clear: if you're looking for documentation on how to use Alpine, you should head over to the Alpine docs site. This repo is primarily for contributors and anyone interested in the internals.
The repository uses npm workspaces to manage a mono-repo structure. Each package lives in its own folder under /packages, and rather than running separate builds for each one, a single npm run build command handles all the package bundles. The bundling is done exclusively with ESBuild, and all the configuration lives in a single scripts/build.js file.
Here's what's in the box: the main alpinejs package contains all of Alpine's core. Then there's a collection of plugins, each doing something specific—collapse for smooth expand/collapse animations, csp for a CSP-safe build, focus for managing focus within an element, history for binding data to query string parameters via the history API, intersect for triggering expressions when elements enter the viewport, mask for auto-formatting text inputs as users type, morph for intelligently morphing HTML (similar to morphdom), and persist for keeping Alpine state across page loads. There's also a docs package where the documentation lives.
Each package produces at least two builds: a "cdn" build that's self-initializing and can be dropped into a <script defer> tag, and module files (module.esm.js and module.cjs.js) for importing as a JavaScript module.
Why It's Cool
-
One build command to rule them all. Instead of juggling separate build processes for each package, the mono-repo setup means you run
npm run buildonce and everything compiles. That's a small thing that adds up to a lot of saved time when you're working across multiple packages. -
ESBuild keeps things fast. Alpine V3 moved to ESBuild exclusively for bundling. If you've ever waited on a Webpack build, you know why this matters. The configuration is centralized in one file, so there's no hunting through dozens of config files to figure out what's going on.
-
The plugin architecture is genuinely modular. Each plugin does one thing and does it well. Need to format phone numbers as users type? Grab the
maskplugin. Want to persist a dropdown's open state across page reloads? That'spersist. You're not pulling in a massive dependency just to get one feature. -
CSP-safe builds are a first-class concern. The
csppackage exists specifically to provide a version of Alpine that works with strict Content Security Policies. That's not an afterthought—it's a dedicated package, which tells you the maintainers care about environments where inline scripts aren't allowed. -
Testing is split sensibly. Cypress handles integration tests, Vitest handles unit tests. Both live under
/tests, and you can run them independently. If you're doing development work, the README recommendsnpm run cypressto open the Cypress UI, which is a nice touch for debugging.
How to Try It
Getting started is straightforward. First, clone the repo:
git clone https://github.com/alpinejs/alpine
cd alpine
Then install dependencies and build everything:
npm install
npm run build
Once that's done, you can include the compiled CDN build in any webpage:
<script defer src="/packages/alpinejs/dist/cdn.js"></script>
If you want to work on a specific plugin, you can find its compiled output in packages/[package]/dist. For development, you might prefer running npm run watch instead of npm run build so changes rebuild automatically.
Testing is split between two tools. Run npm run cypress to open the Cypress UI (recommended during development), or npm run vitest to run unit tests directly.
The full repository is at github.com/alpinejs/alpine.
Final Thoughts
This repo is really for two audiences: contributors who want to work on Alpine.js itself, and developers curious about how a modern mono-repo with ESBuild is structured. If you're just looking to use Alpine in your project, you don't need to clone anything—just grab it from a CDN and read the docs. But if you've ever thought about contributing to an open-source project, or you're setting up your own mono-repo and want to see how someone else did it, this is a solid reference. The plugin-based architecture and the single-build-command approach are both worth studying.