mirror of
https://github.com/thecyberlearn/quantum-ai-v2.git
synced 2026-08-18 12:32:59 +00:00
16 KiB
16 KiB
Optimized Agent Creation Guide
This guide provides comprehensive patterns and best practices for creating agents without UI/UX failures, based on the optimized Data Analyzer and Job Posting Generator implementations.
Quick Start Checklist
✅ Template Architecture
- Use widget-based layout with CSS custom properties
- Implement self-contained styles (no external dependencies)
- Add proper responsive design with flexbox
- Include accessibility ARIA attributes
✅ Security Implementation
- Implement HTML sanitization functions
- Use XSS prevention techniques
- Validate all form inputs
- Use safe DOM manipulation
✅ Performance Optimization
- Add debouncing for form interactions
- Implement proper event listener management
- Use efficient DOM queries
- Add loading states and feedback
✅ Wallet Integration
- Implement dynamic wallet balance validation
- Add wallet balance synchronization
- Include proper error handling
- Add visual feedback for balance updates
✅ Agent Navigation
- Implement quick agent access panel
- Add proper agent linking
- Include agent discovery features
- Add smooth transitions and animations
Widget-Based Architecture
Core Layout Structure
<div class="agent-container">
<div class="agent-grid">
<!-- Left Column: Main Content -->
<div class="agent-main">
<div class="agent-header">...</div>
<div class="agent-form">...</div>
<div class="agent-output">...</div>
</div>
<!-- Right Column: Sidebar Widgets -->
<div class="agent-sidebar">
<div class="widget wallet-widget">...</div>
<div class="widget how-it-works-widget">...</div>
<div class="widget other-agents-widget">...</div>
</div>
</div>
</div>
CSS Custom Properties System
:root {
--primary: #000000;
--surface: #ffffff;
--surface-variant: #f8fafc;
--background: #f3f4f6;
--outline: #e4e7eb;
--outline-variant: #e1e4e7;
--on-surface: #1a1a1a;
--on-surface-variant: #6b7280;
--success: #10b981;
--error: #ef4444;
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 16px;
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 24px;
--spacing-xl: 32px;
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
--shadow-md: 0 4px 8px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 20px rgba(0, 0, 0, 0.15);
}
Widget Styling Standards
.widget {
background: var(--surface);
border: 1px solid var(--outline);
border-radius: var(--radius-md);
padding: var(--spacing-lg);
margin-bottom: var(--spacing-md);
box-shadow: var(--shadow-sm);
transition: all 0.2s ease;
}
.widget:hover {
box-shadow: var(--shadow-md);
}
.widget h3 {
margin: 0 0 var(--spacing-md) 0;
font-size: 1.125rem;
font-weight: 600;
color: var(--on-surface);
}
Security Implementation
HTML Sanitization Function
function safeSetHTML(element, htmlString) {
// Create temporary container
const temp = document.createElement('div');
temp.innerHTML = htmlString;
// Remove all script tags
const scripts = temp.querySelectorAll('script');
scripts.forEach(script => script.remove());
// Remove dangerous attributes
const allElements = temp.querySelectorAll('*');
allElements.forEach(el => {
// Remove event handlers
const attrs = el.attributes;
for (let i = attrs.length - 1; i >= 0; i--) {
const attr = attrs[i];
if (attr.name.startsWith('on') ||
attr.name === 'javascript:' ||
attr.name === 'data-') {
el.removeAttribute(attr.name);
}
}
// Remove dangerous href/src
if (el.tagName === 'A' && el.href && el.href.startsWith('javascript:')) {
el.removeAttribute('href');
}
if (el.tagName === 'IMG' && el.src && el.src.startsWith('javascript:')) {
el.removeAttribute('src');
}
});
// Set sanitized content
element.innerHTML = temp.innerHTML;
}
XSS Prevention Pattern
// Always validate and sanitize user input
function sanitizeInput(input) {
return input
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// Use when displaying user content
function displayUserContent(content) {
const sanitized = sanitizeInput(content);
const element = document.getElementById('output');
element.textContent = sanitized; // Use textContent, not innerHTML
}
Wallet Balance Integration
Dynamic Balance Validation
// CRITICAL: Always read balance dynamically from DOM
function validateWalletBalance() {
const walletBalanceElement = document.getElementById('walletBalance');
const currentBalance = walletBalanceElement ?
parseFloat(walletBalanceElement.textContent) : 0;
if (currentBalance < 4.00) {
showError('Insufficient wallet balance. Please top up your wallet.');
return false;
}
return true;
}
Balance Synchronization
function updateWalletBalance(newBalance) {
if (newBalance !== undefined) {
// Update header balance
const headerBalance = document.querySelector('a[data-wallet-balance]');
if (headerBalance) {
headerBalance.textContent = `💰 ${newBalance.toFixed(2)} AED`;
}
// Update page balance
const pageBalance = document.getElementById('walletBalance');
if (pageBalance) {
pageBalance.textContent = newBalance.toFixed(2);
}
}
}
Performance Optimization
Debounced Form Interactions
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// Usage for form validation
const debouncedValidation = debounce(validateForm, 300);
document.getElementById('jobForm').addEventListener('input', debouncedValidation);
Event Listener Management
class AgentManager {
constructor() {
this.eventListeners = [];
}
addEventListeners() {
// Store references for cleanup
const submitHandler = this.handleSubmit.bind(this);
const resetHandler = this.handleReset.bind(this);
document.getElementById('submitBtn').addEventListener('click', submitHandler);
document.getElementById('resetBtn').addEventListener('click', resetHandler);
// Store for cleanup
this.eventListeners.push(
{ element: document.getElementById('submitBtn'), event: 'click', handler: submitHandler },
{ element: document.getElementById('resetBtn'), event: 'click', handler: resetHandler }
);
}
cleanup() {
// Remove all event listeners
this.eventListeners.forEach(({ element, event, handler }) => {
if (element) {
element.removeEventListener(event, handler);
}
});
this.eventListeners = [];
}
}
Accessibility Implementation
ARIA Attributes
<!-- Form with proper ARIA labeling -->
<form id="agentForm" role="main" aria-label="Agent Input Form">
<div class="form-group">
<label for="inputField" class="form-label">
Input Description
<span class="required" aria-label="required">*</span>
</label>
<textarea
id="inputField"
name="input_text"
class="form-control"
placeholder="Enter your input here..."
aria-describedby="inputHelp"
aria-required="true"
rows="4">
</textarea>
<div id="inputHelp" class="form-text">
Provide clear, specific information for better results.
</div>
</div>
</form>
<!-- Loading state with proper ARIA -->
<div id="loadingState" class="loading-state"
aria-live="polite"
aria-label="Processing request"
style="display: none;">
<div class="spinner" role="status" aria-hidden="true"></div>
<span class="sr-only">Processing your request...</span>
</div>
Keyboard Navigation
// Ensure proper tab order and keyboard navigation
function enhanceAccessibility() {
// Add keyboard support for custom elements
document.querySelectorAll('.custom-button').forEach(button => {
button.setAttribute('tabindex', '0');
button.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
button.click();
}
});
});
// Add focus management
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && document.querySelector('.modal.active')) {
closeModal();
}
});
}
Quick Agent Access Implementation
Right-Slide Panel
<div class="widget other-agents-widget">
<h3>🤖 Explore Other Agents</h3>
<p>Discover more AI agents to boost your productivity</p>
<button class="btn btn-outline" onclick="showQuickAgentAccess()">
Quick Agent Access
</button>
</div>
<!-- Quick Access Panel -->
<div id="quickAgentPanel" class="quick-agent-panel">
<div class="panel-header">
<h3>🚀 Quick Agent Access</h3>
<button class="panel-close" onclick="hideQuickAgentAccess()">×</button>
</div>
<div class="panel-content">
<div class="agent-grid">
<!-- Agent cards populated dynamically -->
</div>
</div>
</div>
Panel Styling
.quick-agent-panel {
position: fixed;
top: 0;
right: -400px;
width: 400px;
height: 100vh;
background: var(--surface);
border-left: 1px solid var(--outline);
box-shadow: var(--shadow-lg);
z-index: 1000;
transition: right 0.3s ease;
overflow-y: auto;
}
.quick-agent-panel.active {
right: 0;
}
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing-lg);
border-bottom: 1px solid var(--outline);
}
.panel-close {
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: var(--on-surface-variant);
}
Panel JavaScript
function showQuickAgentAccess() {
const panel = document.getElementById('quickAgentPanel');
const overlay = document.createElement('div');
overlay.className = 'panel-overlay';
overlay.onclick = hideQuickAgentAccess;
document.body.appendChild(overlay);
panel.classList.add('active');
document.body.style.overflow = 'hidden';
// Load agents if not already loaded
if (!panel.dataset.loaded) {
loadQuickAgents();
panel.dataset.loaded = 'true';
}
}
function hideQuickAgentAccess() {
const panel = document.getElementById('quickAgentPanel');
const overlay = document.querySelector('.panel-overlay');
panel.classList.remove('active');
document.body.style.overflow = '';
if (overlay) {
overlay.remove();
}
}
function loadQuickAgents() {
const agents = [
{
name: 'Data Analyzer',
description: 'Analyze and interpret your data files with AI precision',
url: '/data-analyzer/',
emoji: '📊'
},
{
name: 'Job Posting Generator',
description: 'Create professional job postings in minutes',
url: '/job-posting-generator/',
emoji: '💼'
},
// Add more agents as needed
];
const container = document.querySelector('#quickAgentPanel .agent-grid');
container.innerHTML = agents.map(agent => `
<div class="agent-card">
<div class="agent-emoji">${agent.emoji}</div>
<h4>${agent.name}</h4>
<p>${agent.description}</p>
<a href="${agent.url}" class="btn btn-primary btn-sm">
Try Now
</a>
</div>
`).join('');
}
Form Validation Patterns
Client-Side Validation
function validateForm() {
const form = document.getElementById('agentForm');
const inputs = form.querySelectorAll('input, textarea, select');
let isValid = true;
inputs.forEach(input => {
const errorElement = document.getElementById(`${input.id}-error`);
// Clear previous errors
input.classList.remove('is-invalid');
if (errorElement) {
errorElement.textContent = '';
}
// Validate required fields
if (input.hasAttribute('required') && !input.value.trim()) {
showFieldError(input, 'This field is required');
isValid = false;
}
// Validate specific field types
if (input.type === 'email' && input.value && !isValidEmail(input.value)) {
showFieldError(input, 'Please enter a valid email address');
isValid = false;
}
if (input.type === 'url' && input.value && !isValidURL(input.value)) {
showFieldError(input, 'Please enter a valid URL');
isValid = false;
}
});
return isValid;
}
function showFieldError(input, message) {
input.classList.add('is-invalid');
const errorElement = document.getElementById(`${input.id}-error`);
if (errorElement) {
errorElement.textContent = message;
}
}
function isValidEmail(email) {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
}
function isValidURL(url) {
try {
new URL(url);
return true;
} catch {
return false;
}
}
Error Handling Patterns
User-Friendly Error Display
function showError(message, type = 'error') {
const errorContainer = document.getElementById('errorContainer');
const errorElement = document.createElement('div');
errorElement.className = `alert alert-${type} alert-dismissible`;
errorElement.innerHTML = `
<span class="alert-icon">⚠️</span>
<span class="alert-message">${message}</span>
<button type="button" class="alert-close" onclick="this.parentElement.remove()">
×
</button>
`;
errorContainer.appendChild(errorElement);
// Auto-dismiss after 5 seconds
setTimeout(() => {
if (errorElement.parentNode) {
errorElement.remove();
}
}, 5000);
}
function showSuccess(message) {
showError(message, 'success');
}
Testing Requirements
UI/UX Testing Checklist
- Test widget responsive behavior on different screen sizes
- Verify wallet balance updates in real-time
- Test form validation with various input combinations
- Verify accessibility with screen reader
- Test keyboard navigation through all interactive elements
- Check quick agent access panel functionality
- Verify error handling and user feedback
- Test performance with large outputs
Security Testing
- Test XSS prevention with malicious inputs
- Verify HTML sanitization functions
- Test CSRF protection
- Check for sensitive data exposure
- Validate input sanitization
Deployment Checklist
Pre-Deployment
- Run all tests and ensure they pass
- Check for console errors
- Verify accessibility compliance
- Test on multiple browsers
- Validate HTML and CSS
- Check for unused CSS/JS
- Optimize images and assets
- Test with real user data
Post-Deployment
- Monitor for JavaScript errors
- Check wallet balance functionality
- Verify agent processing works correctly
- Test performance metrics
- Monitor user feedback
- Check analytics for usage patterns
Maintenance Guidelines
Regular Updates
- Keep dependencies updated
- Monitor for security vulnerabilities
- Update accessibility standards
- Review performance metrics
- Update documentation
Code Quality
- Follow consistent coding standards
- Use proper commenting
- Implement proper error handling
- Add comprehensive tests
- Regular code reviews
This guide ensures that all future agents follow the same optimized patterns, preventing UI/UX failures and maintaining consistency across the platform.