botserver/docs/src/chapter-04-gbui
2025-11-24 09:49:25 -03:00
..
console-mode.md - From 4 to 7. 2025-11-23 20:12:09 -03:00
default-gbui.md - From 4 to 7. 2025-11-23 20:12:09 -03:00
README.md - Review .svg and intro text. 2025-11-24 09:49:25 -03:00
single-gbui.md - From 4 to 7. 2025-11-23 20:12:09 -03:00

Chapter 04: User Interface Architecture - Web Components and Real-Time Communication

The General Bots User Interface (gbui) system implements a sophisticated, component-based architecture for creating responsive, real-time conversational experiences across multiple platforms and devices. This chapter provides comprehensive technical documentation on the UI framework, rendering pipeline, WebSocket communication protocols, and interface customization capabilities.

Executive Summary

The gbui system represents a modern approach to conversational UI development, implementing a lightweight, standards-based architecture that eliminates framework dependencies while providing enterprise-grade capabilities. The system leverages native Web Components, WebSocket protocols, and progressive enhancement strategies to deliver sub-second response times and seamless user experiences across desktop, mobile, and embedded platforms.

System Architecture Overview

UI Component Stack

The user interface implements a layered architecture for maximum flexibility and performance:

┌─────────────────────────────────────────────────────────────────┐
│                    Presentation Layer                           │
│              (HTML5, CSS3, Web Components)                      │
├─────────────────────────────────────────────────────────────────┤
│                    Interaction Layer                            │
│         (Event Handling, Gesture Recognition, A11y)             │
├─────────────────────────────────────────────────────────────────┤
│                  Communication Layer                            │
│      (WebSocket, Server-Sent Events, REST API)                 │
├─────────────────────────────────────────────────────────────────┤
│                     State Management                            │
│        (Session Storage, IndexedDB, Service Workers)            │
├─────────────────────────────────────────────────────────────────┤
│                   Rendering Pipeline                            │
│      (Virtual DOM, Incremental Updates, GPU Acceleration)       │
└─────────────────────────────────────────────────────────────────┘

Technical Specifications

Component Technology Performance Target Browser Support
Rendering Engine Native DOM + Virtual DOM diffing 60 FPS animations Chrome 90+, Firefox 88+, Safari 14+
Communication WebSocket (RFC 6455) <100ms latency All modern browsers
State Management IndexedDB + LocalStorage <5ms read/write All modern browsers
Component System Web Components v1 <50ms initialization Chrome, Firefox, Safari, Edge
Styling Engine CSS Grid + Flexbox + Custom Properties <16ms paint All modern browsers
Build Size Vanilla JS (no framework) <50KB gzipped IE11+ with polyfills

Template Architecture

Template Processing Pipeline

The gbui template system implements a multi-stage processing pipeline:

class TemplateProcessor {
    /**
     * Advanced template processing with optimization
     */
    constructor() {
        this.templateCache = new Map();
        this.componentRegistry = new Map();
        this.renderQueue = [];
        this.rafId = null;
    }
    
    processTemplate(templatePath, data) {
        // Stage 1: Template loading and caching
        const template = this.loadTemplate(templatePath);
        
        // Stage 2: Template parsing and AST generation
        const ast = this.parseTemplate(template);
        
        // Stage 3: Data binding and interpolation
        const boundAST = this.bindData(ast, data);
        
        // Stage 4: Component resolution
        const resolvedAST = this.resolveComponents(boundAST);
        
        // Stage 5: Optimization pass
        const optimizedAST = this.optimizeAST(resolvedAST);
        
        // Stage 6: DOM generation
        const domFragment = this.generateDOM(optimizedAST);
        
        // Stage 7: Hydration and event binding
        this.hydrate(domFragment);
        
        return domFragment;
    }
    
    parseTemplate(template) {
        /**
         * Convert HTML template to Abstract Syntax Tree
         */
        const parser = new DOMParser();
        const doc = parser.parseFromString(template, 'text/html');
        
        return this.buildAST(doc.body);
    }
    
