### Install dependencies with pnpm Source: https://scripts.nuxt.com/docs/getting-started/contributing.md Install dependencies and prepare the workspace after cloning the repository. Requires pnpm. ```sh pnpm i && pnpm dev:prepare ``` -------------------------------- ### Run the playground with pnpm dev Source: https://scripts.nuxt.com/docs/getting-started/contributing.md Start the playground development server. ```sh pnpm dev ``` -------------------------------- ### Implement PayPal v6 payment flow Source: https://scripts.nuxt.com/docs/migration-guide/v0-to-v1.md Use the sdkInstance to check eligibility and start a payment session. ```ts const eligibility = await sdkInstance.findEligibleMethods() if (eligibility.isEligible('paypal')) { const session = sdkInstance.createPayPalOneTimePaymentSession({ onApprove: async (data) => { /* capture order */ }, }) await session.start({ presentationMode: 'auto' }, createOrderPromise) } ``` -------------------------------- ### Cloudflare Web Analytics schema and example usage Source: https://scripts.nuxt.com/docs/guides/registry-scripts.md The schema defines the Cloudflare Web Analytics options, requiring a token of at least 32 characters and an optional spa flag. The example shows a development-time call with a short token, which Nuxt Scripts skips and logs as invalid during development. ```ts export const CloudflareWebAnalyticsOptions = object({ /** * The Cloudflare Web Analytics token. */ token: pipe(string(), minLength(32)), /** * Cloudflare Web Analytics enables measuring SPAs automatically by overriding the History API’s pushState function * and listening to the onpopstate. Hash-based router is not supported. * * @default true */ spa: optional(boolean()), }) ``` ```ts useScriptCloudflareWebAnalytics({ token: '123', // skipped in development because the token is too short }) ``` -------------------------------- ### Upgrade Nuxt project with nuxi upgrade --force Source: https://scripts.nuxt.com/docs/getting-started/installation.md Upgrades an existing Nuxt project to meet the prerequisites for Nuxt Scripts 2 (Node.js 24+, Nuxt 4.5.1+, Unhead >=3.3.1 <4). Run this before installing the module. ```bash npx nuxi@latest upgrade --force ``` -------------------------------- ### Add Nuxt Scripts module with nuxi module add scripts Source: https://scripts.nuxt.com/docs/getting-started/installation.md Installs Nuxt Scripts and adds it to the modules array in your Nuxt config. This is the recommended installation command. ```bash npx nuxi@latest module add scripts ``` -------------------------------- ### Lifecycle-aware SDK readiness with resolve({ waitFor }) Source: https://scripts.nuxt.com/docs/api/use-script.md Use resolve({ waitFor }) when a vendor script exposes a callback that fires after the script element's load event. The example waits for window.onExampleReady to resolve with { ready: true }, and returns a cleanup function that deletes the callback. Listener cleanup and abort rejection are tied to the shared script lifecycle. ```TypeScript const sdk = useScript<{ ready: true }>('https://example.com/sdk.js', { resolve: ({ waitFor }) => waitFor<{ ready: true }>((resolve) => { window.onExampleReady = () => resolve({ ready: true }) return () => delete window.onExampleReady }), }) const api = await sdk.load() ``` -------------------------------- ### Register scripts with scripts:registry hook Source: https://scripts.nuxt.com/docs/api/nuxt-hooks.md Use this hook within a Nuxt module setup to push custom scripts to the registry. The example demonstrates defining a script label, logo, source URL, bundling preference, and an auto-imported composable. ```ts import { createResolver, defineNuxtModule } from '@nuxt/kit' const { resolve } = createResolver(import.meta.url) export default defineNuxtModule({ setup(_options, nuxt) { nuxt.hooks.hook('scripts:registry', async (registry) => { registry.push({ // Shown in DevTools label: 'My Custom Script', logo: ``, // Static script URL and bundling capability src: 'https://cdn.jsdelivr.net/npm/my-custom-script@1.0.0', bundle: true, // Auto-imported composable import: { name: 'useScriptMyCustomScript', from: resolve('./runtime/scripts/my-custom-script'), }, }) }) }, }) ``` -------------------------------- ### Lint and test with pnpm Source: https://scripts.nuxt.com/docs/getting-started/contributing.md Run linting and tests before submitting a change. Execute both commands in sequence. ```sh pnpm lint ``` ```sh pnpm test:run ``` -------------------------------- ### Run nuxi prepare for type augmentation Source: https://scripts.nuxt.com/docs/migration-guide/v0-to-v1.md Execute the nuxi prepare command to update generated type templates after upgrading. ```bash npx nuxi prepare ``` -------------------------------- ### Load multiple instances with unique key (useScriptGoogleAnalytics) Source: https://scripts.nuxt.com/docs/guides/registry-scripts.md Load multiple instances of a registry script by giving each call a unique `key`. Without a key, the first script instance is returned. ```ts const { proxy: gaOne } = useScriptGoogleAnalytics({ id: 'G-TR58L0EF8P', }) const { proxy: gaTwo } = useScriptGoogleAnalytics({ // without a key the first script instance will be returned key: 'gtag2', id: 'G-1234567890', }) ``` -------------------------------- ### Manual script warmup Source: https://scripts.nuxt.com/docs/guides/warmup.md Use the warmup method to manually initiate script loading based on user interaction or viewport visibility. ```ts const script = useScript('/video.js', { trigger: 'manual' }) // Start downloading when the video enters the viewport onVisible(videoContainer, () => { script.warmup('preload') }) // Execute after a click onClick(videoContainer, () => { script.load() }) ``` -------------------------------- ### Idle timeout trigger: composable and nuxt.config Source: https://scripts.nuxt.com/docs/guides/script-triggers.md Shows how to use `useScriptTriggerIdleTimeout()` in a composable and the equivalent `idleTimeout` trigger in `nuxt.config.ts`. The timer starts after Nuxt is ready. ```ts useScript('https://example.com/analytics.js', { trigger: useScriptTriggerIdleTimeout({ timeout: 5000 }) }) ``` ```ts export default defineNuxtConfig({ scripts: { registry: { googleAnalytics: { id: 'GA_MEASUREMENT_ID', trigger: { idleTimeout: 3000 }, } } } }) ``` -------------------------------- ### Handling pre-hydration events with ssrAttrs Source: https://scripts.nuxt.com/docs/api/use-script-trigger-element.md A Vue component that binds ssrAttrs to an element so a pre-hydration mousedown event still starts the script. The trigger is checked to be a promise before reading ssrAttrs. ```Vue ``` -------------------------------- ### Run migration CLI Source: https://scripts.nuxt.com/docs/migration-guide/v1-to-v2.md Use the migration CLI to update the project. The --dry-run flag allows previewing changes before applying them. ```bash npx @nuxt/scripts-cli migrate v2 --dry-run npx @nuxt/scripts-cli migrate v2 ``` -------------------------------- ### Load js-confetti in a component with useScriptNpm Source: https://scripts.nuxt.com/docs/getting-started/confetti-tutorial.md Call useScriptNpm inside a Vue component's setup script to load the js-confetti browser file. After this, the browser's Network panel should show the script request. ```vue ``` -------------------------------- ### Define a global script as a URL string Source: https://scripts.nuxt.com/docs/guides/global.md Configure a global script by mapping a key to its source URL. ```ts export default defineNuxtConfig({ scripts: { globals: { myScript: 'https://analytics.com/tracker.js', } } }) ``` -------------------------------- ### Migrate custom readiness callbacks to resolve Source: https://scripts.nuxt.com/docs/migration-guide/v1-to-v2.md Replace the deprecated use option with the resolve option using the waitFor helper to manage script lifecycle and readiness. ```diff const script = useScript('https://example.com/sdk.js', { - use: () => readyPromise.then(() => window.example), + resolve: ({ waitFor }) => waitFor((resolve) => { + window.onExampleReady = () => resolve(window.example) + return () => delete window.onExampleReady + }), }) ``` -------------------------------- ### Bind third-party consent manager to trigger Source: https://scripts.nuxt.com/docs/guides/first-party.md Binds a third-party consent manager's signal (OneTrust example) to a reactive ref and passes it to `useScriptTriggerConsent()`. The Google Analytics script loads only when the consent signal becomes true. ```vue ``` -------------------------------- ### Create custom composable for shared config (useFathomAnalytics) Source: https://scripts.nuxt.com/docs/guides/registry-scripts.md Keep shared configuration in your own composable to reuse the same script instance across pages. ```ts export function useFathomAnalytics() { return useScriptFathomAnalytics({ site: 'SITE_ID', }) } ``` -------------------------------- ### Error details hidden without crossorigin Source: https://scripts.nuxt.com/docs/guides/cors.md Without `crossorigin`, browsers hide error details from external scripts for security. This example shows that `window.onerror` receives only "Script error." instead of the actual error. ```js window.onerror = msg => console.log(msg) // Shows: "Script error." instead of actual error ``` -------------------------------- ### Guard GTM initialization Source: https://scripts.nuxt.com/docs/migration-guide/v0-to-v1.md Use a flag to prevent repeated initialization in the onBeforeGtmStart callback. ```diff +let initialized = false useScriptGoogleTagManager({ onBeforeGtmStart: (gtag) => { + if (initialized) return + initialized = true // your init code } }) ``` -------------------------------- ### Binary load gate with useScriptTriggerConsent Source: https://scripts.nuxt.com/docs/guides/consent.md Sets up a binary consent trigger shared across a main-thread script and a cookie banner. The trigger is created in utils/cookie.ts, passed to useScript() so the analytics script waits for acceptance, and the banner calls scriptsConsent.accept() to grant consent. ```ts export const scriptsConsent = useScriptTriggerConsent() ``` ```vue ``` ```vue ``` -------------------------------- ### Fanning out consent to multiple scripts Source: https://scripts.nuxt.com/docs/guides/consent.md Shows how to fan out consent updates to multiple scripts (Google Analytics, Meta Pixel, Matomo) from a single banner. Each vendor uses its own consent API: ga.consent.update, meta.consent.grant/revoke, and matomo.consent.give/forget. The Matomo example requires defaultConsent: 'required' or 'given' for consent.give() to work. ```ts const ga = useScriptGoogleAnalytics({ id: 'G-XXX', defaultConsent: { ad_storage: 'denied', analytics_storage: 'denied' } }) const meta = useScriptMetaPixel({ id: '123', defaultConsent: 'denied' }) const matomo = useScriptMatomoAnalytics({ cloudId: 'foo.matomo.cloud', defaultConsent: 'required' }) function onAcceptAll() { ga.consent.update({ ad_storage: 'granted', ad_user_data: 'granted', ad_personalization: 'granted', analytics_storage: 'granted', }) meta.consent.grant() matomo.consent.give() } function onDeclineAll() { ga.consent.update({ ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied', }) meta.consent.revoke() matomo.consent.forget() } ``` -------------------------------- ### Manual trigger with load() Source: https://scripts.nuxt.com/docs/guides/script-triggers.md Shows how to use the `manual` trigger to load a script by calling `load()` directly. The script does not load automatically. ```ts const { load } = useScript('https://example.com/script.js', { trigger: 'manual' }) // Load when you decide await load() ``` -------------------------------- ### Reload script after SPA navigation with reload() Source: https://scripts.nuxt.com/docs/api/use-script.md Use reload() to remove, reinsert, and re-execute a script that scans the DOM once and must scan again after SPA navigation. The example reloads the script when the route path changes. Prefer the vendor's SPA API when available, such as iubenda's _iub.cs.api.activateSnippets(). ```TypeScript const { reload } = useScript('https://example.com/dom-scanner.js') // Reload when navigating watch(() => route.path, () => reload()) ``` -------------------------------- ### Load js-confetti with useScriptNpm, useScript, and useHead Source: https://scripts.nuxt.com/docs/getting-started/confetti-tutorial.md Three equivalent ways to load the same js-confetti browser file: the registry script useScriptNpm, the low-level useScript, and useHead. Use useScriptNpm for a convenient registry-based approach; useScript for direct URL control; useHead for manual script injection. ```ts useScriptNpm({ packageName: 'js-confetti', file: 'dist/js-confetti.browser.js', version: '0.12.0', }) ``` ```ts useScript('https://unpkg.com/js-confetti@0.12.0/dist/js-confetti.browser.js') ``` ```ts useHead({ script: [ { src: 'https://unpkg.com/js-confetti@0.12.0/dist/js-confetti.browser.js' } ] }) ``` -------------------------------- ### Migrate markers and centerMarker props Source: https://scripts.nuxt.com/docs/migration-guide/v0-to-v1.md Replace the markers and centerMarker props by using child ScriptGoogleMapsMarker components. ```diff - + + + + ``` -------------------------------- ### Load a global script via app.head Source: https://scripts.nuxt.com/docs/guides/global.md The standard way to load a global script using Nuxt's app.head configuration. ```ts export default defineNuxtConfig({ app: { head: { script: [{ src: 'https://analytics.com/tracker.js', async: true }] } } }) ``` -------------------------------- ### Define a global script with options Source: https://scripts.nuxt.com/docs/guides/global.md Use a two-item tuple to provide script options, such as triggers, alongside the script source. ```ts export default defineNuxtConfig({ scripts: { globals: { myScript: [ { src: 'https://example.com/script.js' }, // load the script as part of the hydration process instead of on idle { trigger: 'client' } ] } } }) ``` -------------------------------- ### Customize ScriptYouTubePlayer with awaitingLoad slot Source: https://scripts.nuxt.com/docs/guides/facade-components.md Use the #awaitingLoad slot to display content while the component is waiting for the script to trigger. ```vue ``` -------------------------------- ### Load a script with useScript in app.vue Source: https://scripts.nuxt.com Demonstrates loading a script using the useScript composable in app.vue, including trigger configuration and type-safe proxy usage. ```javascript const { proxy } = useScript('/tracker.js', { trigger: 'onNuxtReady', use() { return { trackEvent: window.trackEvent } } }) // fully typed, SSR safe proxy.trackEvent('page_view') ``` -------------------------------- ### Define a script with useScript Source: https://scripts.nuxt.com/docs/guides/warmup.md Basic usage of useScript to load a script with the default trigger. ```ts useScript('/script.js') ``` -------------------------------- ### Migrate ScriptGoogleMapsPinElement to #content slot Source: https://scripts.nuxt.com/docs/migration-guide/v0-to-v1.md Move custom pin markup into the #content slot of ScriptGoogleMapsMarker as ScriptGoogleMapsPinElement is removed. ```diff - - - + + + ``` -------------------------------- ### Migrate static placeholder props to ScriptGoogleMapsStaticMap Source: https://scripts.nuxt.com/docs/migration-guide/v0-to-v1.md Use the ScriptGoogleMapsStaticMap component within the #placeholder slot instead of using placeholder props. ```diff - + + + ``` -------------------------------- ### Rename ScriptGoogleMapsOverlayView overlay ref Source: https://scripts.nuxt.com/docs/migration-guide/v0-to-v1.md Update ScriptGoogleMapsOverlayView refs to use overlayView instead of the deprecated overlay key. ```diff const overlayRef = ref() onMounted(() => { - console.log(overlayRef.value?.overlay) + console.log(overlayRef.value?.overlayView) }) ``` -------------------------------- ### Configure Google Analytics with consent in consent.ts Source: https://scripts.nuxt.com Shows how to initialize Google Analytics with default consent settings and update them using the consent object. ```typescript const { consent } = useScriptGoogleAnalytics({ id: 'G-XXXXXXXX', defaultConsent: { ad_storage: 'denied', analytics_storage: 'denied', }, }) // Google Consent Mode v2 consent.update({ ad_storage: 'granted', analytics_storage: 'granted', }) ``` -------------------------------- ### Reuse one instance across pages (nuxt.config.ts + component) Source: https://scripts.nuxt.com/docs/guides/registry-scripts.md Configure a registry script once in `nuxt.config.ts` and reuse it in a component without repeating options. The explicit `trigger: 'onNuxtReady'` loads the script globally. ```ts export default defineNuxtConfig({ scripts: { registry: { // The explicit trigger loads the script globally. fathomAnalytics: { site: 'SITE_ID', trigger: 'onNuxtReady', } } } }) ``` ```vue ``` -------------------------------- ### Mock registry script in development (nuxt.config.ts) Source: https://scripts.nuxt.com/docs/guides/registry-scripts.md Use in development to mock a registry script so the vendor script is not loaded. Mock mode registers a manual context and skips option validation. ```ts export default defineNuxtConfig({ scripts: { registry: { googleTagManager: { trigger: 'onNuxtReady' }, }, }, $development: { scripts: { registry: { googleTagManager: 'mock', }, }, }, }) ``` -------------------------------- ### Define a global script with attributes Source: https://scripts.nuxt.com/docs/guides/global.md Configure a global script with additional HTML attributes like integrity. ```ts export default defineNuxtConfig({ scripts: { globals: { myScript: { src: 'https://example.com/script.js', integrity: 'sha256-abc123', } } } }) ``` -------------------------------- ### Nuxt config registry script with interaction trigger Source: https://scripts.nuxt.com/docs/api/use-script-trigger-interaction.md Shows how to configure a registry script in `nuxt.config` to load on user interaction. The `trigger` property uses the `interaction` key with an array of events. ```ts export default defineNuxtConfig({ scripts: { registry: { googleAnalytics: { id: 'GA_MEASUREMENT_ID', trigger: { interaction: ['scroll', 'click', 'keydown'] } } } } }) ``` -------------------------------- ### useScript() Source: https://scripts.nuxt.com/docs/api/use-script.md Load and control third-party scripts with Nuxt-specific options. This composable wraps Unhead's useScript() adding Nuxt triggers, bundling, proxying, and reload(). ```APIDOC ## useScript() ### Description Load and control third-party scripts with Nuxt-specific options. This composable wraps Unhead's useScript() adding Nuxt triggers, bundling, proxying, and reload(). ### Signature ```ts export function useScript = Record>( input: UseScriptInput, options?: NuxtUseScriptOptions, ): UseScriptContext, T>> ``` ### Arguments #### `UseScriptInput` Pass a URL string or an object containing script tag attributes. ```ts export type UseScriptInput = string | { src: string async?: boolean defer?: boolean type?: string integrity?: string crossorigin?: string innerHTML?: string textContent?: string referrerpolicy?: string // Additional Unhead script and data attributes are supported. } ``` #### `NuxtUseScriptOptions` Nuxt Scripts extends Unhead's script triggers and warmup options with these options: - `resolve` - Resolve the loaded SDK with lifecycle-bound `signal` and `waitFor` helpers. - `use` - Legacy synchronous or async SDK resolver. Prefer `resolve` for callback-based readiness. - `trigger` - Triggering Script Loading - `bundle` - Control first-party bundling. - `proxy` - Enable or disable supported collection proxying for a registry script. - `partytown` - Run a supported registry script through Partytown. ```ts export type NuxtUseScriptOptions = Omit, 'trigger'> & { /** * The trigger to load the script: * - `onNuxtReady` - Load the script when Nuxt is ready. * - `manual` - Load the script manually by calling `load()` * - `Promise` - Load the script when the promise resolves. */ trigger?: UseScriptOptions['trigger'] | 'onNuxtReady' /** * Bundle the script as an asset and serve it from your server. This avoids the * original host's DNS lookup and keeps the initial request on your origin. * - `true` - Bundle the script as an asset. * - `'force'` - Bundle and download the script again instead of using the build cache. * - `false` - Do not bundle the script. (default for plain useScript calls) * * @deprecated Bundling is enabled automatically for registry scripts that support it. * Set `bundle: false` on a registry script to disable it. */ bundle?: boolean | 'force' /** * Load the script in a web worker using Partytown. * When enabled, adds `type="text/partytown"` to the script tag. * Requires @nuxtjs/partytown to be installed and configured separately. * @see https://partytown.qwik.dev/ */ partytown?: boolean /** * Control proxying for this script. * When `false`, collection requests go directly to the third-party server. * When `true`, collection requests are proxied through `/_scripts/p/`. * This option applies to registry scripts and defaults to their declared * `proxy` capability. */ proxy?: boolean /** * Skip schema validation for the script input. Use this for development stubs * that do not load the actual script. */ skipValidation?: boolean /** * Specify a strategy for warming up the connection to the third-party script. * - `false` - Disable preloading. * - `'preload'` - Preload the script. * - `'preconnect'` | `'dns-prefetch'` - Preconnect to the script origin. */ warmupStrategy?: false | 'preload' | 'preconnect' | 'dns-prefetch' } ``` ### Return Value Returns a `UseScriptContext` object with the resolved SDK and lifecycle methods. ### Notes - The `partytown` option takes an early SSR path and ignores other script attributes and options such as `use`, `beforeInit`, and `warmupStrategy`. The returned stub reports `loaded`; `load()` is a no-op, `remove()` only disconnects DevTools observation, and `proxy`, `reload()`, and lifecycle callbacks are not available. Treat the Partytown return value as an implementation detail. ``` -------------------------------- ### Migrate top-level center and zoom props Source: https://scripts.nuxt.com/docs/migration-guide/v0-to-v1.md Pass center and zoom values via the map-options prop instead of top-level attributes. ```diff - + ``` -------------------------------- ### Generate Agent Skill with skilld add @nuxt/scripts Source: https://scripts.nuxt.com/docs/getting-started/installation.md Optional command to generate an Agent Skill for the Nuxt Scripts package using skilld. Shown in a tip callout. ```bash npx skilld add @nuxt/scripts ``` -------------------------------- ### Customize ScriptYouTubePlayer with loading slot Source: https://scripts.nuxt.com/docs/guides/facade-components.md Use the #loading slot to define content displayed specifically while the script is loading. ```vue ``` -------------------------------- ### Runtime config for Cloudflare Web Analytics Source: https://scripts.nuxt.com/docs/guides/registry-scripts.md The .env file provides the Cloudflare Web Analytics token as a public runtime config field. The nuxt.config.ts registers the script with a client trigger, allowing the token to be supplied via environment variables instead of hardcoding. ```text NUXT_PUBLIC_SCRIPTS_CLOUDFLARE_WEB_ANALYTICS_TOKEN=YOUR_TOKEN ``` ```ts export default defineNuxtConfig({ scripts: { registry: { cloudflareWebAnalytics: { trigger: 'client' }, }, }, }) ``` -------------------------------- ### Nuxt config global script with interaction trigger Source: https://scripts.nuxt.com/docs/api/use-script-trigger-interaction.md Shows how to configure a global script in `nuxt.config` to load on user interaction. The `trigger` property uses the `interaction` key with an array of events. ```ts export default defineNuxtConfig({ scripts: { globals: { chatWidget: ['https://widget.example.com/chat.js', { trigger: { interaction: ['scroll', 'click', 'touchstart'] } }] } } }) ``` -------------------------------- ### Basic usage in app.vue Source: https://scripts.nuxt.com/docs/api/use-script-trigger-consent.md Shows basic usage in app.vue. It creates a trigger, passes it to useScript, and conditionally renders accept/revoke buttons based on the consented ref. ```vue ``` -------------------------------- ### Nuxt config registry script with idleTimeout trigger Source: https://scripts.nuxt.com/docs/api/use-script-trigger-idle-timeout.md Shows how to configure a registry script in nuxt.config with an idleTimeout trigger of 3000 ms. ```ts export default defineNuxtConfig({ scripts: { registry: { googleAnalytics: { id: 'GA_MEASUREMENT_ID', trigger: { idleTimeout: 3000 } // Load 3 seconds after Nuxt ready } } } }) ```