@loupekit/sdk 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # @loupekit/sdk
2
+
3
+ **Embeddable visual-feedback widget for the web.** Drop it into any running product and
4
+ your team can inspect an element, pin a comment to it, and capture a screenshot. Comments
5
+ **persist and re-anchor across redeploys**, and are handed to **Claude Code via MCP** as a
6
+ fully-contextualized, actionable backlog.
7
+
8
+ Part of [**Loupe**](https://github.com/mohamed-ashraf-elsaed/loupe) — the loop is:
9
+ SDK (in your product) → backend API → Postgres + object storage → dashboard (human triage)
10
+ **and** MCP server (Claude reads it) → status flows back.
11
+
12
+ ---
13
+
14
+ ## Why
15
+
16
+ Traditional feedback ("the header looks off on the pricing page") loses the one thing an
17
+ engineer needs: **which element, in what state, on which page.** Loupe captures all of it at
18
+ the moment of the comment — a multi-signal element fingerprint, the target's HTML + computed
19
+ styles, a screenshot, and the normalized URL — so the feedback stays actionable even after
20
+ the UI changes underneath it.
21
+
22
+ ## Features
23
+
24
+ - 🎯 **Click-to-comment inspector** — hover-highlight any element, click to pin a comment.
25
+ - ▭ **Free-region screenshots** — drag a free-size box, screenshot exactly that area, and
26
+ comment on it. The region anchors to the element under its center, so it tracks responsive
27
+ reflow and scrolling.
28
+ - 🔁 **Redeploy-surviving re-anchoring** — a multi-signal fingerprint (stable id/testid, CSS
29
+ path, XPath, text, attributes, position) re-locates the element on the current page; if it
30
+ can't, the pin **detaches** rather than pointing at the wrong thing.
31
+ - 📸 **Screenshot capture** with `[data-loupe-redact]` regions blurred out before anything
32
+ leaves the browser.
33
+ - 🧩 **Shadow-DOM isolation** — the widget's CSS never leaks into your page and vice-versa.
34
+ - 🔌 **Pluggable storage** — talks to the Loupe backend, or persists to `localStorage` for
35
+ offline/demo use.
36
+ - 🤖 **Claude-ready** — every comment carries the context Claude Code needs to make the fix.
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ npm i @loupekit/sdk
42
+ ```
43
+
44
+ > Also mirrored to **GitHub Packages** as `@mohamed-ashraf-elsaed/sdk`. To install from there,
45
+ > add `@mohamed-ashraf-elsaed:registry=https://npm.pkg.github.com` to your `.npmrc`.
46
+
47
+ ## Quick start
48
+
49
+ ```ts
50
+ import { init } from "@loupekit/sdk";
51
+
52
+ init({
53
+ projectKey: "pk_live_yourkey",
54
+ user: { id: "u_92", name: "Sara (PM)", email: "sara@acme.com" },
55
+ apiBase: "https://loupe.yourbackend.com",
56
+ // HMAC-SHA256(user.id, PROJECT_SECRET), computed on your server (see Auth below).
57
+ userHmac: "decb2c…",
58
+ });
59
+ ```
60
+
61
+ That's it — a floating toolbar appears with **Inspect & comment**, **Region shot**, and
62
+ **Comments**. Call `destroy()` to tear it down.
63
+
64
+ ### Offline mode (no backend)
65
+
66
+ Omit `apiBase` and comments persist to `localStorage`. Great for demos and local dev.
67
+
68
+ ```ts
69
+ init({ projectKey: "pk_demo", user: { id: "u_1", name: "You" } });
70
+ ```
71
+
72
+ ## Configuration
73
+
74
+ `init(config: LoupeConfig)`:
75
+
76
+ | Option | Type | Description |
77
+ | ------------------ | ------------------------------------------------ | --------------------------------------------------------------------------------------------- |
78
+ | `projectKey` | `string` **(required)** | Public project key issued by the backend. |
79
+ | `user` | `{ id, name, email? }` **(required)** | The already-authenticated host-app user. |
80
+ | `apiBase` | `string` | Backend base URL. Omit → `localStorage` (offline mode). |
81
+ | `userHmac` | `string` | `HMAC-SHA256(user.id, PROJECT_SECRET)` computed server-side. Required in production for writes. |
82
+ | `autoOpen` | `boolean` | Start with the inspector already active. |
83
+ | `captureScreenshot`| `(el: Element) => Promise<string \| undefined>` | Override element screenshot capture (the extension backs this with `captureVisibleTab`). |
84
+ | `captureRegion` | `(rect: RegionRect) => Promise<string \| undefined>` | Override free-region capture. `rect` is in viewport coordinates. |
85
+ | `headers` | `Record<string, string>` | Extra headers merged into every backend request (e.g. a CSRF token). |
86
+ | `credentials` | `RequestCredentials` | `credentials` mode for backend requests — set `"include"` for cross-origin cookie auth. |
87
+
88
+ ## Redaction
89
+
90
+ Any element marked `data-loupe-redact` is painted over in screenshots **before the pixels
91
+ ever leave the browser** — use it on PII, secrets, or anything sensitive:
92
+
93
+ ```html
94
+ <input data-loupe-redact value="secret.person@acme.com" />
95
+ ```
96
+
97
+ ## Auth model
98
+
99
+ Each project has a secret. **Writes** require `X-Loupe-User` + `X-Loupe-Hmac`
100
+ (`= HMAC-SHA256(userId, PROJECT_SECRET)`), which your server computes and injects into the
101
+ page — users can't spoof identity. The dashboard and MCP server authenticate as admin with
102
+ the raw secret. See the [Auth docs](https://github.com/mohamed-ashraf-elsaed/loupe#auth-model).
103
+
104
+ ## Extending the storage seam
105
+
106
+ Anything implementing `StorageAdapter` can back the widget — swap in your own transport:
107
+
108
+ ```ts
109
+ interface StorageAdapter {
110
+ list(projectKey: string, url: string): Promise<Comment[]>;
111
+ save(comment: Comment): Promise<Comment>;
112
+ update(id: string, patch: Partial<Comment>): Promise<void>;
113
+ remove(id: string): Promise<void>;
114
+ }
115
+ ```
116
+
117
+ ## Browser support
118
+
119
+ Modern evergreen browsers (Chromium, Firefox, Safari). Uses Shadow DOM, `MutationObserver`,
120
+ and the `crypto`/`clipboard` APIs.
121
+
122
+ ## Related packages
123
+
124
+ - [`@loupekit/mcp`](https://www.npmjs.com/package/@loupekit/mcp) — MCP server that hands the
125
+ comments to Claude Code.
126
+ - [`@loupekit/shared`](https://www.npmjs.com/package/@loupekit/shared) — the canonical types.
127
+
128
+ ## License
129
+
130
+ MIT © [Mohamed Ashraf Elsaed](https://github.com/mohamed-ashraf-elsaed)