# Usage guide

## 1. Start the receiver

```sh
npx annotate-loop-receiver
# annotate receiver listening on http://127.0.0.1:8787 (loopback only) → data/annotations
```

Options: `--port=<n>` (default `8787`), `--out-dir=<dir>` (default
`data/annotations`). The host is always `127.0.0.1` — loopback-only by
design, never exposed. The receiver answers CORS preflight so the picker can
POST cross-origin (page port → receiver port). `GET /health` is a liveness
check.

A manual end-to-end fixture lives at `tests/fixtures/e2e/index.html`: serve
it plus `src/picker/annotate-picker.js` on one localhost port, run the
receiver, inject the picker, click, send, and confirm a job files.

Keep the intake dir out of long-lived branches:

```gitignore
data/annotations/*.json
!data/annotations/.gitkeep
```

## 2. Arm the picker

**Bookmarklet (any localhost page, any port):** build once, paste the whole
`javascript:…` file content as a new bookmark's URL, then click that bookmark
on any localhost tab:

```sh
npx annotate-loop-bookmarklet --out=bookmarklet.txt
```

Non-default receiver port? Set the override before arming (e.g. in devtools
console, or bake it into a second bookmarklet run):

```js
window.__annotateReceiverUrl = 'http://127.0.0.1:9999/annotate';
```

**Badge (pilot pages):** mount the framework adapter on pilot pages only —
homepage plus pilot collection pages, not site-wide. See
[examples/astro-usage.md](../examples/astro-usage.md).

## 3. File an annotation

Hover to highlight, click to freeze. The panel shows the captured component
hint and CSS path. Pick an instruction type (`fix` / `copy` / `layout` /
`style` / `other`), describe the change, hit **Send**.

Each bundle carries overlapping location evidence so the spot survives
restyles:

| Field | Purpose |
|---|---|
| `pageUrl` | Which page (localhost only — the receiver rejects anything else) |
| `componentHint` | Nearest `data-component` / `data-annotate` / `data-testid` / `#id` / landmark, else tag |
| `cssPath` | Full CSS path down to the element |
| `xpath` | Id-anchored when possible, positional otherwise |
| `element` | Tag + 160-char text excerpt |
| `viewport` | Width, height, devicePixelRatio |
| `screenshot` | PNG data-URL (SVG `foreignObject`, dependency-free); degrades to `{kind:'unavailable', reason}` when canvas is tainted — locator evidence still files |
| `instruction` | `{type, text}` — the requested change |

## 4. Receiver unreachable? Clipboard fallback

If the receiver is down, the picker copies the full JSON bundle to the
clipboard and shows it in-panel for manual copy. Paste it as a new file under
the intake dir (any `<name>.json`) — same shape, same durability. A backup
copy is also placed on the clipboard after every successful send.

## 5. Triage jobs

Filed jobs are intake, not instructions:

1. Read `data/annotations/*.json`.
2. **Re-verify the spot against the live page** before cutting code
   (see [reverification](reverification.md)) — never trust a stale path blind.
3. Implement the change.
4. Archive/delete the job file. Do not commit screenshots or jobs to
   long-lived branches.
