Nuxt Scripts v1 is the first stable release.
Nuxt Scripts v1 is the first stable release, pushing the ecosystem forward for better privacy and performance for third-party scripts.
📣 Highlights
🔒 First-Party Mode: Privacy Focused Proxy
Every third-party script request exposes your users data to fingerprinting.
Different providers are more intrusive, for example, the X Pixel accesses 9 browser fingerprinting APIs (including navigator.getBattery()), sets 5 tracking cookies, and makes requests to 3 separate domains. Microsoft Clarity reads 10 fingerprinting APIs across 3 domains.
First-party mode acts as a reverse proxy: scripts are bundled at build time and served from your domain, while runtime requests are securely forwarded through your server. Data sent to third-party servers gets anonymised: IPs (180.233.124.74 -> 180.233.124.0), browser versions (Mozilla/5.0 (compatible; Chrome/120.0)) and more. This is auto-enabled for all scripts that support it.
A side-effect is a performance boost from avoiding extra DNS lookups, fewer cookie banners, and reducing expensive fingerprinting queries. It also makes ad-blockers ineffective since requests appear same-origin.
See the First-Party Mode Guide and PR #577 for details.
🛠️ Rebuilt DevTools
The Nuxt DevTools panel has been rewritten around the v1 privacy and capability model. New views surface the things v1 does differently.
🎉 Partytown Web Worker Support
Load third-party scripts off the main thread using Partytown. Scripts run in a web worker, freeing the main thread for your app. Integrates directly with first-party mode. See PR #576.
Set partytown: true per-script:
export default defineNuxtConfig({
modules: ['@nuxtjs/partytown', '@nuxt/scripts'],
scripts: {
registry: {
plausibleAnalytics: { domain: 'example.com', partytown: true },
fathomAnalytics: { site: 'XXXXX', partytown: true },
umamiAnalytics: { websiteId: 'xxx', partytown: true },
}
}
// Forward array auto-configured per-script!
})
Auto-forwarding supported for: googleAnalytics, plausibleAnalytics, fathomAnalytics, umamiAnalytics, matomoAnalytics, segment, mixpanelAnalytics, bingUet, metaPixel, xPixel, tiktokPixel, snapchatPixel, redditPixel, cloudflareWebAnalytics
⚠️ GA4 has known issues with Partytown. GTM is not compatible (requires DOM access). Consider Plausible, Fathom, or Umami instead.
🐦 SSR Social Embeds
Third-party embed scripts (Twitter widgets, Instagram embeds, Bluesky posts) hurt performance and leak user data. Following the Cloudflare Zaraz approach, Nuxt Scripts now fetches embed data server-side and securely proxies all assets through your domain. See PR #590.
<ScriptXEmbed tweet-id="1754336034228171055">
<template #default="{ userName, text, likesFormatted, photos }">
<!-- Full styling control via scoped slots -->
</template>
</ScriptXEmbed>
<ScriptInstagramEmbed post-url="https://instagram.com/p/ABC123/">
<template #default="{ html, shortcode }">
<div v-html="html" />
</template>
</ScriptInstagramEmbed>
<ScriptBlueskyEmbed post-url="https://bsky.app/profile/...">
<template #default="{ html }">
<div v-html="html" />
</template>
</ScriptBlueskyEmbed>
✋ First-Class Consent Controls
v1 treats consent as a first-class concern with two complementary APIs. See the Consent Guide, PR #544, PR #631, and PR #712.
Every consent-aware registry script now exposes a vendor-native consent object on the returned instance plus a typed defaultConsent option applied before the first tracking call.
const gtm = useScriptGoogleTagManager({
id: 'GTM-XXX',
defaultConsent: { ad_storage: 'denied', analytics_storage: 'denied' },
})
// Later, after the user accepts
gtm.consent.update({ ad_storage: 'granted', analytics_storage: 'granted' })
const ttq = useScriptTikTokPixel({ id: '...', defaultConsent: 'hold' })
ttq.consent.grant() // or .revoke() / .hold()
const meta = useScriptMetaPixel({ id: '...', defaultConsent: 'denied' })
meta.consent.grant()
📦 New Registry Scripts
- PostHog Analytics (#568): Product analytics with feature flags
- Google reCAPTCHA v3 (#567): Invisible bot protection
- TikTok Pixel (#569): Conversion tracking
- Google Sign-In (#573): One-tap authentication
- Rybbit Analytics (#453): Privacy-focused open source analytics
- Databuddy Analytics (#495): Lightweight analytics
- Bing UET (#650): Microsoft Advertising conversion tracking
- Mixpanel Analytics (#648): Product analytics and user tracking
- Vercel Analytics (#605): Vercel Web Analytics integration
- Gravatar (#606): Avatar service with privacy-preserving proxy
Other Changes
🔄 Script Reload API
Scripts now expose a .reload() method for re-executing DOM-scanning scripts after SPA navigation. See commit 77f853b.
const script = useScript('/third-party.js')
await script.reload()
🔐 Automatic SRI Integrity Hashes
Bundled scripts can automatically generate Subresource Integrity hashes. See PR #575.
export default defineNuxtConfig({
scripts: {
assets: {
integrity: 'sha384'
}
}
})
📊 Script Stats Export
New @nuxt/scripts/stats subpath export for auditing script privacy, performance, and security characteristics.
import { getScriptStats } from '@nuxt/scripts/stats'
const stats = await getScriptStats()
// Privacy ratings (A+ to F), performance ratings, CWV estimates,
// cookie analysis, network behavior, tracked data types
🎬 YouTube Player Overhaul
- Isolated player instances (#586): Multiple players work correctly
- Aspect ratio control: New
ratio prop
- Proper cleanup: Players destroyed on unmount
📹 Vimeo Player Enhancements
- Aspect ratio control (#624): New
ratio prop, matching YouTube Player API
🗺️ Google Maps Overhaul
The Google Maps integration received a major DX overhaul for v1, making it feel like a native Vue component library rather than a wrapper around options bags.
Declarative SFC Components (#510): 11 composable components for markers, shapes, overlays, clustering, and more. All use Vue's injection system for parent/child communication and clean up automatically on unmount.
Custom Marker Content (#658): The #content slot on ScriptGoogleMapsMarker replaces the default pin with any HTML or Vue template. Build price tags, status badges, or any custom marker visual declaratively.
<ScriptGoogleMapsMarker :position="{ lat: -34.397, lng: 150.644 }">
<template #content>
<div class="price-tag">$420k</div>
</template>
</ScriptGoogleMapsMarker>
Custom Overlay View (#658): ScriptGoogleMapsOverlayView renders arbitrary Vue content at a map position with full styling control. When nested inside a marker, it auto-inherits position and follows the marker during drag. Supports v-model:open for toggling visibility without remounting.
<ScriptGoogleMapsMarker :position="pos" @click="open = !open">
<ScriptGoogleMapsOverlayView v-model:open="open" anchor="bottom-center" :offset="{ x: 0, y: -50 }">
<MyCustomPopup @close="open = false" />
</ScriptGoogleMapsOverlayView>
</ScriptGoogleMapsMarker>
Direct :position Prop: Marker components now accept :position as a top-level prop (no options bag needed for the most common case).
Additional Components:
ScriptGoogleMapsStaticMap (#673): The static placeholder is now a standalone component, with images routed through your server so API keys stay server-side. Use it inside #placeholder on ScriptGoogleMaps, or standalone for store locators and contact pages that never need the interactive Maps API.
ScriptGoogleMapsGeoJson (#656): Declarative wrapper around google.maps.Data for loading and styling GeoJSON with full event bindings.
Infrastructure:
- Color mode support (#587): Auto light/dark map switching with
mapIds prop
- Geocode proxy: Server-side geocoding reduces billing and hides API keys
- Memory leak fixes (#651):
useGoogleMapsResource composable ensures all sub-components clean up safely on unmount, even across async boundaries
- Marker clustering perf (#517, #653): Batch operations with
noDraw flag to avoid multiple rerenders
Deprecation: The legacy ScriptGoogleMapsMarker (wrapping google.maps.Marker) and ScriptGoogleMapsAdvancedMarkerElement names have been consolidated into ScriptGoogleMapsMarker (wrapping google.maps.marker.AdvancedMarkerElement). We removed ScriptGoogleMapsPinElement; use the #content slot on ScriptGoogleMapsMarker instead.
🔧 Environment-Variable Config
The module now auto-populates runtimeConfig.public.scripts defaults for any enabled registry entry. Script IDs, keys, and domains resolve from NUXT_PUBLIC_SCRIPTS_* env vars without any runtimeConfig boilerplate. See PR #634.
# .env
NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID=G-XXXXXX
NUXT_PUBLIC_SCRIPTS_POSTHOG_API_KEY=phc_xxx
⚠️ Breaking Changes & Migration
Upgrading from v0? See the v0 to v1 migration guide for the summary table and before/after diffs for every breaking change and deprecation.
🐛 Bug Fixes
cdfb697 fix(rybbit): queue custom events before script loads (#585)
f8ce5a1 fix(gtm): invoke onBeforeGtmStart callback when ID is in config (#584)
a8d20b0 fix: add estree-walker as a dependency (#583)
4c79486 fix(plausible): use consistent window reference in clientInit stub (#574)
78367b1 fix(matomo): respect user-provided URL protocol (#572)
c685f43 fix: broken type augmenting
e2050a2 fix: align templates with existing augments (#589)
da3a8cc chore: include .nuxt types (#588)
039380e fix: prevent memory leaks in all Google Maps sub-components (#651)
7e139b3 fix: avoid mutating runtimeConfig scriptOptions (#638)
01b1af4 fix: expand self-closing <Script*> tags to prevent SFC extraction issues (#613)
c3a6098 fix: preserve compressed/binary request bodies in proxy handler (#619)
96db067 fix: missing Bing UET types (#710)
fdaf089 fix(types): prevent registry entry types from collapsing to never (#701)
698a585 fix: inherit registry scriptOptions in composable instances (#691)
506dfd8 fix(google-maps): guard pan-on-open for closed/unpositioned overlay (#698)
6fdd533 fix(google-maps): prevent center reset on re-render and export clusterer types (#686)
0e4ae9e fix(google-maps): prevent zoom/pan reset when overlay toggles (#685)
33ebf61 fix(google-maps): close races in resolveQueryToLatLng (#693)
4df13ed fix: add defineSlots to all components for proper slot type inference (#684)
afbb6bd fix(types): broken IDE display of registry types (#683)
63d4da5 fix: add v0 migration warnings and docs for breaking config changes (#679)
3007458 fix(google-analytics): add www.google.com and www.googletagmanager.com to proxy domains (#678)
1c47e72 fix: add missing proxy domains across registry scripts
e6ecfff fix(google-maps): bind $attrs to overlay view (#672)
c2f8a8b fix(google-maps): remove redundant slot props from OverlayView (#666)
b65e5db fix(google-maps): OverlayView, InfoWindow, and AdvancedMarkerElement DX issues (#660)
a597de9 fix: prevent memory leak in ScriptGoogleMapsAdvancedMarkerElement (#649)
32ff4fa fix: improve registry script DX and type safety (#647)
569eeeb fix(first-party): inject proxy endpoints for boolean/mock registry entries (#640)
00fbaae fix: allow custom script keys in ScriptRegistry type (#632)
3b93696 fix(plausible): broken firstParty mode
1c31a71 fix(gravatar): broken proxy
Nuxt Scripts v1 is the first stable release, pushing the ecosystem forward for better privacy and performance for third-party scripts.
📣 Highlights
🔒 First-Party Mode: Privacy Focused Proxy
Every third-party script request exposes your users data to fingerprinting.
Different providers are more intrusive, for example, the X Pixel accesses 9 browser fingerprinting APIs (including
navigator.getBattery()), sets 5 tracking cookies, and makes requests to 3 separate domains. Microsoft Clarity reads 10 fingerprinting APIs across 3 domains.First-party mode acts as a reverse proxy: scripts are bundled at build time and served from your domain, while runtime requests are securely forwarded through your server. Data sent to third-party servers gets anonymised: IPs (
180.233.124.74->180.233.124.0), browser versions (Mozilla/5.0 (compatible; Chrome/120.0)) and more. This is auto-enabled for all scripts that support it.A side-effect is a performance boost from avoiding extra DNS lookups, fewer cookie banners, and reducing expensive fingerprinting queries. It also makes ad-blockers ineffective since requests appear same-origin.
See the First-Party Mode Guide and PR #577 for details.
🛠️ Rebuilt DevTools
The Nuxt DevTools panel has been rewritten around the v1 privacy and capability model. New views surface the things v1 does differently.
🎉 Partytown Web Worker Support
Load third-party scripts off the main thread using Partytown. Scripts run in a web worker, freeing the main thread for your app. Integrates directly with first-party mode. See PR #576.
Set
partytown: trueper-script:Auto-forwarding supported for:
googleAnalytics,plausibleAnalytics,fathomAnalytics,umamiAnalytics,matomoAnalytics,segment,mixpanelAnalytics,bingUet,metaPixel,xPixel,tiktokPixel,snapchatPixel,redditPixel,cloudflareWebAnalytics🐦 SSR Social Embeds
Third-party embed scripts (Twitter widgets, Instagram embeds, Bluesky posts) hurt performance and leak user data. Following the Cloudflare Zaraz approach, Nuxt Scripts now fetches embed data server-side and securely proxies all assets through your domain. See PR #590.
✋ First-Class Consent Controls
v1 treats consent as a first-class concern with two complementary APIs. See the Consent Guide, PR #544, PR #631, and PR #712.
Every consent-aware registry script now exposes a vendor-native
consentobject on the returned instance plus a typeddefaultConsentoption applied before the first tracking call.📦 New Registry Scripts
Other Changes
🔄 Script Reload API
Scripts now expose a
.reload()method for re-executing DOM-scanning scripts after SPA navigation. See commit 77f853b.🔐 Automatic SRI Integrity Hashes
Bundled scripts can automatically generate Subresource Integrity hashes. See PR #575.
📊 Script Stats Export
New
@nuxt/scripts/statssubpath export for auditing script privacy, performance, and security characteristics.🎬 YouTube Player Overhaul
ratioprop📹 Vimeo Player Enhancements
ratioprop, matching YouTube Player API🗺️ Google Maps Overhaul
The Google Maps integration received a major DX overhaul for v1, making it feel like a native Vue component library rather than a wrapper around options bags.
Declarative SFC Components (#510): 11 composable components for markers, shapes, overlays, clustering, and more. All use Vue's injection system for parent/child communication and clean up automatically on unmount.
Custom Marker Content (#658): The
#contentslot onScriptGoogleMapsMarkerreplaces the default pin with any HTML or Vue template. Build price tags, status badges, or any custom marker visual declaratively.Custom Overlay View (#658):
ScriptGoogleMapsOverlayViewrenders arbitrary Vue content at a map position with full styling control. When nested inside a marker, it auto-inherits position and follows the marker during drag. Supportsv-model:openfor toggling visibility without remounting.Direct
:positionProp: Marker components now accept:positionas a top-level prop (no options bag needed for the most common case).Additional Components:
ScriptGoogleMapsStaticMap(#673): The static placeholder is now a standalone component, with images routed through your server so API keys stay server-side. Use it inside#placeholderonScriptGoogleMaps, or standalone for store locators and contact pages that never need the interactive Maps API.ScriptGoogleMapsGeoJson(#656): Declarative wrapper aroundgoogle.maps.Datafor loading and styling GeoJSON with full event bindings.Infrastructure:
mapIdspropuseGoogleMapsResourcecomposable ensures all sub-components clean up safely on unmount, even across async boundariesnoDrawflag to avoid multiple rerendersDeprecation: The legacy
ScriptGoogleMapsMarker(wrappinggoogle.maps.Marker) andScriptGoogleMapsAdvancedMarkerElementnames have been consolidated intoScriptGoogleMapsMarker(wrappinggoogle.maps.marker.AdvancedMarkerElement). We removedScriptGoogleMapsPinElement; use the#contentslot onScriptGoogleMapsMarkerinstead.🔧 Environment-Variable Config
The module now auto-populates
runtimeConfig.public.scriptsdefaults for any enabled registry entry. Script IDs, keys, and domains resolve fromNUXT_PUBLIC_SCRIPTS_*env vars without anyruntimeConfigboilerplate. See PR #634.# .env NUXT_PUBLIC_SCRIPTS_GOOGLE_ANALYTICS_ID=G-XXXXXX NUXT_PUBLIC_SCRIPTS_POSTHOG_API_KEY=phc_xxxUpgrading from v0? See the v0 to v1 migration guide for the summary table and before/after diffs for every breaking change and deprecation.
🐛 Bug Fixes
cdfb697fix(rybbit): queue custom events before script loads (#585)f8ce5a1fix(gtm): invoke onBeforeGtmStart callback when ID is in config (#584)a8d20b0fix: addestree-walkeras a dependency (#583)4c79486fix(plausible): use consistent window reference in clientInit stub (#574)78367b1fix(matomo): respect user-provided URL protocol (#572)c685f43fix: broken type augmentinge2050a2fix: align templates with existing augments (#589)da3a8ccchore: include.nuxttypes (#588)039380efix: prevent memory leaks in all Google Maps sub-components (#651)7e139b3fix: avoid mutating runtimeConfig scriptOptions (#638)01b1af4fix: expand self-closing<Script*>tags to prevent SFC extraction issues (#613)c3a6098fix: preserve compressed/binary request bodies in proxy handler (#619)96db067fix: missing Bing UET types (#710)fdaf089fix(types): prevent registry entry types from collapsing tonever(#701)698a585fix: inherit registry scriptOptions in composable instances (#691)506dfd8fix(google-maps): guard pan-on-open for closed/unpositioned overlay (#698)6fdd533fix(google-maps): prevent center reset on re-render and export clusterer types (#686)0e4ae9efix(google-maps): prevent zoom/pan reset when overlay toggles (#685)33ebf61fix(google-maps): close races inresolveQueryToLatLng(#693)4df13edfix: adddefineSlotsto all components for proper slot type inference (#684)afbb6bdfix(types): broken IDE display of registry types (#683)63d4da5fix: add v0 migration warnings and docs for breaking config changes (#679)3007458fix(google-analytics): addwww.google.comandwww.googletagmanager.comto proxy domains (#678)1c47e72fix: add missing proxy domains across registry scriptse6ecffffix(google-maps): bind$attrsto overlay view (#672)c2f8a8bfix(google-maps): remove redundant slot props from OverlayView (#666)b65e5dbfix(google-maps): OverlayView, InfoWindow, and AdvancedMarkerElement DX issues (#660)a597de9fix: prevent memory leak inScriptGoogleMapsAdvancedMarkerElement(#649)32ff4fafix: improve registry script DX and type safety (#647)569eeebfix(first-party): inject proxy endpoints for boolean/mock registry entries (#640)00fbaaefix: allow custom script keys inScriptRegistrytype (#632)3b93696fix(plausible): broken firstParty mode1c31a71fix(gravatar): broken proxy