Modular Alpine.js toolkit — headless stores, magics, directives, and shared infrastructure. TypeScript-first, tree-shakeable, SSR-safe. Framework-agnostic: works with Vite, Astro, static HTML, or any ESM bundler.
Built by ailuracode. 38 independent npm packages; install only what you need.
Alpine gives you reactivity in HTML. This monorepo adds headless, framework-agnostic modules coordinated by a shared core:
@ailuracode/alpine-core— controller primitives (BaseController,EventEmitter,CleanupStack,ToolkitError), the singleton registry, and Alpine registration guards that throwRegistrationErroron collisions instead of silently overwriting your$store.
You wire your own CSS — no Tailwind or data-theme baked in. Plugin logic lives in headless controllers so you can drive state from any stack (Blade, Livewire, Astro, vanilla TS) and bridge it into Alpine when you want reactive UIs.
pnpm add alpinejs \
@ailuracode/alpine-core \
@ailuracode/alpine-theme \
@ailuracode/alpine-media \
@ailuracode/alpine-scroll \
@ailuracode/alpine-toastimport Alpine from "alpinejs";
import { themePlugin } from "@ailuracode/alpine-theme";
import { mediaPlugin } from "@ailuracode/alpine-media";
import { scrollPlugin } from "@ailuracode/alpine-scroll";
import { toastPlugin } from "@ailuracode/alpine-toast";
Alpine.plugin(themePlugin());
Alpine.plugin(mediaPlugin());
Alpine.plugin(scrollPlugin());
Alpine.plugin(toastPlugin());
Alpine.start();
// Theme is CSS-framework agnostic — apply your own classes via subscribe:
Alpine.store("theme").on("change", (detail) => {
document.documentElement.classList.toggle("dark", detail.resolved === "dark");
});Code-split heavy plugins with dynamic import():
import Alpine from "alpinejs";
const plugins = [
() => import("@ailuracode/alpine-theme").then((m) => m.themePlugin()),
() => import("@ailuracode/alpine-media").then((m) => m.mediaPlugin()),
() => import("@ailuracode/alpine-toast").then((m) => m.toastPlugin()),
];
await Promise.all(plugins.map((load) => load().then((p) => Alpine.plugin(p))));
Alpine.start();See Getting started for HTML usage, registration guards, and CDN patterns.
| Package | Description |
|---|---|
@ailuracode/alpine-core |
Controller primitives, singleton registry, Alpine registration guards, controller↔store/directive bridge |
Start here for most Alpine apps.
| Package | API | Description |
|---|---|---|
@ailuracode/alpine-theme |
$store.theme, $theme |
Light / dark / system preference, headless ThemeController |
@ailuracode/alpine-media |
$store.media |
Viewport breakpoints and media features |
@ailuracode/alpine-scroll |
$store.scroll |
Scroll tracking and body lock for overlays |
@ailuracode/alpine-sidebar |
$store.sidebar |
Sidebar / drawer shell state |
@ailuracode/alpine-lang |
$store.lang |
Browser-language detection and reactive current-language store |
| Package | API | Description |
|---|---|---|
@ailuracode/alpine-env |
$network, $visibility, $battery, $platform |
Browser environment magics |
@ailuracode/alpine-transfer |
$clipboard, $share, $export |
Outbound data transfer magics |
@ailuracode/alpine-toggle |
$toggle |
Binary and ternary toggle state machines |
@ailuracode/alpine-timer |
$timer |
Countdown, countup, and stopwatch factories |
@ailuracode/alpine-form |
$store.form |
Headless form state, validation, and submission lifecycle |
@ailuracode/alpine-child |
x-child |
asChild-style attribute transfer to first child |
@ailuracode/alpine-gesture |
$store.gesture, x-gesture |
Headless gesture recognition — tap, swipe, pan, pinch, long press |
| Package | API | Description |
|---|---|---|
@ailuracode/alpine-overlay |
$store.overlay |
Portal root, z-index stack, overlay registry |
@ailuracode/alpine-permissions |
$store.permissions, $permissions |
Browser permission registry + adapter contract |
@ailuracode/alpine-keyboard |
$store.keyboard, $keyboard |
Scoped keyboard shortcut registry with chords and sequences |
@ailuracode/alpine-dialog |
$store.dialog |
Accessible modal state and focus trap |
@ailuracode/alpine-menu |
$store.menu |
Exclusive dropdown/context menu keyboard navigation |
@ailuracode/alpine-tooltip |
$store.tooltip |
Tooltip positioning and delays |
@ailuracode/alpine-toast |
$store.toast, $toast |
Headless toast queue; fromPayload for plain objects |
@ailuracode/alpine-tabs |
$store.tabs |
Accessible tabs with URL sync |
@ailuracode/alpine-accordion |
$store.accordion |
Single/multi accordion state |
@ailuracode/alpine-command |
$store.command |
Command palette / Spotlight |
@ailuracode/alpine-carousel |
$store.carousel |
Embla-powered accessible carousel |
@ailuracode/alpine-virtual |
$store.virtual, $virtual |
Headless virtual list controller |
@ailuracode/alpine-selection |
$store.selection, $selection |
Headless selection primitives |
@ailuracode/alpine-collection |
createCollectionController<T, K>() |
Headless filter/sort/group/paginate controller (no Alpine plugin yet) |
@ailuracode/alpine-history |
$store.history, $history |
Headless undo/redo history controller |
@ailuracode/alpine-realtime |
$store.realtime, $realtime |
Headless realtime transport (SSE/WebSocket via realtimePlugin from @ailuracode/alpine-realtime/alpine) |
| Package | API | Description |
|---|---|---|
@ailuracode/alpine-geo |
$store.geo |
Geolocation |
@ailuracode/alpine-attention |
$wakelock, $idle |
Wake Lock and Idle Detection |
@ailuracode/alpine-notify |
$notify |
Web Notifications |
@ailuracode/alpine-calendar |
$calendar |
Calendar date logic (date-fns) |
@ailuracode/alpine-json-api |
$jsonapi |
Typed JSON:API client |
| Package | Description |
|---|---|
@ailuracode/alpine-query |
Store-agnostic query cache (createQueryClient, query({ adapter })) |
@ailuracode/alpine-query-kit |
Recommended — query + Nanostores adapter; headless main entry |
@ailuracode/alpine-query-kit/devtools |
Styled Query Devtools panel (development-only subpath, ALP-36 exception) |
@ailuracode/alpine-query-adapter-alpine |
Native Alpine.reactive adapter |
@ailuracode/alpine-query-adapter-zustand |
Zustand vanilla adapter |
The apps/demo/ directory is a Starlight documentation site plus an interactive playground. It is part of the pnpm workspace and is not published to npm.
pnpm install
pnpm run dev:demo/— documentation site (Starlight, from Starlight pages inapps/demo/src/pages)/playground/— live Alpine.js demos (Essentials highlighted)
See AGENTS.md for the full checklist when adding a plugin or package.
- Getting started — install, registration, HTML usage, CDN
- Plugin events — typed
on/once/offand event lifecycle - Permissions — adapter contract for browser permissions
- Query stack — store-agnostic cache and adapters
- Device detection — media/env/toggle/realtime cross-package patterns
- E2E testing — Playwright harness and conventions
- Plugin reference: see each package's
README.md(canonical, npm-published) - Toggle reference — single canonical plugin doc kept under
docs/plugins/ - AGENTS.md — guide for AI agents and maintainers
pnpm install # install all workspaces
pnpm test # full test suite (required before release)
pnpm run lint # biome check (strict)
pnpm run lint:fix # auto-fix
pnpm run format # biome format --write
pnpm run typecheck # tsc --noEmit across packages
pnpm run build # compile all packages to dist/
pnpm run test:coverage # coverage thresholds
pnpm run pack:check # pnpm pack dry-run for publishable packages
pnpm run repo:check # validate monorepo wiring consistency
pnpm run repo:check:built # repo:check plus built export artifact validation
pnpm run architecture:check # enforce source-level architecture invariants
pnpm run changeset:check # verify pending changesets
pnpm test:watch # vitest watch mode
pnpm run test:e2e # Playwright E2E suite
pnpm run test:e2e:affected # E2E only on affected packages
pnpm run size # per-package size-limit budgetsThis repository uses manual publishing with Changesets. CI (ci.yml) only validates — it never versions or publishes. A maintainer performs the release locally.
pnpm run changeset # 1. add a changeset after a user-facing change
pnpm run version # 2. bump versions + generate CHANGELOGs (commits the bump)
pnpm run release # 3. build + test + publish changed packages to npm- Versioning — create a changeset for every consumer-observable change (
patchbug fix,minornew API,majorbreaking). Runpnpm run versionto apply pending changesets, which bumpspackage.jsonversions and appends CHANGELOG entries. Commit the result. - Changelog — Changesets writes
CHANGELOG.mdper package automatically; no manual edit needed. - npm publishing — requires npm 2FA and access to the
@ailuracodescope. Authenticate withnpm login, thenpnpm run release(builds, runs tests, and publishes unpublished versions viachangeset publish). - Provenance — publishes use
publishConfig.access: "public". Configure npm provenance per package if your account supports it; it is opt-in and does not block manual release. - Failure recovery — if publish partially fails, rerun
pnpm run releaseafter fixing the cause. Changesets only publishes versions not yet on the registry, so already-published packages are skipped.
CI and release permissions are intentionally separate: the GitHub Actions workflow has no
NPM_TOKENand cannot publish. Only a maintainer with npm credentials can.
Each package under packages/* has its own version, tests, and README.
MIT