# HTMX Architecture

## Overview

General Bots Suite uses **HTMX** for its user interface - a modern approach that delivers the interactivity of a single-page application without the complexity of JavaScript frameworks like React, Vue, or Angular.

> **Why HTMX?**
> - Simpler code, easier maintenance
> - Server-rendered HTML (fast, SEO-friendly)
> - Progressive enhancement
> - No build step required
> - Smaller payload than SPA frameworks

---

## How HTMX Works

### Traditional Web vs HTMX

**Traditional (Full Page Reload):**
```
User clicks → Browser requests full page → Server returns entire HTML → Browser replaces everything
```

**HTMX (Partial Update):**
```
User clicks → HTMX requests fragment → Server returns HTML snippet → HTMX updates only that part
```

### Core Concept

HTMX extends HTML with attributes that define:
1. **What triggers the request** (`hx-trigger`)
2. **Where to send it** (`hx-get`, `hx-post`)
3. **What to update** (`hx-target`)
4. **How to update it** (`hx-swap`)

---

## HTMX Attributes Reference

### Request Attributes

| Attribute | Purpose | Example |
|-----------|---------|---------|
| `hx-get` | GET request to URL | `hx-get="/api/tasks"` |
| `hx-post` | POST request | `hx-post="/api/tasks"` |
| `hx-put` | PUT request | `hx-put="/api/tasks/1"` |
| `hx-patch` | PATCH request | `hx-patch="/api/tasks/1"` |
| `hx-delete` | DELETE request | `hx-delete="/api/tasks/1"` |

### Trigger Attributes

| Attribute | Purpose | Example |
|-----------|---------|---------|
| `hx-trigger` | Event that triggers request | `hx-trigger="click"` |
| | Load on page | `hx-trigger="load"` |
| | Periodic polling | `hx-trigger="every 5s"` |
| | Keyboard event | `hx-trigger="keyup changed delay:300ms"` |

### Target & Swap Attributes

| Attribute | Purpose | Example |
|-----------|---------|---------|
| `hx-target` | Element to update | `hx-target="#results"` |
| `hx-swap` | How to insert content | `hx-swap="innerHTML"` |
| | | `hx-swap="outerHTML"` |
| | | `hx-swap="beforeend"` |
| | | `hx-swap="afterbegin"` |

---

## Suite Architecture

### File Structure

```
ui/suite/
├── index.html          # Main entry point with navigation
├── base.html           # Base template
├── home.html           # Home page
├── default.gbui        # Full desktop layout
├── single.gbui         # Simple chat layout
├── designer.html       # Visual dialog designer
├── editor.html         # Code editor
├── settings.html       # User settings
├── css/
│   ├── app.css         # Application styles
│   ├── apps-extended.css # Extended app styles
│   ├── components.css  # UI components
│   └── global.css      # Global styles
├── js/
│   ├── htmx-app.js     # HTMX application logic
│   ├── theme-manager.js # Theme switching
│   └── vendor/         # Third-party libraries
├── partials/           # Reusable HTML fragments
├── auth/               # Authentication views
├── attendant/          # Attendant interface
├── chat/
│   ├── chat.html       # Chat component
│   ├── chat.css        # Chat styles
│   └── projector.html  # Projector view
├── drive/              # File manager
├── tasks/              # Task manager
├── mail/               # Email client
├── calendar/           # Calendar view
├── meet/               # Video meetings
├── paper/              # Document editor
├── research/           # AI search
├── analytics/          # Dashboards
├── sources/            # Prompts & templates
├── tools/              # Developer tools
└── monitoring/         # System monitoring
```

### Loading Pattern

The Suite uses **lazy loading** - components load only when needed:

```html
<!-- Main navigation in index.html -->
<a href="#chat" 
   data-section="chat"
   hx-get="/ui/suite/chat/chat.html" 
   hx-target="#main-content"
   hx-swap="innerHTML">
    Chat
</a>
```

When user clicks "Chat":
1. HTMX requests `/ui/suite/chat/chat.html`
2. Server returns the Chat HTML fragment
3. HTMX inserts it into `#main-content`
4. Only Chat code loads, not entire app

---

## Component Patterns

### 1. Load on Page View

```html
<!-- Tasks load immediately when component is shown -->
<div id="task-list"
     hx-get="/api/tasks"
     hx-trigger="load"
     hx-swap="innerHTML">
    <div class="loading">Loading tasks...</div>
</div>
```

