Render WordPress footer scripts as server components using next/script with afterInteractive strategy.
The WPFooter component is a thin wrapper around WPScripts that renders WordPress footer scripts. It filters for FOOTER-location scripts and delegates to WPScripts with location="body".
Deprecated alias:
BodyScriptsis still exported as an alias for backwards compatibility, but new code should useWPFooter.
import { WPFooter } from '@axistaylor/nextpress'; export default async function WordPressLayout({ children }) { const { scripts } = await fetchAssets(uri); return ( <html> <head>{/* ... */}</head> <body> {children} <WPFooter scripts={scripts} pathname={uri} /> </body> </html> ); }
| Prop | Type | Required | Description |
|---|---|---|---|
scripts | EnqueuedScript[] | Yes | Array of WordPress scripts to render |
instance | string | No | WordPress instance slug (default: 'default') |
pathname | string | No | Current page pathname (used for WooCommerce proxy placeholder replacement) |
WPFooter filters for scripts with location === 'FOOTER' and renders each one as a next/script component with strategy="afterInteractive". This means:
Because next/script with afterInteractive is managed by Next.js regardless of component tree position, WPFooter works correctly wherever it's placed.
WPFooter needs the current URI for WooCommerce URL transformations. See WPHead - Retrieving URI in Layouts for the complete setup guide.
// app/(wordpress)/layout.tsx import { WPHead, WPFooter } from '@axistaylor/nextpress'; import { headers } from 'next/headers'; export default async function WordPressLayout({ children }) { const uri = (await headers()).get('x-uri') || '/'; const { scripts, stylesheets, importMap } = await fetchAssets(uri); const globalStyles = await fetchGlobalStyles(); return ( <html> <head> <WPHead scripts={scripts} stylesheets={stylesheets} globalStyles={globalStyles} importMap={importMap} pathname={uri} /> </head> <body> {children} <WPFooter scripts={scripts} pathname={uri} /> </body> </html> ); }
For each footer script, WPFooter renders (in order):
extraData (id {handle}-js-extra) - Localized script data with proxy placeholder replacementbefore (id {handle}-js-before) - Inline script (with wc-settings URL transformation for WooCommerce){handle}) - The script src (external scripts loaded directly, WordPress assets proxied)after (id {handle}-js-after) - Inline script after the main scriptThe -js-extra / -js-before / -js-after ID suffixes match WordPress's wp_enqueue_script naming so AssetUpdater can reliably locate each fragment on client-side navigation — in particular so processWcSettings() can run immediately after the wc-settings-js-extra block defines window.wcSettings.
All rendered with strategy="afterInteractive".
WPFooter brackets its output with two zero-byte marker scripts: id="nextpress-body-scripts-start" and id="nextpress-body-scripts-end". AssetUpdater uses these as the clear-and-refill boundary on client-side navigation.
WPFooter includes special handling for WooCommerce:
wc-settings transformation: The before script for wc-settings is transformed to replace WordPress backend URLs with frontend proxy URLsextraData content has proxy placeholders resolved for the current instance and pathnameWordPress asset URLs are automatically transformed:
/wp-content/...) become /atx/{instance}/wp-assets/.../wp-includes/..., /wp-admin/...) become /atx/{instance}/wp-internal-assets/...When using multiple WordPress backends:
<WPFooter scripts={scripts} instance="shop" pathname={uri} />
WPFooter is a React Server Component:
'use client' directivenext/script tags on the serverassetsByUri GraphQL queryimport { WPFooter } from '@axistaylor/nextpress'; import type { EnqueuedScript } from '@axistaylor/nextpress';