Skip to main content

Declarative Site Adapters

Site Adapters are JSON configurations that tell the Appilot extension how to behave on a specific web application. They solve a fundamental challenge: not all web apps work the same way.

The Problem​

Standard web applications change their URL when users navigate between pages. Appilot uses URL patterns to match knowledge content to the current page. Some frameworks break that assumption. Vaadin, GWT, and Ext JS build single-page applications where the URL never changes. Form elements may be wrapped in Shadow DOM, and every user action triggers a server roundtrip.

Without adapters, the extension cannot:

  • Know which page the user is on
  • Find form fields inside Shadow DOM
  • Interact with framework-specific components

The Solution​

A Site Adapter provides structured rules that the extension runtime interprets. Nothing in it executes as code:

ConfigurationPurposeExample
runtime.shadow_dom_max_depthHow deep to traverse Shadow DOM6 for Vaadin (default: 3)
runtime.action_timeout_msWait time for DOM updates after actions3000 for server-roundtrip apps
page_detection.rulesDOM-based view identificationRead menu bar text to determine current view
interaction_overridesCustom interaction strategies per componentOpen-then-select for combo boxes
knowledge_hintsCross-cutting retrieval hintsAlways include domain_global scope

Schema​

{
"schema_version": "1.0",
"domain": "your-app.example.com",
"framework_hints": ["vaadin"],
"runtime": {
"shadow_dom_max_depth": 6,
"action_timeout_ms": 3000,
"mutation_observer_debounce_ms": 500
},
"page_detection": {
"strategy": "dom_selector",
"rules": [
{
"selector": "vaadin-menu-bar [selected]",
"read": "innerText",
"map": {
"Online Services": { "view_path": "zufi/online-services" }
}
}
]
},
"interaction_overrides": {},
"knowledge_hints": {
"always_include_scopes": ["domain_global"]
}
}

Page detection resolves to a view path, which matches a view configured for the domain. Knowledge is linked to views, so retrieval is driven by view identity rather than by the URL.

How It Works​

  1. Extension loads on a domain
  2. Fetches adapter config from GET /apps/domains/adapter/lookup?domain=<hostname>
  3. Caches locally (5-minute TTL)
  4. Applies runtime overrides (Shadow DOM depth, timeouts)
  5. Uses page detection rules to identify the current view (resolved to a view_path)
  6. Retrieves knowledge content linked to that view via content_views
  7. Uses interaction overrides for framework-specific components

Credential fields are out of reach​

An interaction override changes how a field is driven, never whether it may be driven. Password fields, one-time-code fields, payment-card fields and hidden fields are decided by one rule that every reader and every writer consults, and an adapter cannot open them. That covers the paths an adapter exists for: a value written into a shadow-root input, a custom element whose host takes the value directly, and an open-then-select combo box. A read reports the field and whether it is filled; a write is refused.

If your application builds a password box out of something that is not a real form control, the rule cannot recognise it, which is worth knowing before you write an override that reaches it.

Extensibility​

The strategy fields are extension points. Currently supported:

  • Page detection: dom_selector, which reads DOM elements to determine the current page
  • Interaction: open_then_select, for combo boxes that need a click to open

Future strategies can be added without schema changes, because the extension dispatches to handlers based on the strategy name.

API Endpoints​

MethodEndpointAuthPurpose
GET/apps/domains/adapter/lookup?domain=<name>PublicExtension fetches config
GET/apps/domains/:id/adapterJWTRead adapter for a domain
PUT/apps/domains/:id/adapterJWTUpdate adapter config