Skip to content

Backport to upstream - #148

Open
colinmollenhour wants to merge 7 commits into
ijkml:next-majorfrom
colinmollenhour:backport-to-upstream
Open

Backport to upstream#148
colinmollenhour wants to merge 7 commits into
ijkml:next-majorfrom
colinmollenhour:backport-to-upstream

Conversation

@colinmollenhour

Copy link
Copy Markdown

Continuation of #147

colinmollenhour and others added 5 commits April 24, 2026 19:44
The README grouped `proxy: false` and `proxy: 'direct'` under the same
NUXT_PUBLIC_UMAMI_ENDPOINT override, which is wrong: in direct mode the
upstream URL is baked into `routeRules` at build time, and setting
NUXT_PUBLIC_UMAMI_ENDPOINT at server start would overwrite the internal
`/api/savory` path and break the proxy. Split env vars per proxy mode
and add a proxy-modes overview table.

Also call out explicitly that `host` is the Umami server URL (where
analytics are sent to), not the URL of the tracked site.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summarize which items have already been fixed (13/17) with the commit
hash for each, and flag the 4 remaining items (2.2, 2.6, 4.1, 4.7).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Nuxt bug #26535 (page:loading:end firing twice on nested pages) was
fixed by PR #29009, shipped in Nuxt v3.15.2 and v4.0.0. Our peer dep
is >=3.15.4, so all supported versions have the fix.

page:loading:end fires once per navigation after async data and
useHead() have settled, so we no longer need:
  - the 250ms setTimeout workaround for the title lagging page:finish
  - the lastTrackedPath dedup for nested-<NuxtPage> double-fires
  - the useRouter import used for the dedup

Tick 2.2 off the TODO checklist.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Move app.vue, pages/, assets/ into playground/app/ (the v4 default
  srcDir). Files were moved with `git mv` so history follows.
- Bump compatibilityDate from 2024-08-08 to 2026-04-24.
- Add `future: { compatibilityVersion: 4 }` so the playground exercises
  v4 defaults under our >=3.15.4 peer-dep floor as well as under Nuxt
  v4 (where the flag is a no-op).

Verified with `pnpm dev:prepare` (types generated, "Running with
compatibility version 4") and `pnpm dev:build` (full nitro build,
both routes — index and page-[id] — present in the output).

Tick 2.6 off the TODO checklist.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the "Fork: colinmollenhour/nuxt-umami" section, the fork-vs-upstream
changes table, and the AI-assistant prompt; restore the upstream-style
intro (badges, Try it online, npx nuxi module add, docs link). Keep the
new Configure / Proxy modes / Environment variables / Usage sections,
promoted to top-level headings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 27, 2026 15:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Backports fork work into upstream by updating the Nuxt runtime tracking hook behavior and modernizing the playground/docs to align with newer Nuxt compatibility expectations.

Changes:

  • Switch auto pageview tracking from page:finish (with dedupe/debounce) to page:loading:end.
  • Migrate the playground to Nuxt v4-style app/ structure and add simple pages/app shell for manual testing.
  • Refresh README content (badges, quickstart, proxy/env-var behavior) and add a progress checklist to TODO.

Reviewed changes

Copilot reviewed 4 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/runtime/plugin.ts Changes the auto-track hook to page:loading:end and removes dedupe logic.
playground/nuxt.config.ts Updates compatibility date and opts into Nuxt v4 defaults via future.compatibilityVersion.
playground/app/pages/page-[id].vue Adds a dynamic page that sets title via useHead() for tracking/title validation.
playground/app/pages/index.vue Adds an index page with a stable title.
playground/app/assets/reset.css Adds a CSS reset for the playground UI.
playground/app/app.vue Adds a richer playground UI to exercise tracking APIs, directive, and navigation.
TODO.md Adds a progress checklist capturing completed backport items.
README.md Reworks onboarding and documents proxy modes + runtime env var behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md
Comment on lines +113 to +114
# NUXT_PUBLIC_UMAMI_ENDPOINT is ignored/harmful in this mode — do not set it.
# Changing host/customEndpoint requires rebuilding.

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line says NUXT_PUBLIC_UMAMI_ENDPOINT is "ignored" in proxy: 'direct' mode, but runtimeConfig.public.umami.endpoint is still a public runtimeConfig field and Nuxt will override it from NUXT_PUBLIC_UMAMI_ENDPOINT at server start. In proxy: 'direct' that would change the client’s POST target away from /api/savory and likely break tracking. Reword to clarify that it is not ignored and should not be set because it will override the endpoint incorrectly in this mode.

