Technische Architektur

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