Skip to content

fix: bug-report endpoint /api collision (DEV-2114) + BugReportButton hydration (DEV-2017)#2

Merged
pascal-klesse merged 2 commits into
mainfrom
fix/endpoint-collision-and-hydration
Jun 1, 2026
Merged

fix: bug-report endpoint /api collision (DEV-2114) + BugReportButton hydration (DEV-2017)#2
pascal-klesse merged 2 commits into
mainfrom
fix/endpoint-collision-and-hydration

Conversation

@pascal-klesse
Copy link
Copy Markdown
Member

Fixes two bugs that affected built/deployed consumer apps. Releases are automated via semantic-release, so the package version is intentionally not hand-bumped — the merge of these fix: commits will trigger the appropriate patch release.

Fix 1 — DEV-2114: bug-report endpoint 404 on built/deployed apps

Root cause. The module registered its server handler at /api/bug-report and the useBugReport composable did $fetch('/api/bug-report'). Consuming Nuxt apps very commonly proxy all /api/** requests to a separate backend via Nitro routeRules. That catch-all swallows /api/bug-report, forwards it to the backend (→ 404), and bug.lt's own handler never runs. Reproduced live: a built app with an /api/** proxy returned 404 for POST /api/bug-report.

Fix. Move the endpoint off /api/ and make it configurable:

  • New module option endpoint (string), default /_bug-lt/report (Nuxt-internal _-prefix style, like @nuxt/icon's /_nuxt_icon), which won't be caught by /api/** proxies.
  • Exposed to the client via runtimeConfig.public.bugLt.endpoint = options.endpoint.
  • Server: addServerHandler({ route: options.endpoint, ... }) (was hardcoded /api/bug-report).
  • Client (useBugReport): const endpoint = useRuntimeConfig().public.bugLt?.endpoint || '/_bug-lt/report' (was hardcoded /api/bug-report) — server and client now always agree.
  • Types updated in src/runtime.d.ts (PublicRuntimeConfig.bugLt.endpoint) and BugReportConfig.
  • README documents the new endpoint option and why (consumers proxying /api/**).

The server handler file (bug-report.post.ts) is unchanged — the route is declared explicitly in addServerHandler, so only the registered route + client URL needed to change to match.

Fix 2 — DEV-2017: BugReportButton hydration mismatch + "Failed to resolve component: RouterLink"

Root cause. BugReportButton.vue rendered a floating Nuxt UI UButton inside <Teleport to="body"> during SSR. UButton resolves to ULink → NuxtLink with to=undefined, which renders an <a> on SSR but mismatches on client hydration → every page logged [Vue warn]: Failed to resolve component: RouterLink, Hydration node mismatch, and Hydration completed but contains mismatches.

Fix. The floating button is a pure client-side UI overlay, so its <Teleport>/<UButton> block is now wrapped in <ClientOnly> — it never SSR-renders, eliminating the mismatch. Position/color/screenshot/openModal behavior is unchanged. The modal (BugReportModal) needed no change: it is only ever mounted client-side via useOverlay().create() from a click handler (and the auto-mounted button is mounted via a separate createApp() in a client-only app:mounted hook), so it is never part of the SSR tree.

Build / lint / test

  • npm run prepack (build via @nuxt/module-builder): succeeds.
  • npm run lint (eslint): clean, 0 errors / 0 warnings.
  • npm test (vitest): 8 files, 51/51 tests pass. Updated test/module.test.ts to assert the new default endpoint option and the addServerHandler route /_bug-lt/report (instead of the old /api/bug-report).

🤖 Generated with Claude Code

pascal-klesse and others added 2 commits June 1, 2026 21:35
… proxy collision (DEV-2114)

Consuming Nuxt apps very commonly proxy all `/api/**` requests to a separate
backend via Nitro `routeRules`. That catch-all swallowed `/api/bug-report` and
forwarded it to the backend (404), so bug.lt's own server handler never ran on
built/deployed apps.

Add a configurable `endpoint` module option defaulting to `/_bug-lt/report`
(Nuxt-internal `_`-prefix style, outside `/api/`). Expose it via
`runtimeConfig.public.bugLt.endpoint`; register the server handler with
`options.endpoint`; and read the same value in `useBugReport` so server and
client always agree. Document the option and rationale in the README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…match + RouterLink warning (DEV-2017)

The floating button rendered a Nuxt UI `UButton` (which resolves to a NuxtLink
with `to=undefined`) inside `<Teleport to="body">` during SSR. On the client
this mismatched, logging `Failed to resolve component: RouterLink` plus
hydration-node-mismatch warnings on every page.

The button is a pure client-side UI overlay, so wrap the `<Teleport>`/`<UButton>`
block in `<ClientOnly>` to skip SSR entirely. Behavior (position, color,
screenshot capture, openModal) is unchanged. The modal needs no change — it is
only ever mounted client-side via `useOverlay().create()` from a click, never in
the SSR tree.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@pascal-klesse pascal-klesse merged commit 14b8d6b into main Jun 1, 2026
@pascal-klesse pascal-klesse deleted the fix/endpoint-collision-and-hydration branch June 1, 2026 19:39
github-actions Bot pushed a commit that referenced this pull request Jun 1, 2026
## [1.6.7](v1.6.6...v1.6.7) (2026-06-01)

### 🐛 Bug Fixes

* bug-report endpoint /api collision (DEV-2114) + BugReportButton hydration (DEV-2017) ([#2](#2)) ([14b8d6b](14b8d6b))
@pascal-klesse
Copy link
Copy Markdown
Member Author

🎉 This PR is included in version 1.6.7 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant