# IHF Annotation Launcher `static/js/ihf-annotation-launcher.js` is a self-contained vanilla JS module that injects an **Annotate** button adjacent to every element that carries a `data-widget-id` attribute. It works in IHP server-rendered pages **and** in React/Vue pages where IHP does not own the DOM — the launcher relies solely on the presence of `data-widget-id`, not on any framework-specific structure. ## Activation Set the environment variable before starting the server: ```bash IHP_ANNOTATION_LAUNCHER=true devenv up ``` This causes IHP to emit the following tag in every page's ``: ```html ``` When `IHP_ANNOTATION_LAUNCHER` is absent or not `"true"`, the script is not loaded. ## Data attributes | Attribute | Required | Description | |--------------------|----------|--------------------------------------------------| | `data-widget-id` | Yes | UUID of the widget (from the widget registry) | | `data-hub-id` | No | UUID of the hub — read from element or nearest ancestor | | `data-view-context`| No | Logical UI location (informational) | ## Usage in React Because the launcher uses `MutationObserver`, it will pick up React-rendered elements after mount: ```jsx function MyWidget({ widgetId, hubId }) { return (
); } ``` No other integration is required. The launcher injects the Annotate button and handles POST submission to `/widgets/:widgetId/annotations`. ## Programmatic re-scan If your SPA does client-side navigation without full page reloads, call: ```js window.IHFAnnotationLauncher.scan(); ``` ## Submission The launcher POSTs `application/x-www-form-urlencoded` to: ``` POST /widgets/:widgetId/annotations ``` Fields submitted: `body`, `category`, `severity` (fixed `low`), CSRF token. Responses: - `200` or redirect → success (form closes with confirmation) - Any non-OK response → inline error message ## CSRF The launcher reads the CSRF token from ``. IHP emits this tag automatically in authenticated layouts.