Gea Framework: Compiler-First Reactive UI Without Virtual DOM
Technical deep-dive · July 2026

Gea: The Compiler-First
Reactive UI Framework

No virtual DOM. No hooks. No signals. Just plain JavaScript classes compiled into surgical DOM updates — faster than Solid, smaller than Svelte.

Oleg Maximov July 3, 2026 15 min read

What Is Gea?

Gea is a compiler-first reactive UI framework for JavaScript that eliminates the virtual DOM entirely. Instead of diffing at runtime, Gea's Vite plugin analyzes your JSX at build time, traces every state access, and generates surgical DOM patches — code that updates only the specific DOM nodes that depend on changed state. No reconciliation, no diffing, no runtime overhead.

Created by Armagan Amcalar (known in the JavaScript community as dashersw), Gea represents the culmination of 16 years of framework design experience. Amcalar previously created tartJS (the framework behind the world's first client-side rendered single-page e-commerce application) and erste (a modernized version that powered mobile apps in Cordova shells). Gea v1.3.0, released in June 2026, is the third generation of this vision.

Key Highlights

Writing Components in Gea

The core idea is that JavaScript is enough. You don't need to learn new primitives — just write plain classes.

Counter Component

Here's a complete interactive counter component in Gea:

class Counter extends Component {
  count = 0

  increment() { this.count++ }
  decrement() { this.count-- }

  template() {
    return (
      <div class="counter">
        <span>{this.count}</span>
        <button click={this.increment}>+</button>
        <button click={this.decrement}>-</button>
      </div>
    )
  }
}

That's everything. State is a class property. Methods mutate it directly. The template reads it. this.count++ triggers a DOM update. No useState, no signals, no dependency arrays, no wrappers. Just a JavaScript class.

The compiler traces that this.count is used inside the JSX template. When count changes, it generates a surgical patch that updates only the <span> containing the value — not the whole component, not a virtual DOM subtree.

Shared State with Stores

For state shared between components, Gea provides Store — a Proxy-wrapped base class:

class CounterStore extends Store {
  count = 0

  increment() { this.count++ }
  decrement() { this.count-- }
}

Stores work exactly like component-local state: plain properties, plain methods. The Proxy wrapper intercepts property access so the compiler can track dependencies and trigger updates when values change. Arrays are intercepted at the method level — push, splice, sort, and other mutating methods produce fine-grained change events.

Computed Getters

Computed values are just JavaScript getters:

class TodoStore extends Store {
  items = []

  get activeCount() {
    return this.items.filter(i => !i.done).length
  }

  get completedCount() {
    return this.items.filter(i => i.done).length
  }
}

The compiler recognizes getters that depend on store properties and re-evaluates them automatically when their dependencies change. No explicit memoization needed.

Function Components

Gea also supports function components for simpler cases:

function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>
}

Function components receive props as a destructured argument and return JSX. They're compiled the same way as class components — no runtime overhead difference.

How Compiler-First Reactivity Works

The magic — and the performance — comes from Gea's Vite plugin, which runs as a build-time compilation step:

  1. JSX Analysis: The plugin parses every JSX template and identifies all expressions that reference component or store properties.
  2. Dependency Graph: For each expression, the compiler builds a dependency graph mapping DOM nodes to their state sources.
  3. Surgical Patch Generation: At build time, the compiler emits JavaScript that directly updates DOM nodes when their dependencies change — using textContent, setAttribute, or DOM insertion/removal as appropriate.
  4. Runtime Elimination: In a hello-world build, the framework runtime disappears entirely from the bundle. Every DOM manipulation is direct.

This is fundamentally different from the virtual DOM approach used by React and Vue. Instead of re-rendering a virtual tree and diffing against the previous version, Gea's compiler generates code that says: "when property X changes, update DOM node Y." No diffing, no reconciliation — just direct DOM surgery.

Benchmarks: How Gea Stacks Up

The numbers are remarkable. Let's look at two data points: hello-world (proving the compiler can disappear) and a real todo application (proving the runtime stays lean when the app actually does something).

Hello-World Bundle Size

Framework Version Raw JS Brotli JS vs Gea
Gea 1.3.0 214 B 121 B 1.0x
Solid 1.9.12 10,196 B 3,601 B 29.8x
Svelte 5.55.5 23,461 B 8,537 B 70.6x
Vue 3.5.33 58,174 B 20,711 B 171.2x
React 19 19.2.5 / React DOM 19.2.5 189,717 B 50,816 B 420.0x

Measured from fresh Vite 8.0.10 production builds, summing JavaScript assets only. React, Vue, and Svelte used equivalent minimal hello-world components.

Todo App (Interactive) Bundle Size

Framework Version Raw JS Brotli JS Total Raw Total Brotli
Gea 1.3.0 15,364 B 4,896 B 18,075 B 5,664 B
Solid 1.9.12 16,181 B 5,721 B 18,892 B 6,485 B
Svelte 5.55.5 38,812 B 13,661 B 41,523 B 14,429 B
Vue 3.5.33 63,676 B 22,585 B 66,387 B 23,411 B
React 19 19.2.5 / React DOM 19.2.5 192,330 B 51,460 B 195,041 B 52,287 B

CSS was identical across all builds: 2,711 B raw, 746 B brotli.

js-framework-benchmark Results

The js-framework-benchmark is the industry standard for measuring UI framework runtime performance. It constructs a table of 1,000 rows, performs operations like selecting, updating, and swapping rows, and measures the time each framework takes.