    buildAST(node) {
        const ast = {
            type: node.nodeType === 1 ? 'element' : 'text',
            tag: node.tagName?.toLowerCase(),
            attributes: {},
            children: [],
            directives: {},
            events: {}
        };
        
        if (node.nodeType === 1) {
            // Process attributes
            for (const attr of node.attributes) {
                if (attr.name.startsWith('data-')) {
                    ast.directives[attr.name.slice(5)] = attr.value;
                } else if (attr.name.startsWith('on')) {
                    ast.events[attr.name.slice(2)] = attr.value;
                } else {
                    ast.attributes[attr.name] = attr.value;
                }
            }
            
            // Process children
            for (const child of node.childNodes) {
                if (child.nodeType === 1 || child.nodeType === 3) {
                    ast.children.push(this.buildAST(child));
                }
            }
        } else if (node.nodeType === 3) {
            ast.content = node.textContent;
        }
        
        return ast;
    }
}

Template Types and Specifications

default.gbui - Full Desktop Interface

Complete workspace implementation with modular applications:

<!DOCTYPE html>
<html lang="en" data-theme="system">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="General Bots Workspace Interface">
    
    <!-- Performance optimizations -->
    <link rel="preconnect" href="wss://localhost:8080">
    <link rel="dns-prefetch" href="//localhost:8080">
    
    <!-- Critical CSS inline for faster FCP -->
    <style>
        /* Critical path CSS */
        :root {
            --color-primary: #007bff;
            --color-background: #ffffff;
            --color-surface: #f8f9fa;
            --transition-speed: 200ms;
        }
        
        body {
            margin: 0;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto;
            background: var(--color-background);
        }
        
        .app-container {
            display: grid;
            grid-template-areas:
                "header header header"
                "sidebar main aside"
                "footer footer footer";
            grid-template-columns: 240px 1fr 320px;
            grid-template-rows: 48px 1fr 32px;
            height: 100vh;
        }
        
        @media (max-width: 768px) {
            .app-container {
                grid-template-areas:
                    "header"
                    "main"
                    "footer";
                grid-template-columns: 1fr;
            }
        }
    </style>
    
    <!-- Async load non-critical CSS -->
    <link rel="stylesheet" href="/css/components.css" media="print" onload="this.media='all'">
    <link rel="stylesheet" href="/css/themes.css" media="print" onload="this.media='all'">
