From 9e0d28f9c54c5b202df04ca2895198824079f5b4 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Thu, 29 Jan 2026 16:04:22 -0800 Subject: [PATCH 1/3] fix(astro): Automatically use CSR control components for prerendered pages --- .../astro-node/src/pages/index.astro | 5 ++++ .../astro-node/src/pages/prerendered.astro | 25 ++++++++++++++++ integration/tests/astro/components.test.ts | 30 +++++++++++++++++++ .../astro-components/control/Protect.astro | 4 ++- .../astro-components/control/ProtectCSR.astro | 2 +- .../astro-components/control/SignedIn.astro | 4 ++- .../astro-components/control/SignedOut.astro | 4 ++- 7 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 integration/templates/astro-node/src/pages/prerendered.astro diff --git a/integration/templates/astro-node/src/pages/index.astro b/integration/templates/astro-node/src/pages/index.astro index 089eac14653..2f773ce2930 100644 --- a/integration/templates/astro-node/src/pages/index.astro +++ b/integration/templates/astro-node/src/pages/index.astro @@ -64,6 +64,11 @@ import { SignedIn, SignedOut, SignOutButton, OrganizationSwitcher } from '@clerk 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..c9d79d9d9b1 --- /dev/null +++ b/integration/templates/astro-node/src/pages/prerendered.astro @@ -0,0 +1,25 @@ +--- +import { SignedIn, SignedOut } 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 93e8f21b35b..77f76f15468 100644 --- a/integration/tests/astro/components.test.ts +++ b/integration/tests/astro/components.test.ts @@ -511,4 +511,34 @@ testAgainstRunningApps({ withPattern: ['astro.node.withCustomRoles'] })('basic f // await expect(u.page.getByText('Loading')).toBeHidden(); await expect(u.page.getByText("I'm an admin")).toBeVisible(); }); + + test('prerendered page with control components works correctly', async ({ page, context }) => { + const u = createTestUtils({ app, page, context }); + + // Test while signed out + await u.page.goToRelative('/prerendered'); + await u.page.waitForClerkJsLoaded(); + await u.po.expect.toBeSignedOut(); + + // Verify SignedOut content is visible and SignedIn is hidden + await expect(u.page.locator('#signed-out-content')).toBeVisible(); + await expect(u.page.locator('#signed-in-content')).toBeHidden(); + + // 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 again while signed in + await u.page.goToRelative('/prerendered'); + await u.page.waitForClerkJsLoaded(); + + // Verify SignedIn content is visible and SignedOut is hidden + await expect(u.page.locator('#signed-in-content')).toBeVisible(); + await expect(u.page.locator('#signed-out-content')).toBeHidden(); + }); }); diff --git a/packages/astro/src/astro-components/control/Protect.astro b/packages/astro/src/astro-components/control/Protect.astro index c7e039987f4..a57486dc85c 100644 --- a/packages/astro/src/astro-components/control/Protect.astro +++ b/packages/astro/src/astro-components/control/Protect.astro @@ -26,7 +26,9 @@ type Props = ProtectProps & { const { isStatic, ...props } = Astro.props; -const ProtectComponent = isStaticOutput(isStatic) ? ProtectCSR : ProtectSSR; +// Use CSR if explicitly static OR if auth is unavailable (prerendered page) +const shouldUseCSR = isStaticOutput(isStatic) || !Astro.locals.auth; +const ProtectComponent = shouldUseCSR ? ProtectCSR : ProtectSSR; // 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 diff --git a/packages/astro/src/astro-components/control/ProtectCSR.astro b/packages/astro/src/astro-components/control/ProtectCSR.astro index cee284935c5..e3aa5ca8f3c 100644 --- a/packages/astro/src/astro-components/control/ProtectCSR.astro +++ b/packages/astro/src/astro-components/control/ProtectCSR.astro @@ -44,7 +44,7 @@ const {