diff --git a/.github/docs/apps.md b/.github/docs/apps.md index ae5fc609..41b6e4ca 100644 --- a/.github/docs/apps.md +++ b/.github/docs/apps.md @@ -1,6 +1,6 @@ # Framework Applications -This project contains the same weather application built using 12 different JavaScript frameworks. Each implementation provides identical functionality but uses the specific patterns and approaches of its framework. +This project contains the same weather application built using 14 different JavaScript frameworks. Each implementation provides identical functionality but uses the specific patterns and approaches of its framework. ## Available Frameworks @@ -17,6 +17,8 @@ The project includes implementations for: **Alpine.js** - Minimal framework with HTML-first approach **Lit** - Web Components with efficient updates **VanJS** - Ultra-small vanilla framework +**Lume.js** - Minimal reactive state library with no build step +**Gea** - Compiler-first reactive framework with surgical DOM updates **Vanilla** - Pure JavaScript without any framework Each app lives in its own directory under `apps/{framework}/` and can be developed, built, and tested independently. diff --git a/apps/geajs/README.md b/apps/geajs/README.md new file mode 100644 index 00000000..cfe68bda --- /dev/null +++ b/apps/geajs/README.md @@ -0,0 +1,65 @@ +# Weather App — Gea + +A weather application built with [Gea](https://geajs.com/) — a compiler-first reactive UI framework that compiles JSX into surgical DOM updates at build time (a hello-world app ships ~121 B of brotli JavaScript). + +## Usage + +```bash +# Install dependencies +npm install + +# Dev server (Vite + @geajs/vite-plugin) +npm run dev + +# Production build +npm run build + +# Run tests (from repo root) +npm run test:geajs + +# Lint (from repo root) +npm run lint:geajs +``` + +## Implementation + +Gea doesn't use signals, hooks, dependency arrays, or a virtual DOM. You write ordinary JavaScript — classes with state and methods, getters for computed values — and the Vite plugin (`@geajs/vite-plugin`) analyzes the JSX at build time, works out which DOM nodes depend on which state paths, and generates the reactive wiring. At runtime only the affected nodes are patched. + +The implementation uses: + +- **`Store`** — [`weather-store.js`](src/weather-store.js) is a singleton class extending `Store`. Its fields (`searchQuery`, `isLoading`, `hasError`, `weatherData`, `activeForecastIndex`) are made reactive through a deep Proxy; mutations are plain assignments like `this.isLoading = true`. +- **Getters as computed values** — derived state such as `showContent`, `locationLabel`, `currentTemperature`, and `forecastDays` are ordinary JavaScript getters on the store. The compiler tracks which state paths they read and re-evaluates the dependent DOM bindings when those paths change. +- **Class components** — each UI piece ([`SearchForm`](src/components/SearchForm.jsx), [`CurrentWeather`](src/components/CurrentWeather.jsx), [`ForecastItem`](src/components/ForecastItem.jsx), …) extends `Component` and returns JSX from `template()`. JSX uses HTML-style attributes (`class`, `for`) and native-style event bindings (`click={...}`, `input={...}`, `submit={...}`) wired through document-level event delegation. +- **Function components** — stateless UI like [`LoadingState`](src/components/LoadingState.jsx) is a plain function; the compiler converts it to a class component at build time. +- **Conditional rendering** — `{condition && }` in [`WeatherDisplay`](src/components/WeatherDisplay.jsx) compiles into `