</head>
<body>
    <!-- Application Shell -->
    <div class="app-container" id="app">
        <!-- Header Bar -->
        <header class="app-header" role="banner">
            <div class="header-brand">
                <img src="/assets/logo.svg" alt="General Bots" width="32" height="32">
                <h1 class="header-title">General Bots</h1>
            </div>
            
            <nav class="header-nav" role="navigation" aria-label="Main">
                <button class="nav-item" data-app="chat" aria-label="Chat" aria-keyshortcuts="Alt+1">
                    <svg class="icon" aria-hidden="true"><!-- Chat icon --></svg>
                    <span>Chat</span>
                </button>
                <button class="nav-item" data-app="drive" aria-label="Drive" aria-keyshortcuts="Alt+2">
                    <svg class="icon" aria-hidden="true"><!-- Drive icon --></svg>
                    <span>Drive</span>
                </button>
                <button class="nav-item" data-app="tasks" aria-label="Tasks" aria-keyshortcuts="Alt+3">
                    <svg class="icon" aria-hidden="true"><!-- Tasks icon --></svg>
                    <span>Tasks</span>
                </button>
                <button class="nav-item" data-app="mail" aria-label="Mail" aria-keyshortcuts="Alt+4">
                    <svg class="icon" aria-hidden="true"><!-- Mail icon --></svg>
                    <span>Mail</span>
                </button>
            </nav>
            
            <div class="header-actions">
                <button class="theme-toggle" aria-label="Toggle theme">
                    <svg class="icon" aria-hidden="true"><!-- Theme icon --></svg>
                </button>
                <button class="user-menu" aria-label="User menu">
                    <img src="/api/user/avatar" alt="" class="avatar" width="32" height="32">
                </button>
            </div>
        </header>
        
        <!-- Sidebar -->
        <aside class="app-sidebar" role="complementary">
            <nav class="sidebar-nav" aria-label="Secondary">
                <!-- Dynamic navigation items -->
            </nav>
        </aside>
        
        <!-- Main Content Area -->
        <main class="app-main" role="main">
            <div class="app-view" id="app-view">
                <!-- Dynamic content loaded here -->
            </div>
        </main>
        
        <!-- Right Panel -->
        <aside class="app-aside" role="complementary">
            <div class="panel-content">
                <!-- Contextual information -->
            </div>
        </aside>
        
        <!-- Footer -->
        <footer class="app-footer" role="contentinfo">
            <div class="footer-status">
                <span class="status-indicator" aria-live="polite"></span>
                <span class="connection-status">Connected</span>
            </div>
        </footer>
    </div>
    
    <!-- Web Components -->
    <script type="module">
        // Chat Component
        class ChatComponent extends HTMLElement {
            constructor() {
                super();
                this.attachShadow({ mode: 'open' });
                this.messages = [];
                this.ws = null;
            }
            
            connectedCallback() {
                this.render();
                this.connectWebSocket();
                this.setupEventListeners();
            }
            
            render() {
                this.shadowRoot.innerHTML = `
                    <style>
                        :host {
                            display: flex;
                            flex-direction: column;
                            height: 100%;
                        }
                        
                        .messages {
                            flex: 1;
                            overflow-y: auto;
                            padding: 1rem;
                        }
                        
                        .message {
                            margin: 0.5rem 0;
                            padding: 0.75rem;
                            border-radius: 8px;
                            max-width: 70%;
                            animation: fadeIn 0.3s ease;
                        }
                        
                        .message-user {
                            background: var(--color-primary);
                            color: white;
                            align-self: flex-end;
                            margin-left: auto;
                        }
                        
                        .message-bot {
                            background: var(--color-surface);
                            align-self: flex-start;
                        }
                        
                        .input-area {
                            display: flex;
                            padding: 1rem;
                            border-top: 1px solid var(--color-border);
                        }
                        
                        @keyframes fadeIn {
                            from { opacity: 0; transform: translateY(10px); }
                            to { opacity: 1; transform: translateY(0); }
                        }
                    </style>
                    
                    <div class="messages" role="log" aria-live="polite"></div>
                    
                    <form class="input-area">
                        <input 
                            type="text" 
                            class="message-input"
                            placeholder="Type a message..."
                            aria-label="Message input"
                            autocomplete="off"
                        />
                        <button type="submit" aria-label="Send message">
                            <svg class="icon"><!-- Send icon --></svg>
                        </button>
                    </form>
                `;
            }
            
            connectWebSocket() {
                const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
                this.ws = new WebSocket(`${protocol}//${window.location.host}/ws`);
                
                this.ws.onopen = () => {
                    console.log('WebSocket connected');
                    this.dispatchEvent(new CustomEvent('connected'));
                };
                
                this.ws.onmessage = (event) => {
                    const message = JSON.parse(event.data);
                    this.addMessage(message);
                };
                
                this.ws.onerror = (error) => {
                    console.error('WebSocket error:', error);
                    this.reconnect();
                };
            }
            
            addMessage(message) {
                this.messages.push(message);
                this.renderMessage(message);
                this.scrollToBottom();
            }
        }
        
        // Register Web Component
        customElements.define('chat-component', ChatComponent);
    </script>
</body>
</html>

single.gbui - Minimalist Chat Interface