Framework Score vs Vanilla JS
Vanilla JS 1.00
Gea 1.3 1.02 +2%
Solid 1.9 1.10 +10%
Svelte 5 1.10 +10%
Vue 3.6 1.22 +22%
React 19 1.43 +43%

Gea scores 1.02 — within 2% of hand-written vanilla JavaScript. This is the closest any compiled UI framework has come to matching raw DOM manipulation performance.

Built-In Features

Gea ships as a batteries-included toolkit, not just a rendering library:

Client-Side Router

A built-in RouterView and Link component with route params, wildcards, and programmatic navigation. The router is tree-shaken — importing it when you need it adds no overhead when you don't.

Gea UI — Accessible Components

The @geajs/ui package provides 35+ accessible UI primitives built on Zag.js: dialogs, menus, tooltips, accordions, comboboxes, and more. These are headless components — you style them with your own CSS while the accessibility logic (ARIA attributes, keyboard navigation, focus management) is handled automatically.

Gea Mobile

Built on the experience from erste (Amcalar's earlier mobile framework), Gea Mobile provides iOS-style navigation, gesture handling, swipe-back gestures, and mobile-specific transitions for building native-feeling web applications in a Cordova/Capacitor shell.

Two-Way Props

Objects and arrays passed as props remain connected to the parent's reactive proxy. A child component mutating a prop object directly updates the parent — no explicit events, no v-model. Primitives are passed by value as expected.

HMR and Developer Experience

Gea supports Hot Module Replacement during development. Edit a component and see the result instantly without losing state. A VS Code extension is also in development.

Gea vs Svelte vs Solid: The Compiled Framework Landscape

Gea enters a space where Svelte and Solid already compete. Here's how they compare:

Gea vs Svelte

Svelte pioneered the "compile away" approach — it turns components into efficient imperative code at build time. However, Svelte still ships a runtime reactivity system. Gea takes compilation further by using Proxy-based stores that let the compiler trace dependencies precisely and eliminate virtually all runtime code.

Gea vs Solid

Solid uses fine-grained reactivity via signals — each reactive value is tracked individually, enabling precise DOM updates without a virtual DOM. But signals require explicit creation (createSignal, createEffect), which is a small conceptual overhead.

Getting Started

Creating a new Gea project is straightforward:

npm create gea
cd my-gea-app
npm run dev

The scaffold creates a Vite 8.0 project with TypeScript, JSX compilation, and the Gea plugin pre-configured. Official example projects on GitHub demonstrate counters, todo apps, routing patterns, and server-side rendering.

Should You Use Gea?

Gea is genuinely innovative — the compiler-first approach delivers benchmark results that seemed impossible a year ago. But as with any new framework, the decision depends on your context:

Consider Gea if:

Stick with established frameworks if:

For most projects, the established frameworks are the right choice. But Gea represents a genuine step forward in what's possible with compiled UI frameworks, and its approach to eliminating runtime overhead through compiler analysis is likely to influence the next generation of tools — regardless of whether you use it directly.

FAQ

What is the Gea framework?
Gea is a compiler-first reactive JavaScript UI framework created by Armagan Amcalar (dashersw). Unlike React or Vue, Gea eliminates the virtual DOM entirely — it compiles JSX into surgical DOM patches at build time. State is managed via Proxy-based stores using plain JavaScript classes. Version 1.3.0 was released in June 2026.
How is Gea different from Svelte?
Both Gea and Svelte use compilation to eliminate runtime overhead, but Gea takes it further. While Svelte compiles components and still ships a small runtime for reactivity, Gea's compiler can eliminate the framework entirely from hello-world bundles — 121 bytes vs Svelte's 8.5 KB. Gea also uses end-to-end compiled reactivity: the compiler traces every state access through JSX and generates targeted DOM update code for each dependency. For the latest SvelteKit updates including {const ...} declarations and SvelteKit 3 preview features, see my Svelte July 2026 guide.
How fast is Gea compared to other frameworks?
Gea scores 1.02 on js-framework-benchmark, within 2% of hand-written vanilla JavaScript (1.00). It beats Solid (1.10), Svelte (1.10), Vue (1.22), and React (1.43) by significant margins. For bundle size, a hello-world Gea app is 121 bytes brotli — 30x smaller than Solid (3.6 KB), 70x smaller than Svelte (8.5 KB), 171x smaller than Vue (20.7 KB), and 420x smaller than React (50.8 KB).
Does Gea use hooks or signals?
No. Gea has no hooks, no signals, no dependency arrays, and no special primitives. Components are plain JavaScript classes or functions. State is a class property mutated directly with this.count++. Stores are Proxy-wrapped classes where getters serve as computed values. Reactivity emerges from the compiler analyzing JSX at build time, not from runtime primitives.
Is Gea production-ready?
Gea v1.3.0 is a stable release with 374 commits, active development, and 90 tags. It ships with a built-in client-side router, 35+ accessible UI components (Zag.js-based), mobile primitives, HMR support, and a Vite 8.0 plugin. The framework is MIT-licensed. For production use, evaluate its ecosystem maturity and community size compared to established frameworks.
How do I start a Gea project?
Run npm create gea and follow the interactive prompt. The scaffold creates a Vite 8.0 project with TypeScript support, JSX compilation, and the Gea plugin configured. There are also official example projects on GitHub covering counter, todo, routing, and server-side rendering.
Does Gea support TypeScript?
Yes. Gea has first-class TypeScript support. Components and stores can be written with full type annotations. The Vite plugin handles JSX compilation and type checking through the standard TypeScript toolchain.
Contact

Working on a web project?

I build production applications with React, Next.js, Node.js, and modern JavaScript frameworks. Gea, Svelte, or Solid — whatever fits your project best.