From 3d0046b5ff1e06a8e62c057ff6e5fc4897556a9d Mon Sep 17 00:00:00 2001 From: Nathan Rodd Date: Thu, 30 Jul 2026 12:10:11 -0400 Subject: [PATCH 1/3] Repaint README shields on the pink ramp Co-Authored-By: Claude Fable 5 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 60b735d..bec3535 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ LOCKUP - HORZ - BY FS - LIGHT - COLOR (3) -![NPM Downloads](https://img.shields.io/npm/dm/%40subtextdev%2Fsubtext-wizard?style=flat-square&labelColor=240046&color=7b2cbf) -![NPM Last Updated](https://img.shields.io/npm/last-update/%40subtextdev%2Fsubtext-wizard?style=flat-square&labelColor=3c096c&color=9d4edd) -![NPM Version](https://img.shields.io/npm/v/%40subtextdev%2Fsubtext-wizard?style=flat-square&labelColor=5a189a&color=e0aaff) +![NPM Downloads](https://img.shields.io/npm/dm/%40subtextdev%2Fsubtext-wizard?style=flat-square&labelColor=46001f&color=b81b56) +![NPM Last Updated](https://img.shields.io/npm/last-update/%40subtextdev%2Fsubtext-wizard?style=flat-square&labelColor=6b0f36&color=f5447b) +![NPM Version](https://img.shields.io/npm/v/%40subtextdev%2Fsubtext-wizard?style=flat-square&labelColor=9a1847&color=ffd6e4) **Session replay, built for agents.** Subtext is agentic session review: it captures production sessions of your app and connects them to your coding agent — Claude Code, Cursor, Codex, Devin, your own harness — so it can review what real users did, reproduce reported bugs, verify its own UI changes, and manage capture privacy rules, all without leaving the terminal. From ea634292aed9c558d2e92bcaa648a8167f89f447 Mon Sep 17 00:00:00 2001 From: Nathan Rodd Date: Thu, 30 Jul 2026 12:32:39 -0400 Subject: [PATCH 2/3] Route Hydrogen installs through the @subtextdev/hydrogen wrapper Hydrogen apps get the wrapper package instead of a pasted inline snippet: (snippet + CSP nonce), withSubtextCSP in entry.server, (commerce events + consent-gated capture + onSessionUrl linkage), and useSubtextIdentity. Detection runs before the Remix/React Router/Vite checks so Hydrogen's own dependencies can't shadow the match, and the pre-check treats @subtextdev/hydrogen as already installed. Co-Authored-By: Claude Opus 4.8 (1M context) --- .changeset/hydrogen-wrapper-prompt.md | 5 +++++ templates/install-prompt.md | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 .changeset/hydrogen-wrapper-prompt.md diff --git a/.changeset/hydrogen-wrapper-prompt.md b/.changeset/hydrogen-wrapper-prompt.md new file mode 100644 index 0000000..963f515 --- /dev/null +++ b/.changeset/hydrogen-wrapper-prompt.md @@ -0,0 +1,5 @@ +--- +'@subtextdev/subtext-wizard': patch +--- + +Teach the install prompt the Shopify Hydrogen route: detect `@shopify/hydrogen` (before its Remix/React Router/Vite dependencies can shadow the match) and install via the `@subtextdev/hydrogen` wrapper package — snippet + CSP nonce via ``, `withSubtextCSP` in `entry.server`, commerce events + consent-gated capture via ``, identity via `useSubtextIdentity`, and analytics linkage via `onSessionUrl` — instead of pasting the raw inline snippet. `@subtextdev/hydrogen` also counts as "already installed" in the pre-check. diff --git a/templates/install-prompt.md b/templates/install-prompt.md index 0973de8..5cfee3c 100644 --- a/templates/install-prompt.md +++ b/templates/install-prompt.md @@ -20,7 +20,7 @@ Determine whether the capture snippet is *actually* installed. The snippet is th Run these checks in order. Stop at the first positive match. -1. Package dependencies (highest confidence) — Read `package.json`. Look for `@fullstory/browser`, `@fullstory/react-native`, or `@fullstory/snippet` in `dependencies` or `devDependencies`. +1. Package dependencies (highest confidence) — Read `package.json`. Look for `@fullstory/browser`, `@fullstory/react-native`, `@fullstory/snippet`, or `@subtextdev/hydrogen` in `dependencies` or `devDependencies`. 2. Script tag in HTML entry point — Search ONLY the HTML entry point (`index.html`, `app/layout.tsx`, `pages/_document.tsx`, or framework equivalent) for the literal strings `fullstory.com/s/fs.js` or `_fs_script`. Do not search other files. 3. SDK initialization call — Grep for `init\(\s*\{\s*orgId`, `window\['_fs_org'\]\s*=`, or `window\._fs_org\s*=` in `.ts`, `.tsx`, `.js`, `.jsx` files (exclude `node_modules`, test files, and `*.d.ts`). The `init()` call comes from `@fullstory/browser` v2: `import { init } from '@fullstory/browser'`. @@ -45,6 +45,7 @@ Before making any changes, do a read-only pass to gather what the install will d Read `package.json` and project structure to detect the framework: +- `@shopify/hydrogen` in dependencies → Shopify Hydrogen → wrapper-package install, see "Shopify Hydrogen" under Framework patterns. Check this FIRST: Hydrogen apps also contain Remix/React Router and Vite dependencies, which must not shadow this match. - `next` in dependencies → Next.js (App Router) → `app/layout.tsx` - `next` + `pages/_document.tsx` exists → Next.js (Pages Router) → `pages/_document.tsx` - `@remix-run/*` in dependencies → Remix → `app/root.tsx` @@ -99,6 +100,15 @@ This is the snippet to install. It is specific to this organization — install ### Framework patterns +- Shopify Hydrogen — Do NOT paste the raw snippet. Install the wrapper package instead; it handles the snippet, Hydrogen's nonce-based CSP, and consent gating through Shopify's Customer Privacy API: + 1. `npm install @subtextdev/hydrogen` (match the project's package manager: pnpm/yarn/bun if a corresponding lockfile exists). + 2. Derive the configuration from the snippet in Step 4 above — do not invent values: `orgId` is the `window['_fs_org']` value; if `window['_fs_host']` is `eu1.fullstory.com` pass `region="eu"`; if the host values are anything other than `fullstory.com`/`eu1.fullstory.com` standards, pass them through as `host`/`script` props. + 3. `app/root.tsx` — add `` (plus `region`/`host`/`script` if derived above) inside `` of the root layout. The component attaches Hydrogen's CSP nonce automatically via `useNonce()`. + 4. `app/entry.server.tsx` — wrap the existing directives object: `createContentSecurityPolicy(withSubtextCSP({...existing directives}))`, importing `withSubtextCSP` from `@subtextdev/hydrogen` (pass `{region: 'eu'}` as its second argument for EU orgs). This replaces the manual CSP directive edits from Step 2 — do not also add the directives by hand. + 5. `app/root.tsx` — add `` anywhere inside ``. It forwards Hydrogen's commerce events (`product_viewed`, `cart_updated`, search, collection, add/remove-to-cart) into capture and starts/stops capture as Customer Privacy consent changes. + 6. For Step 5 (identity), use the package's `useSubtextIdentity(customer && {uid: customer.id, displayName, email})` hook where the authenticated customer is available on the client (typically the account route), instead of a raw `FS('setIdentity')` call. + 7. For Step 6 (analytics linkage), pass `onSessionUrl` to `` instead of calling `FS('getSession')` directly — it fires with the session URL every time capture starts, which with consent gating can be well after page load: ` { /* attach subtext_url to each detected tool here */ }} />`. + 8. Capture is consent-gated by default, matching how Shopify gates its own analytics. Tell the user: Shopify's privacy banner does not load on default `*.oxygen` preview URLs, so capture will not start there — verify on a real domain. Also note checkout hands off to Shopify-hosted pages, which this integration does not capture. - Next.js (App Router) — Add to `app/layout.tsx` inside ``, or as a `