diff --git a/src/app/canvas/page.tsx b/src/app/canvas/page.tsx
new file mode 100644
index 00000000..614abdfe
--- /dev/null
+++ b/src/app/canvas/page.tsx
@@ -0,0 +1,117 @@
+"use client";
+
+import { Suspense, useEffect, useState } from "react";
+import { ReactFlowProvider } from "@xyflow/react";
+import { Header } from "@/components/Header";
+import { WorkflowCanvas } from "@/components/WorkflowCanvas";
+import { FloatingActionBar } from "@/components/FloatingActionBar";
+import { AnnotationModal } from "@/components/AnnotationModal";
+import { PopiaiEmbedBridge } from "@/components/PopiaiEmbedBridge";
+import { useWorkflowStore } from "@/store/workflowStore";
+import { FTUXModal } from "@/components/onboarding/FTUXModal";
+import { getFTUXCompleted, setFTUXCompleted } from "@/store/utils/localStorage";
+import { useFTUXStore } from "@/store/ftuxStore";
+import { useSearchParams } from "next/navigation";
+import { getStoredLoginToken, useUserStore } from "@/store/userStore";
+import { installAuthFetchInterceptor } from "@/utils/authFetch";
+import { useModelStore } from "@/store/modelStore";
+import { isPopiProviderMode } from "@/lib/providerMode";
+import { LoginModal } from "@/components/auth/LoginModal";
+
+if (typeof window !== "undefined") {
+ installAuthFetchInterceptor();
+}
+
+function CanvasPageContent() {
+ const initializeAutoSave = useWorkflowStore(
+ (state) => state.initializeAutoSave
+ );
+ const cleanupAutoSave = useWorkflowStore((state) => state.cleanupAutoSave);
+ const setShowQuickstart = useWorkflowStore((state) => state.setShowQuickstart);
+ const fetchUserInfo = useUserStore((state) => state.fetchUserInfo);
+ const initializePopiModels = useModelStore((state) => state.initializePopiModels);
+ const [showFTUX, setShowFTUX] = useState(false);
+
+ const searchParams = useSearchParams();
+ const token = searchParams.get("token") || '';
+
+ useEffect(() => {
+ if (token || getStoredLoginToken()) {
+ void fetchUserInfo(token, { forceRefresh: true });
+ }
+ }, [fetchUserInfo, token]);
+
+ useEffect(() => {
+ if (!isPopiProviderMode()) return;
+ void initializePopiModels();
+ }, [initializePopiModels]);
+
+ useEffect(() => {
+ initializeAutoSave();
+ return () => cleanupAutoSave();
+ }, [initializeAutoSave, cleanupAutoSave]);
+
+ useEffect(() => {
+ const handleBeforeUnload = (e: BeforeUnloadEvent) => {
+ if (useWorkflowStore.getState().hasUnsavedChanges) {
+ e.preventDefault();
+ }
+ };
+ window.addEventListener("beforeunload", handleBeforeUnload);
+ return () => window.removeEventListener("beforeunload", handleBeforeUnload);
+ }, []);
+
+ // Client-side only FTUX check (SSR-safe)
+ useEffect(() => {
+ const isPopiaiEmbed = new URLSearchParams(window.location.search).get("embed") === "popiai";
+ if (isPopiaiEmbed) {
+ setShowFTUX(false);
+ setShowQuickstart(false);
+ useFTUXStore.getState().resetTutorial();
+ return;
+ }
+
+ if (!getFTUXCompleted()) {
+ setShowFTUX(true);
+ }
+ }, [setShowQuickstart]);
+
+ const handleFTUXComplete = () => {
+ setShowFTUX(false);
+ setFTUXCompleted(true);
+ };
+
+ const handleStartTutorial = () => {
+ setShowFTUX(false);
+ setFTUXCompleted(true);
+ setShowQuickstart(false); // Close WelcomeModal if open
+ useFTUXStore.getState().startTutorial();
+ };
+
+ return (
+