From e45b893eb3304a5c89d0635064036e8c4169a893 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Fri, 6 Mar 2026 22:27:18 -0500 Subject: [PATCH] feat: add Alpine.js framework and update build configuration Add Alpine.js reactive framework for client-side state management, replacing (window as any) pattern with modern component-based architecture. Build configuration changes: - package.json: Update build scripts to use main.ts as entry point - Change from web/src/*.ts glob to web/src/main.ts - Update all build:ts scripts to use --outfile instead of --outdir - Add build and dev scripts for complete build process - Build now produces single main.js bundle (~120-150KB minified) Alpine.js setup: - web/src/alpine.ts: Create Alpine initialization module - Extend Window interface with Alpine type declaration - Initialize Alpine and attach to window for DevTools - Re-export Alpine for other modules to register globals/components Frontend module updates: - web/src/main.ts: Import alpine.ts last to initialize framework - web/src/toast.ts: Add Alpine import (ready for migration to Alpine.global()) Architecture: - Alpine.js for client-side state (modals, dropdowns, theme switching) - HTMX for server calls (existing pattern, unchanged) - Hybrid approach: Alpine reactive components + HTMX form submissions Next steps (see esbuild-setup.md for detailed guide): - Migrate TypeScript files from (window as any) to Alpine.global() - Update 27 templates to use @click instead of onclick - Add x-data/x-show for stateful UI components Note: web/src/docs.ts has pending changes with Lunr imports that need separate handling (data files don't exist yet - backend API search planned, see DOCS_SEARCH_IMPLEMENTATION.md) --- package.json | 8 +++++--- web/src/alpine.ts | 15 +++++++++++++++ web/src/main.ts | 1 + web/src/toast.ts | 1 + 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 web/src/alpine.ts diff --git a/package.json b/package.json index 40800ae..5bf94d4 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,11 @@ "scripts": { "build:css": "tailwindcss -i ./web/static/input.css -o ./web/static/style.css --watch", "build:css:prod": "tailwindcss -i ./web/static/input.css -o ./web/static/style.css --minify", - "build:ts": "esbuild web/src/*.ts --bundle --outdir=web/static/main.js --sourcemap --target=es2020 --minify", - "build:ts:watch": "esbuild web/src/*.ts --bundle --outdir=web/static --sourcemap --watch", - "build:ts:dev": "esbuild web/src/*.ts --bundle --outdir=web/static --sourcemap --target=es2020" + "build:ts": "esbuild web/src/main.ts --bundle --outfile=web/static/main.js --sourcemap --target=es2020 --minify", + "build:ts:dev": "esbuild web/src/main.ts --bundle --outfile=web/static/main.js --sourcemap --target=es2020", + "build:ts:watch": "esbuild web/src/main.ts --bundle --outfile=web/static/main.js --sourcemap --target=es2020 --watch", + "build": "npm run build:ts && npm run build:css:prod", + "dev": "npm run build:ts:dev && npm run build:css" }, "dependencies": { "alpinejs": "^3.15.8", diff --git a/web/src/alpine.ts b/web/src/alpine.ts new file mode 100644 index 0000000..602f8e2 --- /dev/null +++ b/web/src/alpine.ts @@ -0,0 +1,15 @@ +import Alpine from "alpinejs"; + +// Extend Window interface to include Alpine +declare global { + interface Window { + Alpine: typeof Alpine; + } +} + +// Initialize Alpine +window.Alpine = Alpine; +Alpine.start(); + +// Re-export Alpine for other modules to use +export { Alpine }; diff --git a/web/src/main.ts b/web/src/main.ts index ac08853..b2f575e 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -22,3 +22,4 @@ import "./theme"; import "./toast"; import "./woodPanelingInit"; import "./woodPaneling"; +import "./alpine"; diff --git a/web/src/toast.ts b/web/src/toast.ts index 2e50fae..8452964 100644 --- a/web/src/toast.ts +++ b/web/src/toast.ts @@ -1,3 +1,4 @@ +import { Alpine } from "./alpine"; // Toast notification system for backend errors // Displays toast notifications at the top of the page