diff --git a/.changeset/serious-balloons-eat.md b/.changeset/serious-balloons-eat.md
new file mode 100644
index 0000000000..8430b0adf5
--- /dev/null
+++ b/.changeset/serious-balloons-eat.md
@@ -0,0 +1,9 @@
+---
+'@clerk/nextjs': minor
+'@clerk/clerk-react': minor
+---
+
+Speed up loading of clerk-js by using a `` tag when html is generated.
+This is supported during SSR, SSG in
+- Next.js Pages Router
+- Next.js App Router
diff --git a/packages/nextjs/src/app-router/client/ClerkProvider.tsx b/packages/nextjs/src/app-router/client/ClerkProvider.tsx
index 37927fcbc2..777b31a3df 100644
--- a/packages/nextjs/src/app-router/client/ClerkProvider.tsx
+++ b/packages/nextjs/src/app-router/client/ClerkProvider.tsx
@@ -6,6 +6,7 @@ import React, { useEffect, useTransition } from 'react';
import { ClerkNextOptionsProvider } from '../../client-boundary/NextOptionsContext';
import { useSafeLayoutEffect } from '../../client-boundary/useSafeLayoutEffect';
import type { NextClerkProviderProps } from '../../types';
+import { ClerkJSScript } from '../../utils/clerk-js-script';
import { mergeNextClerkPropsWithEnv } from '../../utils/mergeNextClerkPropsWithEnv';
import { useAwaitableNavigate } from './useAwaitableNavigate';
@@ -73,7 +74,10 @@ export const ClientClerkProvider = (props: NextClerkProviderProps) => {
return (
- {children}
+
+
+ {children}
+
);
};
diff --git a/packages/nextjs/src/pages/ClerkProvider.tsx b/packages/nextjs/src/pages/ClerkProvider.tsx
index d862445516..97c135d2e9 100644
--- a/packages/nextjs/src/pages/ClerkProvider.tsx
+++ b/packages/nextjs/src/pages/ClerkProvider.tsx
@@ -7,8 +7,10 @@ import React from 'react';
import { ClerkNextOptionsProvider } from '../client-boundary/NextOptionsContext';
import { useSafeLayoutEffect } from '../client-boundary/useSafeLayoutEffect';
import type { NextClerkProviderProps } from '../types';
+import { ClerkJSScript } from '../utils/clerk-js-script';
import { invalidateNextRouterCache } from '../utils/invalidateNextRouterCache';
import { mergeNextClerkPropsWithEnv } from '../utils/mergeNextClerkPropsWithEnv';
+
setErrorThrowerOptions({ packageName: PACKAGE_NAME });
export function ClerkProvider({ children, ...props }: NextClerkProviderProps): JSX.Element {
@@ -45,6 +47,7 @@ export function ClerkProvider({ children, ...props }: NextClerkProviderProps): J
{...mergedProps}
initialState={initialState}
>
+
{children}
diff --git a/packages/nextjs/src/utils/clerk-js-script.tsx b/packages/nextjs/src/utils/clerk-js-script.tsx
new file mode 100644
index 0000000000..fa3244b78d
--- /dev/null
+++ b/packages/nextjs/src/utils/clerk-js-script.tsx
@@ -0,0 +1,47 @@
+import { useClerk } from '@clerk/clerk-react';
+import { buildClerkJsScriptAttributes, clerkJsScriptUrl } from '@clerk/clerk-react/internal';
+import NextScript from 'next/script';
+import React from 'react';
+
+import { useClerkNextOptions } from '../client-boundary/NextOptionsContext';
+
+type ClerkJSScriptProps = {
+ router: 'app' | 'pages';
+};
+
+function ClerkJSScript(props: ClerkJSScriptProps) {
+ const { publishableKey, clerkJSUrl, clerkJSVersion, clerkJSVariant } = useClerkNextOptions();
+ const { domain, proxyUrl } = useClerk();
+ const options = {
+ domain,
+ proxyUrl,
+ publishableKey: publishableKey!,
+ clerkJSUrl,
+ clerkJSVersion,
+ clerkJSVariant,
+ };
+ const scriptUrl = clerkJsScriptUrl(options);
+
+ /**
+ * Notes:
+ * `next/script` in 13.x.x when used with App Router will fail to pass any of our `data-*` attributes, resulting in errors
+ * Nextjs App Router will automatically move inline scripts inside `