@sightspool/sdk 0.1.0 → 0.1.1

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.
Files changed (2) hide show
  1. package/README.md +139 -1
  2. package/package.json +9 -7
package/README.md CHANGED
@@ -14,6 +14,10 @@ them).
14
14
  > **not** act on your surface (surveys/nudges/experiments are Wave 0005, and every one
15
15
  > is human-gated). Trigger sensitivity and intent inference calibrate with live traffic.
16
16
 
17
+ **Docs:** [full reference + CSP & framework guides](https://sightspool.github.io/sdk/) ·
18
+ [llms.txt](https://sightspool.github.io/sdk/llms.txt) (the machine-readable install/CSP/config
19
+ doc for agents) · [npm](https://www.npmjs.com/package/@sightspool/sdk)
20
+
17
21
  ---
18
22
 
19
23
  ## Install — two lines
@@ -83,7 +87,7 @@ The script tag also reads these optional attributes (the no-build equivalent of
83
87
 
84
88
  | option | type | default | purpose |
85
89
  |---|---|---|---|
86
- | `key` | `string` | — | **required.** Your publishable key (`pk_live_…`), from the Connections → In-product SDK card. Publishable — safe to ship in client JS. |
90
+ | `key` | `string` | — | **required.** Your publishable key (`pk_test_…` / `pk_live_…`), from the Connections → In-product SDK card. Publishable — safe to ship in client JS. See [Keys & environments](#keys--environments). |
87
91
  | `endpoint` | `string` | the bundle's origin (script tag) / `https://app.sightspool.com` (npm) | Ingest base URL. The `<script>` install auto-resolves it to wherever `sdk.global.js` was served from (your app), so the key alone is enough; override for a CDN-hosted bundle or dev. |
88
92
  | `boundaryAsk` | `boolean` | `true` | Show the one-tap "did you do what you came to do?" ask at session boundaries. |
89
93
  | `consent` | `boolean` | `true` | Start capturing immediately. Set `false` to stay paused until you call `Sightspool.consent(true)` (or `start()`) after obtaining consent. |
@@ -107,6 +111,140 @@ un-allowlisted origin.
107
111
 
108
112
  ---
109
113
 
114
+ ## Keys & environments
115
+
116
+ Your key is **publishable** — safe to ship in client JS (the Stripe `pk_` model). Two
117
+ prefixes, one per environment:
118
+
119
+ | prefix | use it for |
120
+ |---|---|
121
+ | `pk_test_…` | development / staging / preview deploys |
122
+ | `pk_live_…` | production |
123
+
124
+ The SDK treats both prefixes **identically** — there's no client-side special-casing; the
125
+ prefix tells *Sightspool* (at ingest) which environment a Signal belongs to, so test traffic
126
+ never mixes into production analytics. Issue both from **Connections → In-product SDK**.
127
+
128
+ > The SDK also **no-ops on localhost** by default (see `captureOnLocalhost`), so even a
129
+ > `pk_live_` key won't capture from `npm run dev`. Test keys are for *deployed* non-prod
130
+ > environments (staging, previews).
131
+
132
+ Keep the key in an environment variable rather than hardcoding it, and pick test vs live by
133
+ environment. The key is exposed to the browser, so use your framework's **client** env-var
134
+ prefix (`NEXT_PUBLIC_`, `VITE_`, `PUBLIC_`, …) — it's publishable, so that's expected:
135
+
136
+ ```js
137
+ Sightspool.init({ key: process.env.NEXT_PUBLIC_SIGHTSPOOL_KEY })
138
+ ```
139
+
140
+ ```bash
141
+ # .env.development / preview
142
+ NEXT_PUBLIC_SIGHTSPOOL_KEY=pk_test_…
143
+ # .env.production
144
+ NEXT_PUBLIC_SIGHTSPOOL_KEY=pk_live_…
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Framework integration
150
+
151
+ ### Next.js (App Router) — `next/script`
152
+
153
+ The idiomatic install is `next/script`, not a raw `<script>`. Add it once in your root
154
+ layout — the tag auto-`init`s from `data-sightspool-key`:
155
+
156
+ ```tsx
157
+ // app/layout.tsx
158
+ import Script from 'next/script'
159
+
160
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
161
+ return (
162
+ <html lang="en">
163
+ <body>
164
+ {children}
165
+ <Script
166
+ src="https://app.sightspool.com/sdk.global.js"
167
+ data-sightspool-key={process.env.NEXT_PUBLIC_SIGHTSPOOL_KEY}
168
+ strategy="afterInteractive"
169
+ />
170
+ </body>
171
+ </html>
172
+ )
173
+ }
174
+ ```
175
+
176
+ Then `identify` the user once known (e.g. a client component after auth):
177
+
178
+ ```tsx
179
+ 'use client'
180
+ useEffect(() => {
181
+ window.Sightspool?.identify(user.id, { account: user.account, plan: user.plan })
182
+ }, [user])
183
+ ```
184
+
185
+ > `data-sightspool-key` is inlined at build time, so `NEXT_PUBLIC_SIGHTSPOOL_KEY` must be set
186
+ > in the environment Next builds in. `strategy="afterInteractive"` keeps it off the critical
187
+ > path.
188
+
189
+ ### React (bundler install)
190
+
191
+ Install the package and call `init` once at app start (a top-level effect or your entry
192
+ module):
193
+
194
+ ```tsx
195
+ import { useEffect } from 'react'
196
+ import Sightspool from '@sightspool/sdk'
197
+
198
+ export function SightspoolBoot({ userId, account, plan }) {
199
+ useEffect(() => {
200
+ Sightspool.init({ key: import.meta.env.VITE_SIGHTSPOOL_KEY })
201
+ }, [])
202
+ useEffect(() => {
203
+ if (userId) Sightspool.identify(userId, { account, plan })
204
+ }, [userId, account, plan])
205
+ return null
206
+ }
207
+ ```
208
+
209
+ > A first-class **`@sightspool/react`** wrapper (a `<SightspoolProvider>` + a `useSightspool`
210
+ > hook over `init`/`identify`) is planned —
211
+ > [issue #3](https://github.com/sightspool/sdk/issues/3).
212
+
213
+ ---
214
+
215
+ ## Content-Security-Policy
216
+
217
+ If your app sets a CSP, allow the SDK's two footprints — the **script load** and the
218
+ **ingest beacon**. With the standard install they're the *same host* (the bundle is served
219
+ from the app it ingests to), so it's one host in two directives:
220
+
221
+ **Script-tag install**
222
+
223
+ ```
224
+ script-src https://app.sightspool.com;
225
+ connect-src https://app.sightspool.com;
226
+ ```
227
+
228
+ **npm / bundler install** — the SDK is bundled into your own first-party JS, so no
229
+ `script-src` host is needed; only the ingest origin:
230
+
231
+ ```
232
+ connect-src https://app.sightspool.com;
233
+ ```
234
+
235
+ If you pass a custom `endpoint`, use *that* origin in `connect-src`. The beacon goes via
236
+ `navigator.sendBeacon` with a `fetch(keepalive)` fallback — both governed by `connect-src`.
237
+
238
+ - **`strict-dynamic` / nonce.** Under `script-src 'strict-dynamic'`, host allowlists are
239
+ ignored for scripts — give the `<script>` tag your per-request nonce (`nonce={nonce}` in
240
+ Next) so it's trusted. `connect-src` still needs the ingest host.
241
+ - **Prompt styles.** The one-tap prompt renders into a **shadow root** and injects its own
242
+ `<style>`. Under a strict `style-src` without `'unsafe-inline'`, those styles may not apply
243
+ — the prompt stays **fully functional but unstyled** (the SDK never throws into your page).
244
+ Add `'unsafe-inline'` to `style-src` if you want it styled.
245
+
246
+ ---
247
+
110
248
  ## What it captures
111
249
 
112
250
  - **Passively, no wiring** — route/screen sequence, clicks, **dead-clicks** and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sightspool/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Sightspool in-product capture SDK — captures user intent, effort, and account at the moment of friction.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -43,17 +43,19 @@
43
43
  "engines": {
44
44
  "node": ">=18"
45
45
  },
46
+ "packageManager": "pnpm@9.15.0",
46
47
  "publishConfig": {
47
48
  "access": "public"
48
49
  },
50
+ "scripts": {
51
+ "build": "tsup",
52
+ "type-check": "tsc --noEmit",
53
+ "test": "node --test __tests__/*.test.ts",
54
+ "prepublishOnly": "pnpm run build"
55
+ },
49
56
  "devDependencies": {
50
57
  "@types/node": "^24.10.4",
51
58
  "tsup": "^8.5.0",
52
59
  "typescript": "^5.9.3"
53
- },
54
- "scripts": {
55
- "build": "tsup",
56
- "type-check": "tsc --noEmit",
57
- "test": "node --test __tests__/*.test.ts"
58
60
  }
59
- }
61
+ }