### 2. Form Submission

```html
<!-- Add task form -->
<form hx-post="/api/tasks"
      hx-target="#task-list"
      hx-swap="afterbegin"
      hx-on::after-request="this.reset()">
    <input type="text" name="text" placeholder="New task..." required>
    <button type="submit">Add</button>
</form>
```

**Flow:**
1. User types task, clicks Add
2. HTMX POSTs form data to `/api/tasks`
3. Server creates task, returns HTML for new task item
4. HTMX inserts at beginning of `#task-list`
5. Form resets automatically

### 3. Click Actions

```html
<!-- Task item with actions -->
<div class="task-item" id="task-123">
    <input type="checkbox" 
           hx-patch="/api/tasks/123"
           hx-vals='{"completed": true}'
           hx-target="#task-123"
           hx-swap="outerHTML">
    <span>Review quarterly report</span>
    <button hx-delete="/api/tasks/123"
            hx-target="#task-123"
            hx-swap="outerHTML"
            hx-confirm="Delete this task?">
        🗑
    </button>
</div>
```

### 4. Search with Debounce

```html
<!-- Search input with 300ms delay -->
<input type="text" 
       name="q"
       placeholder="Search..."
       hx-get="/api/search"
       hx-trigger="keyup changed delay:300ms"
       hx-target="#search-results"
       hx-indicator="#search-spinner">

<span id="search-spinner" class="htmx-indicator">🔄</span>
<div id="search-results"></div>
```

**Flow:**
1. User types in search box
2. After 300ms of no typing, HTMX sends request
3. Spinner shows during request
4. Results replace `#search-results` content

### 5. Real-time Updates (WebSocket)

```html
<!-- Chat with WebSocket -->
<div id="chat-app" hx-ext="ws" ws-connect="/ws">
    <div id="messages"
         hx-get="/api/sessions/current/history"
         hx-trigger="load"
         hx-swap="innerHTML">
    </div>
    
    <form ws-send>
        <input name="content" type="text">
        <button type="submit">Send</button>
    </form>
</div>
```

**Flow:**
1. WebSocket connects on load
2. History loads via HTMX GET
3. New messages sent via WebSocket (`ws-send`)
4. Server pushes updates to all connected clients

### 6. Polling for Updates

```html
<!-- Analytics that refresh every 30 seconds -->
<div class="metric-card"
     hx-get="/api/analytics/messages/count"
     hx-trigger="load, every 30s"
     hx-swap="innerHTML">
    <!-- Content updates automatically -->
</div>
```

### 7. Infinite Scroll

```html
<!-- File list with infinite scroll -->
<div id="file-list">
    <!-- Files here -->
    
    <div hx-get="/api/files?page=2"
         hx-trigger="revealed"
         hx-swap="afterend">
        Loading more...
    </div>
</div>
```

---

## API Response Patterns

### Server Returns HTML Fragments

The server doesn't return JSON - it returns ready-to-display HTML:

**Request:**
```
GET /api/tasks
```

**Response:**
```html
<div class="task-item" id="task-1">
    <input type="checkbox">
    <span>Review quarterly report</span>
</div>
<div class="task-item" id="task-2">
    <input type="checkbox">
    <span>Update documentation</span>
</div>
```

### Swap Strategies

| Strategy | Effect |
|----------|--------|
| `innerHTML` | Replace contents of target |
| `outerHTML` | Replace entire target element |
| `beforeend` | Append inside target (at end) |
| `afterbegin` | Prepend inside target (at start) |
| `beforebegin` | Insert before target |
| `afterend` | Insert after target |
| `delete` | Delete target element |
| `none` | Don't swap (for side effects) |

---

## CSS Integration

### Loading Indicators

```css
/* Hidden by default */
.htmx-indicator {
    display: none;
}

/* Shown during request */
.htmx-request .htmx-indicator {
    display: inline-block;
}

/* Or when indicator IS the requesting element */
.htmx-request.htmx-indicator {
    display: inline-block;
}
```

### Transition Effects

```css
/* Fade in new content */
.htmx-settling {
    opacity: 0;
}

.htmx-swapping {
    opacity: 0;
    transition: opacity 0.2s ease-out;
}
```

---

## JavaScript Integration

### HTMX Events

```javascript
// After any HTMX swap
document.body.addEventListener('htmx:afterSwap', (e) => {
    console.log('Content updated:', e.detail.target);
});

// Before request
document.body.addEventListener('htmx:beforeRequest', (e) => {
    console.log('Sending request to:', e.detail.pathInfo.path);
});

// After request completes
document.body.addEventListener('htmx:afterRequest', (e) => {
    if (e.detail.successful) {
        console.log('Request succeeded');
    } else {
        console.error('Request failed');
    }
});

// On WebSocket message
document.body.addEventListener('htmx:wsAfterMessage', (e) => {
    console.log('Received:', e.detail.message);
});
```

### Triggering HTMX from JavaScript

```javascript
// Trigger an HTMX request programmatically
htmx.trigger('#task-list', 'load');

// Make an AJAX request
htmx.ajax('GET', '/api/tasks', {
    target: '#task-list',
    swap: 'innerHTML'
});

// Process new HTMX content
htmx.process(document.getElementById('new-content'));
```

---

## Designer Page Architecture

The visual dialog designer uses a hybrid approach:

### Canvas Management (JavaScript)
```javascript
// State managed in JavaScript
const state = {
    nodes: new Map(),      // Node data
    connections: [],       // Connections between nodes
    zoom: 1,               // Canvas zoom level
    pan: { x: 0, y: 0 }    // Canvas position
};
```

### File Operations (HTMX)
```html
<!-- Load file via HTMX -->
<button hx-get="/api/v1/designer/files"
        hx-target="#file-list-content">
    Open File
</button>

<!-- Save via HTMX -->
<button hx-post="/api/v1/designer/save"
        hx-include="#designer-data">
    Save
</button>
```

### Drag-and-Drop (JavaScript)
```javascript
// Toolbox items are draggable
toolboxItems.forEach(item => {
    item.addEventListener('dragstart', (e) => {
        e.dataTransfer.setData('nodeType', item.dataset.nodeType);
    });
});

// Canvas handles drop
canvas.addEventListener('drop', (e) => {
    const nodeType = e.dataTransfer.getData('nodeType');
    createNode(nodeType, e.clientX, e.clientY);
});
```

---

## Performance Considerations

### 1. Minimize Request Size

Return only what's needed:
```html
<!-- Good: Return just the updated row -->
<tr id="row-123">...</tr>

<!-- Bad: Return entire table -->
<table>...</table>
```

### 2. Use Appropriate Triggers

```html
<!-- Don't poll too frequently -->
hx-trigger="every 30s"  <!-- Good for dashboards -->
hx-trigger="every 1s"   <!-- Too frequent! -->

<!-- Debounce user input -->
hx-trigger="keyup changed delay:300ms"  <!-- Good -->
hx-trigger="keyup"                       <!-- Too many requests -->
```

### 3. Lazy Load Heavy Content

```html
<!-- Load tab content only when tab is clicked -->
<div role="tabpanel" 
     hx-get="/api/heavy-content"
     hx-trigger="intersect once">
</div>
```

### 4. Use `hx-boost` for Navigation

```html
<!-- Boost all links in nav -->
<nav hx-boost="true">
    <a href="/page1">Page 1</a>  <!-- Now uses HTMX -->
    <a href="/page2">Page 2</a>
</nav>
```

---

## Security

### CSRF Protection

HTMX automatically includes CSRF tokens:

```html
<meta name="csrf-token" content="abc123...">
```

```javascript
// Configure HTMX to send CSRF token
document.body.addEventListener('htmx:configRequest', (e) => {
    e.detail.headers['X-CSRF-Token'] = document.querySelector('meta[name="csrf-token"]').content;
});
```

### Content Security

- Server validates all inputs
- HTML is sanitized before rendering
- Authentication checked on every request

---

## Comparison: HTMX vs React

| Aspect | HTMX | React |
|--------|------|-------|
| **Learning Curve** | Low (HTML attributes) | High (JSX, hooks, state) |
| **Bundle Size** | ~14KB | ~40KB + app code |
| **Build Step** | None | Required |
| **Server Load** | More (renders HTML) | Less (returns JSON) |
| **Client Load** | Less | More |
| **SEO** | Excellent | Requires SSR |
| **Complexity** | Simple | Complex |
| **Best For** | Content sites, dashboards | Complex SPAs, offline apps |

---

## Further Reading

- [HTMX Official Documentation](https://htmx.org/docs/)
- [HTMX Examples](https://htmx.org/examples/)
- [Hypermedia Systems (Book)](https://hypermedia.systems/)
- [Chapter 04: UI Reference](./README.md)