@fastbackr/react 0.0.0-stage → 0.0.3
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/LICENSE +46 -0
- package/README.md +216 -2
- package/dist/app-Cw3fHqqr.js +1615 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +132 -0
- package/package.json +66 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Fastbackr SDK License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OpsCom, Corp. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This license covers the "@fastbackr/react" npm package and its source code (the
|
|
6
|
+
"Software"). The Software is not open source. By installing or using it you
|
|
7
|
+
accept these terms.
|
|
8
|
+
|
|
9
|
+
1. Grant. OpsCom, Corp. grants you a free, non-exclusive, non-transferable,
|
|
10
|
+
non-sublicensable license to install and use the Software, solely to connect
|
|
11
|
+
your websites and applications to the Fastbackr service.
|
|
12
|
+
|
|
13
|
+
2. Redistribution. You may redistribute the Software only unmodified and only
|
|
14
|
+
as part of your own website or application. Bundling, minifying,
|
|
15
|
+
transpiling or tree-shaking the Software with your build tools, as part of
|
|
16
|
+
building your own website or application, is not a modification under
|
|
17
|
+
this license.
|
|
18
|
+
|
|
19
|
+
3. Restrictions. Except as section 2 allows, you may not:
|
|
20
|
+
a. modify, adapt or translate the Software, or create derivative works of
|
|
21
|
+
it;
|
|
22
|
+
b. distribute, publish or make available any modified version of the
|
|
23
|
+
Software;
|
|
24
|
+
c. use the Software with any service other than the Fastbackr service;
|
|
25
|
+
d. sell, rent, lease or sublicense the Software on its own;
|
|
26
|
+
e. remove or alter this license or any copyright notice;
|
|
27
|
+
f. reverse engineer, decompile or disassemble the Software, except to the
|
|
28
|
+
extent applicable law expressly permits it despite this restriction.
|
|
29
|
+
|
|
30
|
+
4. Ownership. The Software is licensed, not sold. OpsCom, Corp. keeps all
|
|
31
|
+
rights, title and interest in the Software not expressly granted here.
|
|
32
|
+
|
|
33
|
+
5. Termination. This license ends automatically if you breach any of its
|
|
34
|
+
terms. On termination you must stop using the Software and remove it from
|
|
35
|
+
your websites and applications.
|
|
36
|
+
|
|
37
|
+
6. No warranty. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
38
|
+
EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
|
|
39
|
+
A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
|
40
|
+
|
|
41
|
+
7. Limitation of liability. IN NO EVENT SHALL OPSCOM, CORP. BE LIABLE FOR ANY
|
|
42
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
43
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
|
44
|
+
OF OR OTHER DEALINGS IN THE SOFTWARE.
|
|
45
|
+
|
|
46
|
+
8. Governing law. This license is governed by the laws of the United States.
|
package/README.md
CHANGED
|
@@ -1,3 +1,217 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @fastbackr/react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Let reviewers click any element of your React app, or drag a box around any area, and leave a
|
|
4
|
+
comment on it. Comments show as numbered badges on the element or area, with replies, Done / Reopen
|
|
5
|
+
and a site-wide drawer.
|
|
6
|
+
|
|
7
|
+
- **One provider.** Wrap your app in `<FastbackrProvider>`. The UI is drawn inside a Shadow root with its own
|
|
8
|
+
stylesheet, so your CSS and ours never touch, whatever your app styles with.
|
|
9
|
+
- **Quiet until clicked.** A page view shows a small `+` button in the bottom-right corner, adds
|
|
10
|
+
two listeners and makes no requests. The first click on `+` loads the UI as a separate chunk.
|
|
11
|
+
- **Your app vouches for identity.** Your server trades its API key for a short-lived reviewer token.
|
|
12
|
+
The key never reaches a browser.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npm install @fastbackr/react @fastbackr/core
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
React 19 is a peer dependency. `@fastbackr/react` is the browser side; your server imports
|
|
21
|
+
`@fastbackr/core`:
|
|
22
|
+
|
|
23
|
+
| Import | Runs in | What it is |
|
|
24
|
+
| ------------------------ | ----------- | ------------------------------------------------------- |
|
|
25
|
+
| `@fastbackr/react` | Browser | `<FastbackrProvider>`, `useFastbackr()` |
|
|
26
|
+
| `@fastbackr/core/server` | Your server | `createTokenHandler`, `createReviewerToken`, the errors |
|
|
27
|
+
|
|
28
|
+
## Setup
|
|
29
|
+
|
|
30
|
+
You need a Fastbackr project and its API key (v1: created in the Fastbackr dashboard), with your site's
|
|
31
|
+
origins on the project's allowed list (`http://localhost:*` style patterns are fine).
|
|
32
|
+
|
|
33
|
+
### 1. Keep the API key on the server
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
# .env (server only)
|
|
37
|
+
FASTBACKR_API_KEY=fb_...
|
|
38
|
+
# Optional, for a self-hosted or local API. Defaults to https://api.fastbackr.com
|
|
39
|
+
FASTBACKR_URL=http://localhost:3300
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**`FASTBACKR_API_KEY` must never reach a browser.** Do not prefix it with `NEXT_PUBLIC_`, `VITE_` or
|
|
43
|
+
anything else that inlines it into client code, do not return it from a route, and do not log it.
|
|
44
|
+
Anyone holding it can mint tokens for any name on your project.
|
|
45
|
+
|
|
46
|
+
### 2. Add the token route
|
|
47
|
+
|
|
48
|
+
The SDK asks this route on your own origin for a short-lived reviewer token, so your session cookie
|
|
49
|
+
stays first-party. `createTokenHandler` reads the key from `FASTBACKR_API_KEY`, decides who the
|
|
50
|
+
reviewer is and answers the SDK. Next.js App Router:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
// app/api/fastbackr/route.ts
|
|
54
|
+
import { createTokenHandler } from '@fastbackr/core/server';
|
|
55
|
+
import { auth } from '@/lib/auth'; // your own auth
|
|
56
|
+
|
|
57
|
+
export const POST = createTokenHandler({
|
|
58
|
+
// Optional: who is signed in. Leave it out and everyone comments as a guest.
|
|
59
|
+
getUser: async () => {
|
|
60
|
+
const session = await auth();
|
|
61
|
+
return session && { id: session.user.id, name: session.user.name, email: session.user.email };
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The handler takes a web `Request` and returns a `Response`, so it is the route as-is in React
|
|
67
|
+
Router, Hono, SvelteKit, Bun, Deno and Workers too. `getUser` gets the request. When it names
|
|
68
|
+
nobody, a visitor who typed a name gets a guest token (id `guest:<random id>`, `verified: false`),
|
|
69
|
+
so a guest can never claim a signed-in user's id; anyone else gets 401 and the SDK asks for a name.
|
|
70
|
+
|
|
71
|
+
### 3. Wrap your app
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
// app/layout.tsx
|
|
75
|
+
import { FastbackrProvider } from '@fastbackr/react';
|
|
76
|
+
|
|
77
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
78
|
+
return (
|
|
79
|
+
<html lang="en">
|
|
80
|
+
<body>
|
|
81
|
+
<FastbackrProvider>{children}</FastbackrProvider>
|
|
82
|
+
</body>
|
|
83
|
+
</html>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The provider is a client component that Server Components can render. Only one SDK runs per page,
|
|
89
|
+
so React Strict Mode and a second provider are fine.
|
|
90
|
+
|
|
91
|
+
### 4. Allow the API in your Content-Security-Policy
|
|
92
|
+
|
|
93
|
+
If your site sends a CSP, add the API to `connect-src`:
|
|
94
|
+
|
|
95
|
+
```text
|
|
96
|
+
Content-Security-Policy: connect-src 'self' https://api.fastbackr.com
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
When the policy blocks the API, the SDK logs one console error naming the directive to add.
|
|
100
|
+
|
|
101
|
+
## Using it
|
|
102
|
+
|
|
103
|
+
- Click `+` (or press `c` once the bar is open). The cursor becomes a crosshair: click an element, or
|
|
104
|
+
drag a box around an area, then write in the box that opens below it. On touch screens, tap an
|
|
105
|
+
element.
|
|
106
|
+
- The bar stays for the rest of the tab's session. Its chevron (Minimize) goes back to the `+`
|
|
107
|
+
button. Its ✕ (Close) removes the `+` button too, in this browser; press `f` three times
|
|
108
|
+
(outside a text field) to bring it back. `useFastbackr().show()` does the same from code.
|
|
109
|
+
- `Feedback` opens the drawer with every thread on the site, filtered by status and page.
|
|
110
|
+
- A box is stored as a fraction of the element it sits on, so it follows that element at other
|
|
111
|
+
screen widths. When the element's shape changes a lot (columns stacked on a phone), the whole
|
|
112
|
+
element is outlined and the thread names the width the comment was left at.
|
|
113
|
+
|
|
114
|
+
## Options
|
|
115
|
+
|
|
116
|
+
`<FastbackrProvider>` props:
|
|
117
|
+
|
|
118
|
+
| Prop | Type | Default |
|
|
119
|
+
| ---------------- | ------------------------------------ | --------------------------- |
|
|
120
|
+
| `tokenUrl` | `string` | `/api/fastbackr` |
|
|
121
|
+
| `getToken` | `(guest?) => Promise<Token \| null>` | asks `tokenUrl` |
|
|
122
|
+
| `endpoint` | `string` | `https://api.fastbackr.com` |
|
|
123
|
+
| `signIn` | `() => void \| Promise<void>` | none: no "Sign in" button |
|
|
124
|
+
| `queryKeys` | `readonly string[]` | `[]` |
|
|
125
|
+
| `hashRoutes` | `boolean` | `false` |
|
|
126
|
+
| `getPageContext` | `() => { key, path, title }` | built from the URL |
|
|
127
|
+
|
|
128
|
+
- `getToken` replaces the request to `tokenUrl`, for a token route of your own. With no arguments
|
|
129
|
+
it asks "who is signed in?". With `guest` (`{ id, name }`) a guest typed their name; `guest.id` is
|
|
130
|
+
random, generated once and kept in `localStorage`. Resolve `{ token, expiresAt, user }`, or `null`
|
|
131
|
+
for "not signed in". A rejection's message is shown.
|
|
132
|
+
- The SDK refreshes the token a minute before it expires and after any 401.
|
|
133
|
+
- `useFastbackr()`, inside the provider, returns `show()` and `hide()` for your own buttons. `show()`
|
|
134
|
+
brings back a closed `+` button and sends a rainbow ring around it (or around the open bar) for 2s.
|
|
135
|
+
`hide()` is the same as Close.
|
|
136
|
+
- `hashRoutes: true` makes `#records/12` a distinct page. Credential-looking query keys (`token`,
|
|
137
|
+
`secret` and similar) never enter a page key, even when listed.
|
|
138
|
+
|
|
139
|
+
## Guests
|
|
140
|
+
|
|
141
|
+
Without a signed-in session the bar asks for a name, or "Anonymously" (the name `Anonymous`), and,
|
|
142
|
+
when you passed `signIn`, shows a "Sign in" button. A guest's name carries a "guest" tag in threads and the drawer list; in the bar, a guest clicks their
|
|
143
|
+
name to change it.
|
|
144
|
+
|
|
145
|
+
What a guest may do is a per-project setting on the server:
|
|
146
|
+
|
|
147
|
+
| Guest access | Effect |
|
|
148
|
+
| ------------ | ------------------------------------------------------------------- |
|
|
149
|
+
| `off` | `/v1/tokens` refuses `verified: false` (403 `guest_access_off`) |
|
|
150
|
+
| `write-only` | A guest sees, replies to and resolves only the threads they created |
|
|
151
|
+
| `read-write` | A guest is treated like a signed-in reviewer |
|
|
152
|
+
|
|
153
|
+
Use `write-only` when guests are outsiders (customers, prospects) who must not read your team's
|
|
154
|
+
comments.
|
|
155
|
+
|
|
156
|
+
## Screenshots
|
|
157
|
+
|
|
158
|
+
Turn on Screenshots in the project's settings in the dashboard (off by default) and each new thread
|
|
159
|
+
gets an image of the reviewer's viewport, taken on Save, with the commented element outlined. It
|
|
160
|
+
shows above the first message. The reviewer can uncheck "Take screenshot" in the comment box to skip
|
|
161
|
+
it for that comment. Fastbackr's own UI is left out, and `data-fastbackr-private`
|
|
162
|
+
elements and form fields (text inputs, textareas, selects, editable regions) become black boxes.
|
|
163
|
+
Everything else on screen is captured, customer data included: mark private areas with
|
|
164
|
+
`data-fastbackr-private`. The panel shows the image from a `blob:` URL, so a CSP needs
|
|
165
|
+
`img-src blob:`.
|
|
166
|
+
|
|
167
|
+
## Marking up your page (optional)
|
|
168
|
+
|
|
169
|
+
Comments find their element again from its tag, label, text and position. Ids that look generated
|
|
170
|
+
(`:r1:`, `radix-12`, hashed names) are ignored. Explicit ids are sturdier:
|
|
171
|
+
|
|
172
|
+
| Attribute | Effect |
|
|
173
|
+
| -------------------------------- | ------------------------------------------------------------- |
|
|
174
|
+
| `data-fastbackr-id="hero-cta"` | Stable identity; a comment attaches to exactly this element |
|
|
175
|
+
| `data-fastbackr-component="Nav"` | Labels comments left on this element |
|
|
176
|
+
| `data-fastbackr-private` | Never in a comment's excerpt; a black box in screenshots |
|
|
177
|
+
|
|
178
|
+
Form field values are never captured, and screenshots black the fields out.
|
|
179
|
+
|
|
180
|
+
## A token route in another language
|
|
181
|
+
|
|
182
|
+
`createTokenHandler` is the easy path. Any server can answer the SDK instead (Express, Rails,
|
|
183
|
+
Django, Go): `POST /api/fastbackr` on your origin receives `{}` ("who is signed in?") or
|
|
184
|
+
`{ "guest": { "id", "name" } }`. Answer:
|
|
185
|
+
|
|
186
|
+
- 200 with the body of `POST https://api.fastbackr.com/v1/tokens`, which you call with
|
|
187
|
+
`Authorization: Bearer <FASTBACKR_API_KEY>` and `{ "user": { "id", "name", "email"?, "verified" } }`.
|
|
188
|
+
Vouch for a guest as `{ "id": "guest:<guest.id>", "name": <guest.name>, "verified": false }`.
|
|
189
|
+
- 401 when nobody may comment yet: the SDK shows its name form.
|
|
190
|
+
- 403 `{ "error": { "code": "guest_access_off", ... } }` passed on from the API.
|
|
191
|
+
|
|
192
|
+
In Node, `createReviewerToken({ apiKey, user })` makes that API call for you.
|
|
193
|
+
|
|
194
|
+
## Errors on the server
|
|
195
|
+
|
|
196
|
+
`createTokenHandler` answers errors itself (500 when `FASTBACKR_API_KEY` is missing, 502 when the
|
|
197
|
+
API cannot be reached) and logs the reason. `createReviewerToken` throws `FastbackrError` with
|
|
198
|
+
`status` and `code`:
|
|
199
|
+
|
|
200
|
+
- `status: 0`, `invalid_request`: bad input; nothing was sent.
|
|
201
|
+
- `status: 0`, `network_error`: the API could not be reached.
|
|
202
|
+
- otherwise the API's own status and code, for example `401 unauthorized` (bad or revoked key),
|
|
203
|
+
`403 guest_access_off`.
|
|
204
|
+
|
|
205
|
+
Error messages never include the API key.
|
|
206
|
+
|
|
207
|
+
## How it is built
|
|
208
|
+
|
|
209
|
+
`@fastbackr/core` holds the logic: tokens, the API client, finding an element again, select mode.
|
|
210
|
+
This package draws the UI with the components and theme of Fastbackr's design system (shadcn on
|
|
211
|
+
Base UI, Tailwind CSS v4). The build compiles that stylesheet and the SDK injects it into its
|
|
212
|
+
Shadow root; your page never loads it. Browsers ignore `@property` inside a Shadow root, so the build
|
|
213
|
+
turns on Tailwind's fallback values for its `--tw-*` variables instead. The UI uses the system font.
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
Free to install and use with the Fastbackr service. Modifying it is not allowed. See `LICENSE`.
|