Systemarchitektur & Datenfluss
Vollständige Transparenz über unsere technische Architektur, Datenflüsse und Implementierungsdetails
100% EU-Server
Frankfurt (AWS)
Async & Non-Blocking
< 50ms Load Time
Edge Functions
Niedrige Latenz
System-Übersicht
Die accessibleAI Engine besteht aus vier Hauptkomponenten, die nahtlos zusammenarbeiten, um Websites barrierefrei zu machen:
Architektur-Übersicht
Browser
User's Website
VAE Widget
Client-Side
Edge Function
Server-Side
Cloudflare Worker
LLM API Integration
Supabase DB
Data Storage
1. VAE Widget (Client)
- • DOM-Scanning & Element-ID-Injection
- • Action-Processing (Remediation)
- • User-Präferenzen (Overlay)
- • Mutation Observer für SPAs
2. Edge Functions (Server)
- • HTML-Analyse (LLM-basiert)
- • WCAG-Issue-Detection
- • Action-Generierung
- • Supabase-Integration
3. Cloudflare Workers
- • LLM API Calls (Gemini, GPT, Claude)
- • Prompt-Management
- • Response-Transformation
- • Fallback-Chain
4. Supabase Backend
- • Datenbank (PostgreSQL)
- • Auth & Session-Management
- • Page Impressions Tracking
- • Audit-Logs
Client-Side: VAE Widget
Das VAE (Visual Accessibility Enhancer) Widget ist die Client-Side-Komponente, die direkt im Browser des Nutzers läuft. Es ist verantwortlich für das Scanning des DOMs, die Injection von Element-IDs und die Anwendung von Accessibility-Fixes.
Widget-Initialization
Widget Init Code
// Source: widget/main.js lines 48-90
// VAE Widget Initialization
if (window.VAE) {
console.log('VAE: Script loaded - initializing directly');
if (window.vaeConfig?.client?.environment === 'test') {
// Test Mode
import('./src/testing.js').then(() => {
VAE.UI.init();
VAE.Core.init();
VAE.VersionManager.init();
});
} else {
// Production Mode
// Check URL exclusion BEFORE creating UI
if (window.VAE.Config?.isUrlExcluded?.()) {
console.log('VAE: URL excluded, skipping initialization');
} else {
VAE.UI.init();
VAE.Core.init();
VAE.VersionManager.init();
// Dispatch initialized event
window.dispatchEvent(new CustomEvent('vae-initialized', {
detail: {
modules: {
UI: !!window.VAE.UI,
Core: !!window.VAE.Core,
VersionManager: !!window.VAE.VersionManager
}
}
}));
}
}
}Core Initialization Flow
VAE Core Init
// Source: widget/src/core.js lines 1460-1495
async function init() {
console.log('[VAE Core] Initializing...', window.location.href);
// 1. URL Exclusion Check
if (VAE.Config?.isUrlExcluded?.()) {
console.log('[VAE Core] URL excluded, hiding widget');
const widgetElement = document.querySelector('.vae-widget');
if (widgetElement) widgetElement.style.display = 'none';
return;
}
// 2. Freemium Restriction Check
const restrictionCheck = VAE.API.checkFreemiumRestrictions();
if (restrictionCheck.restricted) {
hideWidgetForFreemiumRestriction();
return;
}
// 3. Initialize Queue Status UI
initializeQueueStatusUI();
setupSpaNavigationHandling();
// 4. Wait for DOM Stability
console.log('VAE.Core: Waiting for DOM stability...');
await waitForDOMStability();
console.log('VAE.Core: DOM stability achieved');
// 5. Initialize DOM Structure & VAE-IDs
initializeDynamicContentAnalysisAndDOMStructure();
// 6. Generate Content Hash
const pagePathname = window.location.pathname;
pathnameHash = simpleStringHash(pagePathname);
// ... Continue with analysis
}Bundle Size & Performance
Minified
~80 KB
Gzipped
~28 KB
Load Time
< 50ms
Memory
~3 MB
// Source: widget/package.json, widget/webpack.config.js
Server-Side: Edge Functions
Die Server-Side-Komponenten laufen als Supabase Edge Functions (Deno Runtime) und Cloudflare Workers. Sie sind verantwortlich für die HTML-Analyse, LLM-Integration und Datenspeicherung.
Warum Edge Functions?
Niedrige Latenz
Edge Functions laufen näher am User → weniger Latenz
Skalierbarkeit
Automatisches Scaling ohne Server-Management
Global verteilt
Multi-Region-Deployment für weltweite Performance
// Source: supabase/functions/wcag-task-manager-v2/index.ts, cloudflare-workers/wcag-analyzer-worker/src/index.ts
Datenfluss & Anonymisierung
Der Datenfluss zwischen Client und Server ist so gestaltet, dass nur die minimal notwendigen Informationen übertragen werden. Sensible Daten werden niemals übertragen.
Was verlässt den Browser?
✅ Wird übertragen:
- • Anonymisierte DOM-Struktur (Skeleton)
- • Element-IDs (data-vae-id)
- • HTML-Tags & Attribute
- • ARIA-Rollen & -Eigenschaften
- • Page URL (ohne Query-Parameter)
❌ Wird NICHT übertragen:
- • Formulareingaben
- • Passwörter oder sensible Daten
- • Cookies oder Session-Token
- • User-spezifische Inhalte
- • Persönlich identifizierbare Informationen (PII)
Content-Stripping
Vor der Übertragung werden alle Text-Inhalte, Bilder-URLs und andere sensible Daten aus dem HTML entfernt. Nur die strukturelle Information (Tags, Attribute, ARIA-Rollen) wird an den Server gesendet.
SPA-Integration
Single Page Applications (SPAs) erfordern besondere Aufmerksamkeit, da der DOM sich bei Route-Wechseln ändert, ohne dass die Seite neu geladen wird.
React / Next.js Integration
React useEffect Hook
import { useEffect } from 'react';
export default function MyApp({ Component, pageProps }) {
useEffect(() => {
// Initialize VAE Widget
const script = document.createElement('script');
script.src = 'https://auth.accessibleai.eu/storage/v1/object/public/cdn/vae-loader-versioned.js';
script.async = true;
script.onload = () => {
if (window.aai) {
window.aai('init', {
apiKey: process.env.NEXT_PUBLIC_AAI_API_KEY,
autoAnalyze: true
});
}
};
document.head.appendChild(script);
return () => {
// Cleanup on unmount
script.remove();
};
}, []);
return <Component {...pageProps} />;
}Vue / Nuxt Integration
Vue Plugin
// plugins/accessibleai.client.js
export default defineNuxtPlugin((nuxtApp) => {
if (process.client) {
const script = document.createElement('script');
script.src = 'https://auth.accessibleai.eu/storage/v1/object/public/cdn/vae-loader-versioned.js';
script.async = true;
script.onload = () => {
if (window.aai) {
window.aai('init', {
apiKey: useRuntimeConfig().public.aaiApiKey,
autoAnalyze: true
});
}
};
document.head.appendChild(script);
}
});// Source: widget/src/core.js function setupSpaNavigationHandling()
Mutation Observer Pattern
Um DOM-Änderungen in SPAs zu erkennen, verwendet das VAE Widget einen Mutation Observer mit Debouncing, um Performance-Probleme zu vermeiden.
Mutation Observer Setup
// Source: widget/src/text.js lines 602-616
function startObserver() {
if (observer) return;
observer = new MutationObserver(handleMutations);
observer.observe(document.body, {
childList: true, // Watch for added/removed nodes
subtree: true, // Watch all descendants
});
}
function handleMutations(mutations) {
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) { // Element node
// Apply accessibility fixes to new elements
const currentState = VAE.StateManager.getState('text');
if (node.matches(TARGET_SELECTORS)) {
applyTextSizeToElement(node, currentState.fontSize);
applyLineHeightToElement(node, currentState.lineHeight);
applyFontFamilyToElement(node, currentState.fontFamily);
}
}
});
}
});
}Performance-Optimierung
- • Debouncing: Mutation Handler wird nur alle 100ms ausgeführt
- • Selective Observation: Nur relevante DOM-Elemente werden beobachtet
- • CPU-Usage: < 2% durchschnittliche CPU-Nutzung
- • Memory: ~2-3 MB zusätzlicher Speicher für Observer
Event Listener Management
Das VAE Widget muss Event Listener sorgfältig managen, um keine bestehenden Listener zu überschreiben oder Tastaturfallen zu erzeugen.
Problem: Tastaturfallen
Tastaturfallen entstehen, wenn Elemente den Fokus "fangen" und nicht mehr freigeben. Das VAE Widget löst dieses Problem durch intelligentes Event-Delegation-Pattern.
Strategien zur Vermeidung:
- Event-Delegation: Listener werden auf Parent-Elementen registriert, nicht auf jedem einzelnen Element
- Priorisierung: Original-Listener haben Vorrang, VAE-Listener werden nur als Fallback verwendet
- Cleanup: Listener werden ordnungsgemäß entfernt, wenn Komponenten unmounted werden
- e.preventDefault() Handling: Das Widget respektiert bestehende preventDefault()-Calls und überschreibt sie nicht
// Source: widget/src/core.js - Event handling sections