Suggested change
# NUXT_PUBLIC_UMAMI_ENDPOINT is ignored/harmful in this mode — do not set it.
# Changing host/customEndpoint requires rebuilding.
# Do not set NUXT_PUBLIC_UMAMI_ENDPOINT in this mode.
# Nuxt can still override the public endpoint from it at server start, which would change
# the browser POST target away from /api/savory and likely break tracking.
# Changing host/customEndpoint requires rebuilding instead of a runtime override.

Copilot uses AI. Check for mistakes.
Comment thread src/runtime/plugin.ts
Comment on lines +18 to +23
// `page:loading:end` fires once per navigation after async data and
// `useHead()` have settled, so the document title is correct and we
// don't need to dedupe nested-<NuxtPage> double-fires. Requires the
// fix from Nuxt PR #29009 (shipped in v3.15.2 / v4.0.0); our peer
// dep `>=3.15.4` guarantees it.
nuxtApp.hook('page:loading:end', () => {

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new auto-track implementation assumes page:loading:end only fires once per navigation (Nuxt >=3.15.2 per the comment). If users run this module on older Nuxt versions, this hook can still double-fire and you’ve removed the previous dedupe/debounce, reintroducing duplicate umTrackView() calls. Either (a) keep a lightweight dedupe guard here (e.g., track last path) so it’s safe across Nuxt versions, or (b) enforce the minimum supported Nuxt version (and update module compatibility/docs) so older versions can’t install this behavior inadvertently.

Suggested change
// `page:loading:end` fires once per navigation after async data and
// `useHead()` have settled, so the document title is correct and we
// don't need to dedupe nested-<NuxtPage> double-fires. Requires the
// fix from Nuxt PR #29009 (shipped in v3.15.2 / v4.0.0); our peer
// dep `>=3.15.4` guarantees it.
nuxtApp.hook('page:loading:end', () => {
let lastTrackedPath: string | undefined;
// `page:loading:end` should fire once per navigation after async data
// and `useHead()` have settled so the document title is correct, but
// keep a lightweight dedupe guard so older Nuxt versions or unexpected
// double-fires do not emit duplicate page-view events.
nuxtApp.hook('page:loading:end', () => {
const currentPath = typeof window === 'undefined'
? undefined
: `${window.location.pathname}${window.location.search}${window.location.hash}`;
if (currentPath && currentPath === lastTrackedPath)
return;
lastTrackedPath = currentPath;

Copilot uses AI. Check for mistakes.
Comment thread playground/nuxt.config.ts
Comment on lines +5 to +7
// Opt in to Nuxt v4 defaults (notably `srcDir: 'app/'`) while we're
// still on the v3.15+ peer-dep floor. Flag is a no-op under Nuxt v4.
future: { compatibilityVersion: 4 },

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment says the Nuxt v4-defaults opt-in is safe because you’re on a “v3.15+ peer-dep floor”, but playground/package.json currently depends on nuxt: ^3.12.4. That mismatch can break future.compatibilityVersion and also undermines the assumption behind the page:loading:end hook change. Align the playground’s Nuxt dependency with the stated minimum (>=3.15.4) or adjust/remove the claim here.

Copilot uses AI. Check for mistakes.
@colinmollenhour

Copy link
Copy Markdown
Author

@copilot apply changes based on the comments in this thread

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants