|
1 | 1 | --- |
2 | 2 | title: "Troubleshooting JavaScript / Node.js projects" |
3 | | -excerpt: "Fix a disclosure widget that never appears, a published build that serves an old integration, a broken config file, or an outdated @patchstack/connect — including prompts to paste into an AI site builder." |
| 3 | +excerpt: "Fix a disclosure widget that never appears or appears twice, a published build that serves an old integration, a broken config file, or an outdated @patchstack/connect — including prompts to paste into an AI site builder." |
4 | 4 | hidden: false |
5 | 5 | createdAt: "Mon Sep 07 2026 00:00:00 GMT+0000 (Coordinated Universal Time)" |
6 | | -updatedAt: "Mon Sep 07 2026 00:00:00 GMT+0000 (Coordinated Universal Time)" |
| 6 | +updatedAt: "Wed Sep 09 2026 00:00:00 GMT+0000 (Coordinated Universal Time)" |
7 | 7 | sidebar: |
8 | 8 | order: 7.4 |
9 | 9 | label: "Troubleshooting JS / Node.js" |
10 | 10 | --- |
11 | 11 |
|
12 | 12 | import { Steps, Aside } from '@astrojs/starlight/components'; |
13 | 13 |
|
14 | | -This page covers the problems that come up after connecting a JavaScript or Node.js project with [`@patchstack/connect`](/getting-started/installing-patchstack/installing-on-javascript-node-projects/): a disclosure widget that never appears, a published site still serving an old integration, a build that broke after a config change, and a connector stuck on an old version. |
| 14 | +This page covers the problems that come up after connecting a JavaScript or Node.js project with [`@patchstack/connect`](/getting-started/installing-patchstack/installing-on-javascript-node-projects/): a disclosure widget that never appears, a widget that appears twice, a published site still serving an old integration, a build that broke after a config change, and a connector stuck on an old version. |
15 | 15 |
|
16 | 16 | Every section ends with a **prompt you can paste into your site builder's AI chat**. The prompts are deliberately explicit about proving the result, because builder assistants otherwise tend to report the version they remember, or stop after editing one file. |
17 | 17 |
|
@@ -205,6 +205,55 @@ Please diagnose and fix the Patchstack build after the config-file update. |
205 | 205 | Please complete and verify the fix. Thank you. |
206 | 206 | ``` |
207 | 207 |
|
| 208 | +## I see two Patchstack widgets |
| 209 | + |
| 210 | +Two shield buttons stacked in the corner, sometimes one opening the owner log-in and the other the report form, mean the widget script ran twice on that page. They often sit on exactly the same pixel, so the second one only shows when a panel opens or the layout shifts. |
| 211 | + |
| 212 | +The widget keeps **one floating launcher per page** on its own: |
| 213 | + |
| 214 | +- A second copy loaded by the **same document** is ignored, with a `[PatchstackWidget]` warning in the browser console. |
| 215 | +- A copy inside a page of **your own site that the shell shows in an `<iframe>`** stands down as well, with a console message. The connector's `mark-build` step stamps every built HTML file, so an embedded static page carries the tag too; that copy is harmless and you can leave it. |
| 216 | + |
| 217 | +What still needs your attention is a second tag that you, or the builder's AI, added by hand. It usually lives in a component, a layout, or a runtime `useEffect` that appends the script. Keep exactly one tag, in the root shell. |
| 218 | + |
| 219 | +<Aside type="note" title="React StrictMode"> |
| 220 | +In development React runs effects twice. A snippet that appends the widget `<script>` in `useEffect` must call `destroy()` on the widget in its cleanup, or the first copy survives. The React snippet in the [widget integration guide](https://cdn.patchstack.com/llm.html) does this. |
| 221 | +</Aside> |
| 222 | + |
| 223 | +Count the copies on the published page from the browser console: |
| 224 | + |
| 225 | +```js |
| 226 | +document.querySelectorAll('script[src*="patchstack-widget"]').length // want 1 |
| 227 | +document.querySelectorAll('#patchstack-widget-host').length // want 1 |
| 228 | +``` |
| 229 | + |
| 230 | +If the page embeds another page of your site in an `<iframe>`, run the same two lines inside that frame (pick it in the console's context dropdown). One host in the shell and none in the frame is the expected result. |
| 231 | + |
| 232 | +### Prompt: two widgets on the page |
| 233 | + |
| 234 | +```text |
| 235 | +Please make sure the Patchstack widget is loaded exactly once on this site. |
| 236 | +
|
| 237 | +1. Search the entire project - source files, layouts, components, and static |
| 238 | + HTML under public/ - for "patchstack-widget.js" and list every place that |
| 239 | + loads it. |
| 240 | +2. Keep exactly one <script> tag: the connector-managed one in the root shell |
| 241 | + (index.html, or the root layout for Next.js / TanStack Start / Remix). It |
| 242 | + must carry data-site-uuid with the value from the committed |
| 243 | + .patchstackrc.json. |
| 244 | +3. Remove every other copy that was added by hand: in components, in layouts, |
| 245 | + and in code that appends the script at runtime. If a component must load it |
| 246 | + at runtime, call destroy() on the returned widget in the effect cleanup. |
| 247 | +4. Leave the tag that @patchstack/connect writes into static HTML pages during |
| 248 | + mark-build; the widget ignores it when that page is shown inside the shell. |
| 249 | +5. Run the complete production build, publish it, open the live site, and |
| 250 | + confirm a single launcher is visible and the browser console shows no |
| 251 | + "[PatchstackWidget] A floating widget is already on this page" warning. |
| 252 | +
|
| 253 | +Please make the changes and show me the list from step 1 and the console |
| 254 | +check from step 5. Thank you. |
| 255 | +``` |
| 256 | + |
208 | 257 | ## Still stuck? |
209 | 258 |
|
210 | 259 | - `npx @patchstack/connect guide` prints a project-aware checklist of what is present and what is missing. |
|
0 commit comments