diff --git a/.changeset/pink-dingos-exercise.md b/.changeset/pink-dingos-exercise.md new file mode 100644 index 00000000000..561d7ba7c98 --- /dev/null +++ b/.changeset/pink-dingos-exercise.md @@ -0,0 +1,5 @@ +--- +"@clerk/astro": patch +--- + +Fixed an error when using Control components in prerendered pages diff --git a/integration/templates/astro-node/src/pages/index.astro b/integration/templates/astro-node/src/pages/index.astro index 62e04e87c93..7f44152784f 100644 --- a/integration/templates/astro-node/src/pages/index.astro +++ b/integration/templates/astro-node/src/pages/index.astro @@ -64,6 +64,11 @@ import { Show, SignOutButton, OrganizationSwitcher } from '@clerk/astro/componen title='For members' body='Learn how Astro works and explore the official API docs.' /> + diff --git a/integration/templates/astro-node/src/pages/prerendered.astro b/integration/templates/astro-node/src/pages/prerendered.astro new file mode 100644 index 00000000000..85c382b7d44 --- /dev/null +++ b/integration/templates/astro-node/src/pages/prerendered.astro @@ -0,0 +1,25 @@ +--- +import { Show } from '@clerk/astro/components'; +import Layout from '../layouts/Layout.astro'; + +// This page is prerendered at build time despite output: 'server' mode +export const prerender = true; +--- + + +

Prerendered Page with Clerk Components

+ +

This page is statically generated at build time (prerender = true) in server output mode.

+ + +
+

✅ You are signed in! (This content should be hidden initially and shown after client-side auth check)

+
+
+ + +
+

🔒 You are signed out. (This content should be visible initially for signed-out users)

+
+
+
diff --git a/integration/tests/astro/components.test.ts b/integration/tests/astro/components.test.ts index e05722b722f..4919fa96ec8 100644 --- a/integration/tests/astro/components.test.ts +++ b/integration/tests/astro/components.test.ts @@ -513,4 +513,27 @@ testAgainstRunningApps({ withPattern: ['astro.node.withCustomRoles'] })('basic f // await expect(u.page.getByText('Loading')).toBeHidden(); await expect(u.page.getByText("I'm an admin")).toBeVisible({ timeout: 15_000 }); }); + + test('Show component works correctly on prerendered pages', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + + // Visit prerendered page when signed out + await u.page.goToRelative('/prerendered'); + await expect(u.page.getByText('🔒 You are signed out.')).toBeVisible(); + await expect(u.page.getByText('✅ You are signed in!')).not.toBeVisible(); + + // Sign in + await u.page.goToRelative('/sign-in'); + await u.po.signIn.waitForMounted(); + await u.po.signIn.signInWithEmailAndInstantPassword({ + email: fakeAdmin.email, + password: fakeAdmin.password, + }); + await u.po.expect.toBeSignedIn(); + + // Visit prerendered page when signed in + await u.page.goToRelative('/prerendered'); + await expect(u.page.getByText('✅ You are signed in!')).toBeVisible(); + await expect(u.page.getByText('🔒 You are signed out.')).not.toBeVisible(); + }); }); diff --git a/packages/astro/src/astro-components/control/Show.astro b/packages/astro/src/astro-components/control/Show.astro index 9a72534ddff..71b1e4882a1 100644 --- a/packages/astro/src/astro-components/control/Show.astro +++ b/packages/astro/src/astro-components/control/Show.astro @@ -22,7 +22,10 @@ if (typeof when === 'undefined') { const props = { ...rest, when }; -const ShowComponent = isStaticOutput(isStatic) ? ShowCSR : ShowSSR; +// If user explicitly sets isStatic prop, honor it +// Otherwise, detect based on runtime (whether auth function exists) +const shouldUseCSR = isStatic !== undefined ? isStaticOutput(isStatic) : !Astro.locals?.auth; +const ShowComponent = shouldUseCSR ? ShowCSR : ShowSSR; // Note: Astro server islands also use a "fallback" slot for loading states // See: https://docs.astro.build/en/guides/server-islands/#server-island-fallback-content