Coding For Websites
by Adrian Goldner

How to structure your AlpineJS Code into modules

I really love AlpineJS. It just got the right balance between ease of use & must-have JavaScript features. I like to think of it as a jQuery-alternative plus two-way bindings without the heavy load of a framework like Vue or React.

However, I still use a bundler (Rollup most of the time) to organize my code into modules. And since AlpineJS resides globally in the window scope (one drawback of its simplicity) you can't bundle it up into single components as easily as in Vue, for example.

And because I like to organize my code into little chunks I'll show you the pattern I use to write my AlpineJS-Components:

Create the Main Entry-File

I use to call my main entry JavaScript-File main.js or site.js and it looks something like this:

// Import the all-mighty AlpineJS
import "alpinejs";

// Component to bootstrap our site
import App from "./components/App";

// import any components you might want to use now:
import { initNavigation } from "./components/Navigation";
import { initExampleComponent } from "./components/ExampleComponent";

// Start the app!
App(() => {

As you can see after importing alpine I import a main component called App that is responsible for bootstrap and start all components. In my components, I only export one init-function that gets called in the App-Component's callback.

Create the App-Component

The App-Component looks like the following:

// components/App.js
export const App = fn => {
  if (document.readyState != "loading") {
  } else {
    document.addEventListener("DOMContentLoaded", fn);

export default App;

Yeah, it's just as simple as it gets.

The App-Component takes only a callback function fn as an argument which will then be called if the DOM is ready to handle our JavaScript code.

Our first AlpineJS Component

Then you can create your individual components like so:

// components/ExampleComponent.js
 * Initialize our component here!
export const initExampleComponent = () => {
  // First, check if this component has to be initialized
  if (hasExampleComponent()) {
    // then, fire it up!

 * Checks if page has autocomplete component
 * @return {Boolean}
const hasExampleComponent = () => {
  return document.getElementsByClassName("example-component").length > 0;

// Start our component
const start = () => {
  	// initialize your alpine component here into the window object
  	window.example = () => {
      return {
        isOpen: false,
        // ... and so forth

I like this approach a lot because it is pretty transparent and you only "pollute" the main window scope if the given component exists on the site. That might be unnecessary with, for example, a navigation component because you might want to render it on every page but I used this pattern many times for small components that were used only on a few pages. It just keeps my code tidy.

Do you like this pattern? Is it something you do already when using AlpineJS?

If you like to, we can chat on Twitter!