Lightweight, focused chat implementation:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>Chat</title>
    
    <style>
        /* Minimal critical CSS - 3KB gzipped */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: system-ui, -apple-system, sans-serif;
            height: 100vh;
            display: flex;
            flex-direction: column;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        }
        
        .chat-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            max-width: 800px;
            width: 100%;
            margin: 0 auto;
            background: white;
            box-shadow: 0 0 40px rgba(0,0,0,0.1);
        }
        
        .messages {
            flex: 1;
            overflow-y: auto;
            padding: 2rem;
            scroll-behavior: smooth;
        }
        
        .message {
            margin: 1rem 0;
            display: flex;
            animation: slideUp 0.3s ease;
        }
        
        .message-content {
            padding: 0.75rem 1rem;
            border-radius: 18px;
            max-width: 75%;
            word-wrap: break-word;
        }
        
        .user .message-content {
            background: #007bff;
            color: white;
            margin-left: auto;
            border-bottom-right-radius: 4px;
        }
        
        .bot .message-content {
            background: #f1f3f5;
            color: #333;
            border-bottom-left-radius: 4px;
        }
        
        .typing-indicator {
            display: none;
            padding: 0.75rem 1rem;
            background: #f1f3f5;
            border-radius: 18px;
            width: 60px;
        }
        
        .typing-indicator.active {
            display: inline-block;
        }
        
        .typing-indicator span {
            display: inline-block;
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: #999;
            margin: 0 2px;
            animation: typing 1.4s infinite;
        }
        
        .typing-indicator span:nth-child(2) {
            animation-delay: 0.2s;
        }
        
        .typing-indicator span:nth-child(3) {
            animation-delay: 0.4s;
        }
        
        .input-area {
            display: flex;
            padding: 1rem;
            background: white;
            border-top: 1px solid #e9ecef;
        }
        
        .message-input {
            flex: 1;
            padding: 0.75rem;
            border: 1px solid #dee2e6;
            border-radius: 24px;
            font-size: 1rem;
            outline: none;
            transition: border-color 0.2s;
        }
        
        .message-input:focus {
            border-color: #007bff;
        }
        
        .send-button {
            margin-left: 0.5rem;
            padding: 0.75rem;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 50%;
            width: 48px;
            height: 48px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            transition: background 0.2s;
        }
        
        .send-button:hover {
            background: #0056b3;
        }
        
        .send-button:disabled {
            background: #6c757d;
            cursor: not-allowed;
        }
        
        @keyframes slideUp {
            from {
                opacity: 0;
                transform: translateY(20px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
        
        @keyframes typing {
            0%, 60%, 100% {
                transform: translateY(0);
            }
            30% {
                transform: translateY(-10px);
            }
        }
        
        /* Dark mode support */
        @media (prefers-color-scheme: dark) {
            body {
                background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
            }
            
            .chat-container {
                background: #1e1e1e;
            }
            
            .bot .message-content {
                background: #2d2d2d;
                color: #e0e0e0;
            }
            
            .input-area {
                background: #1e1e1e;
                border-top-color: #333;
            }
            
            .message-input {
                background: #2d2d2d;
                border-color: #404040;
                color: #e0e0e0;
            }
        }
        
        /* Mobile optimizations */
        @media (max-width: 768px) {
            .chat-container {
                border-radius: 0;
            }
            
            .messages {
                padding: 1rem;
            }
            
            .message-content {
                max-width: 85%;
            }
        }
    </style>
</head>
<body>
    <div class="chat-container">
        <div class="messages" id="messages">
            <!-- Messages will be added here -->
        </div>
        
        <div class="message bot">
            <div class="typing-indicator" id="typing">
                <span></span>
                <span></span>
                <span></span>
            </div>
        </div>
        
        <form class="input-area" id="chat-form">
            <input 
                type="text" 
                class="message-input" 
                id="message-input"
                placeholder="Type your message..."
                autocomplete="off"
                autofocus
            />
            <button type="submit" class="send-button" id="send-button">
                <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                    <line x1="22" y1="2" x2="11" y2="13"></line>
                    <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
                </svg>
            </button>
        </form>
    </div>
    
    <script>
        // Lightweight chat implementation - 5KB uncompressed
        (function() {
            'use strict';
            
            const elements = {
                messages: document.getElementById('messages'),
                input: document.getElementById('message-input'),
                form: document.getElementById('chat-form'),
                typing: document.getElementById('typing'),
                sendButton: document.getElementById('send-button')
            };
            
            let ws = null;
            let reconnectTimeout = null;
            let isConnected = false;
            
            // Initialize WebSocket connection
            function connect() {
                const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
                ws = new WebSocket(`${protocol}//${window.location.host}/ws/chat`);
                
                ws.onopen = () => {
                    isConnected = true;
                    clearTimeout(reconnectTimeout);
                    console.log('Connected to chat server');
                    
                    // Send initial handshake
                    ws.send(JSON.stringify({
                        type: 'handshake',
                        timestamp: Date.now()
                    }));
                };
                
                ws.onmessage = (event) => {
                    const data = JSON.parse(event.data);
                    handleMessage(data);
                };
                
                ws.onerror = (error) => {
                    console.error('WebSocket error:', error);
                };
                
                ws.onclose = () => {
                    isConnected = false;
                    console.log('Disconnected from chat server');
                    
                    // Attempt reconnection
                    reconnectTimeout = setTimeout(connect, 3000);
                };
            }
            
            // Handle incoming messages
            function handleMessage(data) {
                switch(data.type) {
                    case 'message':
                        addMessage(data.content, data.sender || 'bot');
                        break;
                        
                    case 'typing':
                        showTypingIndicator(data.isTyping);
                        break;
                        
                    case 'error':
                        console.error('Server error:', data.message);
                        break;
                }
            }
            
            // Add message to chat
            function addMessage(content, sender) {
                const messageDiv = document.createElement('div');
                messageDiv.className = `message ${sender}`;
                
                const contentDiv = document.createElement('div');
                contentDiv.className = 'message-content';
                contentDiv.textContent = content;
                
                messageDiv.appendChild(contentDiv);
                elements.messages.appendChild(messageDiv);
                
                // Scroll to bottom
                elements.messages.scrollTop = elements.messages.scrollHeight;
                
                // Hide typing indicator
                showTypingIndicator(false);
            }
            
            // Show/hide typing indicator
            function showTypingIndicator(show) {
                elements.typing.classList.toggle('active', show);
                if (show) {
                    elements.messages.scrollTop = elements.messages.scrollHeight;
                }
            }
            
            // Send message
            function sendMessage(content) {
                if (!content.trim() || !isConnected) return;
                
                // Add user message to UI
                addMessage(content, 'user');
                
                // Send to server
                ws.send(JSON.stringify({
                    type: 'message',
                    content: content,
                    timestamp: Date.now()
                }));
                
                // Show typing indicator
                showTypingIndicator(true);
                
                // Clear input
                elements.input.value = '';
                elements.input.focus();
            }
            
            // Handle form submission
            elements.form.addEventListener('submit', (e) => {
                e.preventDefault();
                sendMessage(elements.input.value);
            });
            
            // Handle Enter key
            elements.input.addEventListener('keydown', (e) => {
                if (e.key === 'Enter' && !e.shiftKey) {
                    e.preventDefault();
                    sendMessage(elements.input.value);
                }
            });
            
            // Initialize connection
            connect();
            
            // Add welcome message
            setTimeout(() => {
                addMessage('Hello! How can I help you today?', 'bot');
            }, 500);
        })();
    </script>
</body>
</html>

WebSocket Communication Protocol

Protocol Specification

Real-time bidirectional communication implementation:

interface WebSocketProtocol {
    // Message Types
    enum MessageType {
        HANDSHAKE = 'handshake',
        MESSAGE = 'message',
        TYPING = 'typing',
        PRESENCE = 'presence',
        ERROR = 'error',
        HEARTBEAT = 'heartbeat',
        ACKNOWLEDGE = 'acknowledge'
    }
    
    // Base Message Structure
    interface BaseMessage {
        id: string;
        type: MessageType;
        timestamp: number;
        version: string;
    }
    
    // Message Implementations
    interface ChatMessage extends BaseMessage {
        type: MessageType.MESSAGE;
        content: string;
        sender: 'user' | 'bot';
        metadata?: {
            tokens?: number;
            processingTime?: number;
            confidence?: number;
            sources?: string[];
        };
    }
    
    interface TypingMessage extends BaseMessage {
        type: MessageType.TYPING;
        isTyping: boolean;
        sender: string;
    }
    
    interface PresenceMessage extends BaseMessage {
        type: MessageType.PRESENCE;
        status: 'online' | 'away' | 'offline';
        lastSeen?: number;
    }
}

Connection Management

Robust connection handling with automatic recovery:

class WebSocketManager {
    constructor(url) {
        this.url = url;
        this.ws = null;
        this.reconnectAttempts = 0;
        this.maxReconnectAttempts = 5;
        this.reconnectDelay = 1000;
        this.heartbeatInterval = 30000;
        this.messageQueue = [];
        this.isConnected = false;
        
        this.connect();
    }
    
    connect() {
        this.ws = new WebSocket(this.url);
        
        this.ws.onopen = () => {
            this.isConnected = true;
            this.reconnectAttempts = 0;
            
            // Start heartbeat
            this.startHeartbeat();
            
            // Flush message queue
            this.flushQueue();
            
            // Send handshake
            this.send({
                type: 'handshake',
                version: '1.0.0',
                capabilities: ['typing', 'presence', 'files']
            });
        };
        
        this.ws.onmessage = (event) => {
            const message = JSON.parse(event.data);
            this.handleMessage(message);
        };
        
        this.ws.onerror = (error) => {
            console.error('WebSocket error:', error);
        };
        
        this.ws.onclose = () => {
            this.isConnected = false;
            this.stopHeartbeat();
            this.attemptReconnect();
        };
    }
    
    attemptReconnect() {
        if (this.reconnectAttempts >= this.maxReconnectAttempts) {
            console.error('Max reconnection attempts reached');
            this.onMaxReconnectFailed();
            return;
        }
        
        this.reconnectAttempts++;
        const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
        
        console.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
        
        setTimeout(() => {
            this.connect();
        }, delay);
    }
    
    startHeartbeat() {
        this.heartbeatTimer = setInterval(() => {
            if (this.isConnected) {
                this.send({ type: 'heartbeat' });
            }
        }, this.heartbeatInterval);
    }
    
    send(data) {
        const message = {
            ...data,
            id: this.generateId(),
            timestamp: Date.now()
        };
        
        if (this.isConnected && this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(JSON.stringify(message));
        } else {
            // Queue message for later delivery
            this.messageQueue.push(message);
        }
        
        return message.id;
    }
    
    flushQueue() {
        while (this.messageQueue.length > 0) {
            const message = this.messageQueue.shift();
            this.ws.send(JSON.stringify(message));
        }
    }
}

Performance Optimization

Rendering Performance

Techniques for maintaining 60 FPS:

class RenderOptimizer {
    constructor() {
        this.renderQueue = [];
        this.isRendering = false;
        this.rafId = null;
        
        // Virtual DOM for diff calculations
        this.virtualDOM = {
            messages: [],
            state: {}
        };
        
        // DOM references cache
        this.domCache = new WeakMap();
    }
    
    scheduleRender(updates) {
        // Batch updates
        this.renderQueue.push(...updates);
        
        if (!this.isRendering) {
            this.isRendering = true;
            this.rafId = requestAnimationFrame(() => this.performRender());
        }
    }
    
    performRender() {
        const startTime = performance.now();
        
        // Process render queue
        const updates = this.renderQueue.splice(0, 100); // Limit batch size
        
        // Calculate minimal DOM updates
        const patches = this.calculatePatches(updates);
        
        // Apply patches
        this.applyPatches(patches);
        
        // Continue rendering if queue not empty
        if (this.renderQueue.length > 0) {
            this.rafId = requestAnimationFrame(() => this.performRender());
        } else {
            this.isRendering = false;
        }
        
        // Monitor performance
        const renderTime = performance.now() - startTime;
        if (renderTime > 16.67) {
            console.warn(`Render took ${renderTime}ms - possible jank`);
        }
    }
    
    calculatePatches(updates) {
        const patches = [];
        
        for (const update of updates) {
            const oldVNode = this.virtualDOM[update.path];
            const newVNode = update.value;
            
            const diff = this.diff(oldVNode, newVNode);
            if (diff) {
                patches.push({
                    path: update.path,
                    diff: diff
                });
            }
            
            // Update virtual DOM
            this.virtualDOM[update.path] = newVNode;
        }
        
        return patches;
    }
}

Resource Loading

Progressive loading strategies:

class ResourceLoader {
    constructor() {
        this.loadQueue = [];
        this.loadingResources = new Set();
        this.resourceCache = new Map();
        
        // Intersection Observer for lazy loading
        this.observer = new IntersectionObserver(
            (entries) => this.handleIntersection(entries),
            {
                rootMargin: '50px',
                threshold: 0.01
            }
        );
    }
    
    async loadCriticalResources() {
        // Critical CSS
        await this.loadCSS('/css/critical.css', { priority: 'high' });
        
        // Critical JavaScript
        await this.loadScript('/js/core.js', { priority: 'high' });
        
        // Preload fonts
        this.preloadFonts([
            '/fonts/inter-var.woff2',
            '/fonts/jetbrains-mono.woff2'
        ]);
        
        // Prefetch likely navigation targets
        this.prefetchResources([
            '/api/user',
            '/api/conversations/recent'
        ]);
    }
    
    async loadCSS(href, options = {}) {
        return new Promise((resolve, reject) => {
            const link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = href;
            
            if (options.priority === 'high') {
                link.fetchpriority = 'high';
            }
            
            link.onload = resolve;
            link.onerror = reject;
            
            document.head.appendChild(link);
        });
    }
    
    preloadFonts(fonts) {
        fonts.forEach(font => {
            const link = document.createElement('link');
            link.rel = 'preload';
            link.as = 'font';
            link.type = 'font/woff2';
            link.href = font;
            link.crossOrigin = 'anonymous';
            document.head.appendChild(link);
        });
    }
}

Accessibility Implementation

WCAG 2.1 AAA Compliance

Comprehensive accessibility features:

class AccessibilityManager {
    constructor() {
        this.announcer = this.createAnnouncer();
        this.focusTrap = null;
        this.prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
        
        this.initializeA11y();
    }
    
    initializeA11y() {
        // Skip navigation links
        this.addSkipLinks();
        
        // Keyboard navigation
        this.setupKeyboardNav();
        
        // Screen reader announcements
        this.setupAnnouncements();
        
        // Focus management
        this.setupFocusManagement();
        
        // High contrast mode detection
        this.detectHighContrast();
    }
    
    createAnnouncer() {
        const announcer = document.createElement('div');
        announcer.setAttribute('role', 'status');
        announcer.setAttribute('aria-live', 'polite');
        announcer.setAttribute('aria-atomic', 'true');
        announcer.className = 'sr-only';
        document.body.appendChild(announcer);
        return announcer;
    }
    
    announce(message, priority = 'polite') {
        this.announcer.setAttribute('aria-live', priority);
        this.announcer.textContent = message;
        
        // Clear after announcement
        setTimeout(() => {
            this.announcer.textContent = '';
        }, 1000);
    }
    
    setupKeyboardNav() {
        document.addEventListener('keydown', (e) => {
            // Keyboard shortcuts
            if (e.altKey) {
                switch(e.key) {
                    case '1': this.navigateTo('chat'); break;
                    case '2': this.navigateTo('drive'); break;
                    case '3': this.navigateTo('tasks'); break;
                    case '4': this.navigateTo('mail'); break;
                    case '/': this.focusSearch(); break;
                }
            }
            
            // Tab trap for modals
            if (this.focusTrap && e.key === 'Tab') {
                this.handleTabTrap(e);
            }
            
            // Escape key handling
            if (e.key === 'Escape') {
                this.handleEscape();
            }
        });
    }
}

Security Considerations

Content Security Policy

Comprehensive CSP implementation:

<meta http-equiv="Content-Security-Policy" content="
    default-src 'self';
    script-src 'self' 'unsafe-inline' 'unsafe-eval';
    style-src 'self' 'unsafe-inline';
    img-src 'self' data: blob:;
    font-src 'self' data:;
    connect-src 'self' wss://localhost:8080;
    media-src 'self';
    object-src 'none';
    frame-src 'none';
    base-uri 'self';
    form-action 'self';
    frame-ancestors 'none';
    upgrade-insecure-requests;
">

XSS Prevention

Input sanitization and output encoding:

class SecurityManager {
    sanitizeHTML(html) {
        const policy = {
            ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'br', 'p', 'code', 'pre'],
            ALLOWED_ATTR: ['href', 'title', 'target'],
            ALLOW_DATA_ATTR: false,
            RETURN_DOM: false,
            RETURN_DOM_FRAGMENT: false,
            RETURN_TRUSTED_TYPE: true
        };
        
        return DOMPurify.sanitize(html, policy);
    }
    
    escapeHTML(text) {
        const map = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#x27;',
            '/': '&#x2F;'
        };
        
        return text.replace(/[&<>"'/]/g, char => map[char]);
    }
}

Summary

The gbui system provides a complete, production-ready user interface framework that delivers enterprise-grade performance while maintaining simplicity and accessibility. Through careful optimization, progressive enhancement, and standards compliance, the system achieves sub-second response times and smooth 60 FPS rendering across all supported platforms.