diff --git a/src/pages/page.tsx b/src/pages/page.tsx index 45611d7..b821aec 100644 --- a/src/pages/page.tsx +++ b/src/pages/page.tsx @@ -19,17 +19,10 @@ import { hasSiteBeenVisitedToday } from "@/utils/cookies/siteVisitCookie"; import { logger } from "@/utils/core/Logger"; import { World } from "@/world/World"; -export function HomePage(): React.JSX.Element { +export function HomePage(): React.JSX.Element | null { const navigate = useNavigate(); const introStep = useGameStore((state) => state.intro.currentStep); const setIntroStep = useGameStore((state) => state.setIntroStep); - - useEffect(() => { - if (!hasSiteBeenVisitedToday()) { - navigate({ to: "/site", replace: true }); - } - }, [navigate]); - const dialogMessage = useGameStore( (state) => state.missionFlow.dialogMessage, ); @@ -38,6 +31,12 @@ export function HomePage(): React.JSX.Element { INITIAL_SCENE_LOADING_STATE, ); + useEffect(() => { + if (!hasSiteBeenVisitedToday()) { + navigate({ to: "/site", replace: true }); + } + }, [navigate]); + useEffect(() => { if (!dialogMessage) return undefined; @@ -98,6 +97,13 @@ export function HomePage(): React.JSX.Element { [], ); + // Don't mount the Canvas until we know we will not redirect to /site. + // Without this guard the Canvas would mount, the effect above would fire + // navigate, and the Canvas would unmount mid-load — leaking GLTF requests + // and a WebGL context. The synchronous cookie check happens here AFTER + // all hooks (rules of hooks) but BEFORE any expensive render. + if (!hasSiteBeenVisitedToday()) return null; + const renderIntroOverlay = () => { switch (introStep) { case "video": diff --git a/src/world/GameMap.tsx b/src/world/GameMap.tsx index aee0ee8..33048e5 100644 --- a/src/world/GameMap.tsx +++ b/src/world/GameMap.tsx @@ -175,7 +175,7 @@ export function GameMap({ sceneData.mapNodes.length - visibleMapNodes.length; if (skippedMapNodeCount > 0) { - logger.warn("GameMap", "Lite map skipped heavy map nodes", { + logger.info("GameMap", "Lite map skipped heavy map nodes", { skippedMapNodeCount, }); }