Skip to content

Module System Architecture

FAT Agent uses a modular architecture where each audit concern is encapsulated in a self-contained module. Modules are discovered at import time via a decorator-based registry, and the framework decides which modules to run based on HTML signal detection, site type hints, and user overrides.


How Modules Work

Every module follows the same lifecycle:

  1. Registration -- The @register_module decorator adds the module class to the global registry at import time.
  2. Detection -- The framework scans HTML for module-specific signals (regex patterns) to decide whether to activate conditional modules.
  3. Analysis -- The analyse() method extracts signals from HTML content and response headers.
  4. Scoring -- The score() method converts analysis results into a numeric score (0--100) and a list of actionable findings.
HTML + Headers
      |
      v
  detect_modules()  -->  [seo, security, accessibility, ...]
      |
      v
  module.analyse(html, url, headers)  -->  analysis dict
      |
      v
  module.score(analysis)  -->  { total: 78, findings: [...] }

Module Categories

Core Modules

These four modules always run regardless of detection signals or profile:

Module ID Description
SEO seo Search engine optimisation fundamentals
Security security Security headers and mixed content
Accessibility accessibility WCAG compliance and inclusive design
Performance performance Page weight and loading performance

Conditional Modules

These modules activate when detection signals match or when explicitly requested:

Module ID Auto-Detected
Local SEO local_seo Yes -- LocalBusiness schema, Maps embeds, tel: links
E-commerce ecommerce Yes -- Product schema, cart elements, Shopify/WooCommerce
Email Deliverability email_deliverability Yes -- forms with email inputs
Internationalisation i18n Yes -- hreflang tags, language switchers
Link Checker links Always included (universally useful)
DNS & Infrastructure dns_infra No -- opt-in only
JS Bundle Analysis js_bundle No -- included in full profile
Content Quality content_quality No -- included in content/full profiles
Cookie & GDPR cookie_gdpr No -- included in security/full profiles
PWA Readiness pwa No -- included in full profile
Schema Validation schema_validator No -- included in SEO/full profiles
Sitemap Analysis sitemap No -- included in SEO/full profiles

The Module Registry

All modules are registered in scripts/modules/__init__.py. The registry is a dict mapping module IDs to their classes:

from modules import register_module
from modules.base import AuditModule

@register_module
class MyModule(AuditModule):
    MODULE_ID = "my_module"
    DISPLAY_NAME = "My Module"
    ALWAYS_ENABLED = False

Registry Functions

Function Purpose
register_module(cls) Decorator that adds a module class to the registry
detect_modules(html, site_type, force_enable, force_disable) Returns sorted list of module IDs to run
get_module(module_id) Returns the class for a given module ID
list_all_modules() Returns metadata for every registered module

Auto-Detection

The detect_modules() function builds the module list in this order:

  1. Start with core modules -- seo, security, accessibility, performance
  2. Add the links module -- always useful
  3. Scan HTML for detection signals -- regex patterns per module
  4. Add site-type modules -- if a site type hint is provided (e.g. "ecommerce" adds the ecommerce module)
  5. Apply force_enable overrides -- add any explicitly requested modules
  6. Apply force_disable overrides -- remove any explicitly excluded modules

Detection Signals

DETECTION_SIGNALS = {
    "ecommerce": [
        r"add-to-cart", r"shopping-cart",
        r'"@type"\s*:\s*"Product"',
        r"shopify", r"woocommerce",
    ],
    "i18n": [
        r"hreflang=", r"lang-selector",
        r"language-switcher",
    ],
    "local_seo": [
        r'"@type"\s*:\s*"(LocalBusiness|Restaurant|...)"',
        r"google\.com/maps/embed",
        r'href="tel:',
    ],
    "email_deliverability": [
        r"<form", r"contact-form",
        r'type="email"',
    ],
}

Adding a Custom Module

To add a new module:

  1. Create scripts/modules/my_module.py
  2. Subclass AuditModule and implement analyse() and score()
  3. Decorate with @register_module
  4. Import in scripts/modules/__init__.py
  5. Optionally add to profiles in scripts/profiles.py
  6. Add detection signals to DETECTION_SIGNALS if it should auto-detect

See the Module API reference for the full AuditModule interface and the Contributing guide for the complete process.