Adapters
Adapters are small bridges between Sercrod runtime behavior and an external environment. The core runtime stays focused on HTML attributes, host data, rendering, and browser-native behavior. Device APIs, build tools, test runners, and platform bridges belong in adapters.
Registry
Adapters are registered under window.__Sercrod.adapters.
Role selection lives in window.__Sercrod.adapter_map.
window.__Sercrod = window.__Sercrod || {};
window.__Sercrod.adapters = window.__Sercrod.adapters || {};
window.__Sercrod.adapter_map = window.__Sercrod.adapter_map || {};
The runtime exposes helper methods on the Sercrod class.
Sercrod.set_adapter("capacitor.filesystem", adapter);
Sercrod.use_adapter("file", "capacitor.filesystem");
Sercrod._get_adapter("file");
The name capacitor.filesystem resolves to
window.__Sercrod.adapters.capacitor.filesystem.
Design contract
- Sercrod owns host data, directive detection, expression evaluation, and DOM rendering inside a host.
- The adapter owns communication with the external environment.
- Return
falsewhen the adapter cannot handle a request and browser fallback should continue. - Return any other value when the adapter handled the request.
- Avoid global event interception for behavior that the runtime already handles.
- For AI-assisted work, read
/man.jsonfirst and start from__indexbefore tracing an adapter-specific path.
File role
The first runtime role is file. *save.file and
*load.file check _get_adapter("file") before running
the default browser behavior.
const adapter = {
name: "example.file",
async save(context){
return true;
},
async load(context){
return true;
}
};
For save(context), the context includes the host, rendered
element, source template element, raw attribute value, selected properties,
selected data, and source object.
For load(context), the context includes the host, rendered
element, source template element, raw attribute value, selected properties,
accept string, and apply_loaded_data(json, fileName).
Capacitor filesystem adapter
The official Capacitor filesystem adapter lives at
dist/adapters/capacitor/filesystem.js.
window.__Sercrod.adapters.capacitor.filesystem
window.__Sercrod.adapter_map.file = "capacitor.filesystem"
It lets *save.file and *load.file use Capacitor Filesystem
in a native wrapper while preserving browser fallback when Capacitor is not
available. The same adapter works for both Android and iOS; on macOS, open
the iOS native project in Xcode for the debug build step.
<script src="./sercrod.js"></script>
<script src="./adapters/capacitor/filesystem.js"></script>
For debugging inside the WebView console:
window.__Sercrod.adapter_map.file
window.SercrodCapacitorFilesystemAdapter.diagnose()
localStorage.getItem("sercrod-capacitor-filesystem:last-file")
localStorage.getItem("sercrod-capacitor-filesystem:last-status")
The file role should be capacitor.filesystem. A working
native build should report has_filesystem,
has_write_file, and has_read_file as true.
The status records show where save wrote, whether it could be read back
immediately, and why load failed if no saved file can be read.
On phone builds where the WebView console is inconvenient, the adapter also inserts a small status line after the Save or Load button. This status shows the directory and file name on success, or the plugin error on failure.
Browser storage backends
Browser storage is a backend choice, not a reason to keep adding
new directive families. Use the explicit action forms
*save.file, *load.file,
*save.session, *load.session,
*save.store, and *load.store, then place
custom backends behind an adapter or a small helper when those built-in
forms are not enough.
IndexedDB is a good fit for JSON snapshots, metadata, key-value
records, and indexes. Sercrod's built-in
*save.store and *load.store use IndexedDB
for JSON records. OPFS is a better fit for obvious image payloads,
suspiciously large Blob/File values, and larger app-local file-like
working directories. A practical design is to store large payloads
outside host data and keep only keys, backend names, paths, MIME
types, sizes, timestamps, and status fields in the host data.
{
saved: {
key: "todo-20260518",
name: "Todo snapshot",
size: 2048,
type: "application/json"
}
}
For *load.file, the file adapter bridge still converges
on the same operation: read JSON or source text from the backend, then
pass it into Sercrod's load merge path so Sercrod can merge it into
_stage or _data, dispatch
sercrod-loaded, and update the host. The built-in
*load.session and *load.store forms use that
same merge behavior after reading from browser storage.
Playwright SSG adapter
The Playwright SSG adapter is split into a browser bridge and a Node driver.
dist/adapters/playwright/bridge.js
dist/adapters/playwright/ssg.js
The bridge registers window.__Sercrod.adapters.playwright.ssg
and exposes render_document(args). The Node driver handles
URL/path mapping, partial loading, Playwright orchestration, HTML
beautification, and output file writing.
Fallback rules
Adapters should fail open unless the external environment already handled
the action. If an adapter cannot run, return false so Sercrod
can continue with the browser fallback.
If an adapter starts handling a request and the external operation fails, report the error through host data or events and return a handled value. In that case, browser fallback should not also run.