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:
- Registration -- The
@register_moduledecorator adds the module class to the global registry at import time. - Detection -- The framework scans HTML for module-specific signals (regex patterns) to decide whether to activate conditional modules.
- Analysis -- The
analyse()method extracts signals from HTML content and response headers. - 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:
- Start with core modules --
seo,security,accessibility,performance - Add the links module -- always useful
- Scan HTML for detection signals -- regex patterns per module
- Add site-type modules -- if a site type hint is provided (e.g.
"ecommerce"adds the ecommerce module) - Apply force_enable overrides -- add any explicitly requested modules
- 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:
- Create
scripts/modules/my_module.py - Subclass
AuditModuleand implementanalyse()andscore() - Decorate with
@register_module - Import in
scripts/modules/__init__.py - Optionally add to profiles in
scripts/profiles.py - Add detection signals to
DETECTION_SIGNALSif it should auto-detect
See the Module API reference for the full AuditModule interface and the Contributing guide for the complete process.