# Extensions And Components

> Use HTML adapters, JS hook seams, and component loading correctly in the layered module system.

- Skill: `agent0ai/extensions-and-components` (Agent Skill)
- Install (CLI): `npx skillmds@latest add agent0ai/extensions-and-components`
- Raw SKILL.md: https://api.skillmd.com/api/skills/agent0ai/extensions-and-components/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: agent0ai (https://skillmd.com/u/agent0ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/agent0ai/extensions-and-components

---


Use this skill when the task needs `ext/html/`, `ext/js/`, `x-extension`, `x-component`, `x-context`, or layered override behavior.

## HTML Extension Rules

- Declare structural seams with `<x-extension id="some/path">`.
- Matching HTML files live at `mod/<author>/<repo>/ext/html/some/path/*.html`.
- HTML callers name only the seam; the runtime resolves `ext/html/` automatically.
- Keep extension files thin. They should usually mount a real component with `<x-component path="/mod/...">`.
- `_core/framework` also creates `_core/framework/head/end` in `document.head` during bootstrap when a layer needs head-side HTML or inline bootstrap code without editing page shells.
- Use framework `x-inject="selector"` instead of raw Alpine `x-teleport` when route-owned markup targets a shell seam that may mount later; it mirrors teleport semantics for `<template>` roots, waits for the selector, and disconnects its observer when the source template unmounts.
- Dynamic discovery watches the whole document tree, so `head` seams and the `x-component` nodes they insert are loaded the same way as body content.
- The routed shell header owns Home itself and points it at the empty route `#/`; `_core/onscreen_menu/bar_start` and `_core/onscreen_menu/bar_end` are the left and right shell-control seams, and feature modules add non-Home dropdown menu-action buttons under `_core/onscreen_menu/items` with numeric `data-order` values such as `100`, `200`, `300`, and `400`; `_core/onscreen_menu` sorts contributed controls or items automatically and keeps only the auth exit action after the dropdown seam.

Example:

```html
<x-extension id="page/router/overlay/end"></x-extension>
```

```html
<x-component path="/mod/_core/onscreen_agent/panel.html"></x-component>
```

## JS Hook Rules

- Use `space.extend(import.meta, async function name(...) { ... })` for behavioral seams.
- JS hook files live at `mod/<author>/<repo>/ext/js/<extension-point>/*.js` or `*.mjs`.
- The runtime resolves `/start` and `/end` hooks around the wrapped function automatically.
- `space.extend()` requires a valid module ref and a standalone named function or explicit extension point name.
- Framework-backed pages expose `_core/framework/initializer.js/initialize`; use `_core/framework/head/end` when the work can stay declarative, and keep the initializer `/end` hook for once-per-page shell setup that must stay imperative.
- If a feature needs onscreen-agent-specific prompt shaping or execution validation for its own helpers, add an `ext/js/_core/onscreen_agent/...` hook from that feature instead of editing `_core/onscreen_agent` directly.

## Extension Metadata Rules

- Modules may also store lightweight metadata assets under other `ext/` folders when those files should follow the same readable-layer permissions and same-path override rules as HTML and JS extensions.
- The current first-party example is `ext/panels/*.yaml`, which the dashboard panel index discovers through `file_paths`, batch-reads through `fileRead(...)`, and collapses to one effective manifest per `modulePath + manifestName`.
- Keep those metadata files display-oriented. They are extension-resolved module assets, not general writable storage.

## Component Loader Rules

- `<x-component>` may load a full HTML document or a fragment.
- The loader mounts styles, module scripts, and body nodes, then recursively resolves nested `<x-component>` tags.
- Concurrent scans of the same `<x-component>` target reuse the in-flight load; they must not bail out in a way that leaves late-mounted components partially hydrated.
- Mutation-driven `x-component` discovery watches `document.documentElement`, not only `body`, so head-side components hydrate too.
- Keep component HTML declarative and bind behavior through stores.
- Import the owning store module in the component that owns the feature, not in an unrelated parent shell.

## Context Helper Rules

- Framework bootstrap also injects one hidden runtime `<x-context>` with `data-runtime="browser"` on normal web sessions or `data-runtime="app"` in the packaged desktop runtime; packaged app routes derive that from the desktop bridge before falling back to launcher runtime info or frontend config, and that same element also exposes `runtime-browser` or `runtime-app` through `data-tags`.
- Modules may export additional live skill-filter tags with hidden `<x-context>` elements anywhere in mounted DOM.
- Set one or more tags with `data-tags="a, b, c"`.
- Alpine-bound attributes on `<x-context>` are the normal way to keep tags synced with route or store state.
- Import `/mod/_core/framework/js/context.js` when code needs to inspect current `<x-context>` elements directly; the stable helpers are `getContexts(...)`, `getAttributeValues(...)`, `getTags(...)`, and `getContents(...)`.
- Shared skill discovery reads those tags through that framework helper each time it builds the catalog, auto-loaded skill context, or an explicit skill load.

## Layered Override Behavior

- Module and extension resolution follow the readable `L0 -> L1 -> L2` inheritance chain.
- Identical module-relative extension file paths override lower-ranked entries.
- Different filenames under the same extension point compose together.
- Prefer additive composition before exact-path replacement.
- `maxLayer` constrains module and extension resolution but not logical app-file paths.
- Uncached HTML `<x-extension>` lookups batch before they call `/api/extensions_load`; the default flush is the next animation frame, and frontend constant `HTML_EXTENSIONS_LOAD_BATCH_WAIT_MS` in `app/L0/_all/mod/_core/framework/js/extensions.js` adds an extra wait window in milliseconds before that frame-aligned flush.
- `extensions_load` keeps `maxLayer` at the call level; grouped lookups send ordered `patterns` arrays and receive ordered results with matching `patterns` plus resolved `extensions`.
- JS hook lookups do not use that wait window; they resolve immediately because hook callers await them directly.

## Practical Guidance

- Add a new seam in the owner when downstream customization is realistic.
- Do not bypass an existing seam by reaching into another module's private DOM or internals.
- After adding a new `ext/html/...` or `ext/js/...` file, the running page often needs a refresh before discovery catches up.

## Mandatory Doc Follow-Up

- If extension lookup, component loading, hook behavior, or override semantics change, update the framework docs and the `development` skill subtree in the same session.

