From bfedc43daa2d4e94120f8f344e605c77eebe0381 Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Fri, 29 May 2026 13:58:52 -0700 Subject: [PATCH] Make StackContext globally unique --- .claude/CLAUDE-KNOWLEDGE.md | 3 +++ packages/template/src/providers/stack-context.tsx | 11 +++++++++-- .../src/providers/translation-provider-client.tsx | 13 ++++++++++--- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/.claude/CLAUDE-KNOWLEDGE.md b/.claude/CLAUDE-KNOWLEDGE.md index 5715650cb..924995a54 100644 --- a/.claude/CLAUDE-KNOWLEDGE.md +++ b/.claude/CLAUDE-KNOWLEDGE.md @@ -568,3 +568,6 @@ A: Microsoft Entra ID's v2 token endpoint can reject authorization-code exchange ## Q: How should the development-environment dashboard load local config files? A: Use `jiti` to import the user's config module, matching `stack config push`, so helper functions such as `defineStackConfig(...)` or `makeConfig()` work. Disable `moduleCache` for this reader because the development-environment file watcher may import the same config path repeatedly after edits, and cached modules would otherwise hide changes. + +## Q: How should template React contexts avoid duplicate client-bundle context identities? +A: Define exported provider contexts such as `StackContext` and `TranslationContext` through `createGlobal` from `@stackframe/stack-shared/dist/utils/globals`, not direct `React.createContext(...)` exports. That helper stores the React context under `globalThis[Symbol.for("__hexclave-globals")]`, so duplicated SDK bundles still share the same provider/consumer context object. diff --git a/packages/template/src/providers/stack-context.tsx b/packages/template/src/providers/stack-context.tsx index 7f9cca302..289da0fd2 100644 --- a/packages/template/src/providers/stack-context.tsx +++ b/packages/template/src/providers/stack-context.tsx @@ -1,8 +1,15 @@ "use client"; import React from "react"; +import { createGlobal } from "@stackframe/stack-shared/dist/utils/globals"; import type { StackClientApp } from "../lib/stack-app/apps/interfaces/client-app"; -export const StackContext = React.createContext, -}>(null); +}; + +export const StackContext = createGlobal>( + "StackContext", + () => React.createContext(null), +); +StackContext.displayName ??= "StackContext"; diff --git a/packages/template/src/providers/translation-provider-client.tsx b/packages/template/src/providers/translation-provider-client.tsx index 6c3407c45..693b6f570 100644 --- a/packages/template/src/providers/translation-provider-client.tsx +++ b/packages/template/src/providers/translation-provider-client.tsx @@ -1,11 +1,18 @@ "use client"; -import { createContext, useContext } from "react"; +import React from "react"; +import { createGlobal } from "@stackframe/stack-shared/dist/utils/globals"; -export const TranslationContext = createContext, quetzalLocale: Map, -}>(null); +}; + +export const TranslationContext = createGlobal>( + "TranslationContext", + () => React.createContext(null), +); +TranslationContext.displayName ??= "TranslationContext"; export function TranslationProviderClient(props: { children: React.ReactNode,