# el-ui Framework Specification
Version 0.1.0 — April 2026
---
## Overview
el-ui is a frontend framework where state is an Engram graph and reactivity is spreading activation.
Every framework answers the same question differently: **what re-renders when state changes?**
| Framework | Reactivity model |
|-----------|-----------------|
| React | Virtual DOM diffing |
| Vue | Dependency tracking (Proxy-based) |
| Svelte | Compile-time analysis |
| **el-ui** | **Spreading activation over a state graph** |
The core insight: treating component state as a graph of related nodes, and using the same spreading activation algorithm as the Engram knowledge engine to determine what to update. Reactivity is not declared, tracked, or diffed — it is activated and propagated, exactly as associative memory works in biological neural networks.
---
## 1. Activation-Based Reactivity
### 1.1 The Model
Every piece of state in an el-ui application is a **node** in an in-browser Engram graph. Nodes have:
- `id` — UUID, the node's identity
- `type` — `'state'`, `'route'`, or user-defined
- `name` — the state variable name
- `content` — the current value
- `importance` — a salience weight `[0, 1]`, boosted when the node is activated
Nodes are connected by **edges** with a `weight` `[0, 1]` and a `relation` label.
When state changes (via `setState()`), spreading activation runs from the changed node:
```
strength = parent_strength × edge.weight × target.importance
```
This is multiplicative, matching the Engram core engine (`engram-core/src/activation.rs`). Every factor must be non-trivial for a path to propagate — weak edges, dormant nodes, and irrelevant connections die immediately. Components subscribed to nodes in the resulting **activation surface** update. Everything else stays still.
### 1.2 Why Multiplication, Not Addition
Addition allows many weak signals to accumulate into false relevance — an observation from the Engram architecture. The brain's associative memory is conjunctive: a path requires ALL its links to be strong. Multiplication enforces this. If any factor is near zero, the path dies.
### 1.3 Pruning
Paths with activation strength below `PRUNE_THRESHOLD` (default: `0.01`) are cut. This prevents exponential blowup in large state graphs and models the brain's attention filter.
### 1.4 Importance Boost
When a node is updated, its importance increases by 0.1 (capped at 1.0). Recently-changed state is more salient — it activates more easily in future propagation. This mirrors long-term potentiation: frequently-used pathways become lower-resistance.
---
## 2. Component Definition Syntax
Components are defined in `.el` files (the same extension as el source). A component is a specialized el module.
### 2.1 Structure
```
component ComponentName {
props {
// optional prop declarations
}
state {
// optional state declarations
}
fn methodName(param: Type) -> ReturnType {
// method body
}
template {
// HTML template
}
}
```
All four sections (`props`, `state`, methods, `template`) are optional. Components with no template render an empty string.
### 2.2 Props
Props are inputs from the parent component. They are read-only inside the component.
```
props {
label: String // required
variant: String = "primary" // optional, with default
disabled: Bool = false // boolean with default
onClick: Fn() -> Void // function prop
}
```
Prop types: `String`, `Int`, `Float`, `Bool`, `Fn(...) -> T`, `[T]`, `T?`.
### 2.3 State
State declarations create nodes in the component's Engram graph.
```
state {
count: Int = 0
label: String = "hello"
active: Bool = false
}
```
Each state variable becomes:
1. A node in `this._graph` (seeded at construction time)
2. A reactive binding: changing the value via `setState()` triggers activation
### 2.4 Methods
Methods are `fn` definitions inside the component body. They have access to the component's current state and can call `setState()`.
```
fn increment() -> Void {
count = count + 1
}
```
State assignments in method bodies (`count = count + 1`) are compiled to `setState('count', count + 1)` calls.
---
## 3. Template Syntax
### 3.1 Interpolation
Embed any expression with `{expr}`:
```
{count}
{"Hello, " + name + "!"}
{active ? "on" : "off"}
```
### 3.2 Event Binding
Bind DOM events with `on:event={handler}`:
```
value = e.target.value} />
hovered = true} on:mouseleave={() => hovered = false} />
```
Supported events: `click`, `input`, `change`, `mouseenter`, `mouseleave`, `keydown`, `keyup`, `keypress`, `focus`, `blur`, `submit`, `mousedown`, `mouseup`, `dblclick`, `contextmenu`.
The compiler emits `data-el-{event}` attributes. The renderer binds handlers at mount time and rebinds after each patch.
### 3.3 Dynamic Attributes
```
```
### 3.4 Static Attributes
```
```
### 3.5 Boolean Attributes
```
```
Boolean attributes emit the attribute name if the expression is truthy, nothing if falsy.
### 3.6 Component Usage
Components are invoked by their name (uppercase first letter). Props are passed as attributes:
```
` |
| `RawText(s)` | Inline expression text, text content |
### 8.3 Parser (`crates/el-ui-compiler/src/parser.rs`)
Hand-written recursive descent. Produces `Vec`. Each component is parsed as:
1. `component Name {` — component declaration
2. `props { ... }` — prop definitions (optional)
3. `state { ... }` — state definitions (optional)
4. `fn method(...) -> Type { ... }` — methods (optional, multiple)
5. `template { ... }` — template tree (optional)
The template is parsed as a tree of `TemplateNode` values. HTML elements, component references, interpolations, and block directives are all represented as nodes in this tree.
### 8.4 Code Generator (`crates/el-ui-compiler/src/codegen.rs`)
The code generator transforms the AST into a JavaScript ES2022 module. For each component:
1. Emits a class extending `Component` from the runtime.
2. In the constructor: seeds state nodes into `this._graph`, subscribes to activation events.
3. Emits `setState()`, which calls `this._graph.update()` to trigger activation.
4. Emits a `render()` method returning a template literal string.
5. Translates state assignments in methods: `count = count + 1` → `this.setState('count', count + 1)`.
6. Translates template interpolations: `{count}` → `${count}`.
7. Emits event handlers as `data-el-{event}` attributes for the renderer to bind.
### 8.5 CLI
```bash
# Compile a single .el file
el-ui-compiler App.el -o app.js
# Default output: same name, .js extension
el-ui-compiler App.el # produces App.js
```
---
## 9. Production Build — Quantum-Sealed via engram-crypto
The production build pipeline follows the el sealed artifact format:
```bash
# 1. Compile .el to .js
el-ui-compiler App.el -o app.js --target prod
# 2. Seal the JavaScript bundle
ENGRAM_SEAL_KEY=my-deploy-key el seal app.js -o app.sealed
```
The sealed artifact is an `ENGRAM01` sealed bundle (same format as the el production target):
```
Offset Size Field
────── ────── ─────────────────────────────────────────
0 8 Magic: b"ENGRAM01"
8 2 Format version: u16 big-endian (currently 1)
10 * JSON: { algorithm_id, signature, encapsulated_key, nonce, ciphertext }
```
AES-256-GCM encryption. The key is derived from the deployment binding (environment variable, machine fingerprint, or none). Without the key, the bundle is indistinguishable from random bytes. No static analysis tool can extract the application logic, queries, or API keys from a sealed bundle.
**Why "quantum-sealed":** AES-256 is quantum-resistant at 128-bit quantum security (Grover's algorithm provides only a quadratic speedup). The `algorithm_id` field is forward-compatible with ML-KEM when it stabilizes.
### 9.1 The `{#activate}` Query is Protected
A key benefit of production sealing: `{#activate}` query strings are embedded in the compiled bundle and encrypted with the application logic. Proprietary semantic queries (which encode business logic about how your application understands its data) are invisible to competitors who decompile your application.
---
## 10. Runtime Size Target
The `dist/el-ui.js` runtime targets **under 15KB minified and gzipped**. As of v0.1:
| Module | Purpose | ~Size |
|--------|---------|-------|
| `graph.js` | Engram graph (nodes, edges, activation, search, subscribe) | ~3KB |
| `activation.js` | Standalone activation utilities | ~1.5KB |
| `renderer.js` | DOM patching, event binding | ~2KB |
| `router.js` | Graph-based routing | ~1.5KB |
| `index.js` | Component base class, `mount()`, re-exports | ~1KB |
Total: ~9KB source, ~4KB minified+gzipped (estimated).
---
## 11. Versioning and Compatibility
el-ui follows semantic versioning.
- **v0.1.x** — Initial release. Full re-render on state change. String-based `{#activate}` search.
- **v0.2.x** — Targeted DOM patching (patch only nodes in the activation surface). `{#activate}` with embedding-based semantic search.
- **v0.3.x** — ML-KEM sealed artifacts. Engram database integration for compile-time semantic type checking of `{#activate}` queries.
- **v1.0.0** — Stable API. Full production sealing. LSP integration with spreading activation autocomplete.
---
## 12. Relationship to el
el-ui `.el` files share the `.el` extension with el source files. Components are specialized el modules — in a future version, an `.el` file can mix component definitions with el type definitions, constants, and utility functions in a single compilation unit.
The spreading activation algorithm in `graph.js` and `activation.js` faithfully mirrors `engram-core/src/activation.rs`:
- Same BFS-based traversal
- Same multiplicative strength formula
- Same pruning threshold semantics
- Same winner-take-most rule (strongest path to each node wins)
The in-browser graph is a lightweight implementation without Engram's full embedding vector machinery. In production, a WASM-compiled Engram core can replace the JavaScript graph entirely, enabling true semantic activation with cosine similarity over embedding vectors.