From 5b56ad2a42e94480c1aa33dec26aa886ecc28f3a Mon Sep 17 00:00:00 2001 From: Satya Patel Date: Mon, 2 Feb 2026 13:42:42 -0800 Subject: [PATCH 1/2] feat(desktop): new user landing screen without sidebar or topbar Show a clean onboarding layout when user has no projects. All navigations in the onboarding flow use history.replace so setup screens never appear in back-button history. --- apps/desktop/package.json | 2 +- .../workspaces/useCreateWorkspace.ts | 2 +- .../_dashboard/workspace/page.tsx | 10 +++++--- .../_authenticated/_onboarding/layout.tsx | 24 +++++++++++++++++++ .../_onboarding/welcome/page.tsx | 10 ++++++++ .../main/components/StartView/index.tsx | 2 ++ bun.lock | 12 ++++------ 7 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 apps/desktop/src/renderer/routes/_authenticated/_onboarding/layout.tsx create mode 100644 apps/desktop/src/renderer/routes/_authenticated/_onboarding/welcome/page.tsx diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 075a352a749..8ae691b2388 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -136,7 +136,7 @@ "os-locale": "^6.0.2", "pidtree": "^0.6.0", "posthog-js": "1.310.1", - "posthog-node": "^5.18.0", + "posthog-node": "^5.24.7", "react": "19.1.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", diff --git a/apps/desktop/src/renderer/react-query/workspaces/useCreateWorkspace.ts b/apps/desktop/src/renderer/react-query/workspaces/useCreateWorkspace.ts index 0ce161cce51..db41bf4ee0b 100644 --- a/apps/desktop/src/renderer/react-query/workspaces/useCreateWorkspace.ts +++ b/apps/desktop/src/renderer/react-query/workspaces/useCreateWorkspace.ts @@ -43,7 +43,7 @@ export function useCreateWorkspace(options?: UseCreateWorkspaceOptions) { await utils.workspaces.invalidate(); if (!options?.skipNavigation) { - navigateToWorkspace(data.workspace.id, navigate); + navigateToWorkspace(data.workspace.id, navigate, { replace: true }); } await options?.onSuccess?.(data, ...rest); diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/page.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/page.tsx index bcff6cb939b..46e876084de 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/page.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/page.tsx @@ -2,7 +2,6 @@ import { Spinner } from "@superset/ui/spinner"; import { createFileRoute, useNavigate } from "@tanstack/react-router"; import { useEffect } from "react"; import { electronTrpc } from "renderer/lib/electron-trpc"; -import { StartView } from "renderer/screens/main/components/StartView"; export const Route = createFileRoute("/_authenticated/_dashboard/workspace/")({ component: WorkspaceIndexPage, @@ -26,7 +25,12 @@ function WorkspaceIndexPage() { useEffect(() => { if (isLoading || !workspaces) return; - if (allWorkspaces.length === 0) return; // Show StartView instead + + if (allWorkspaces.length === 0) { + // Redirect to clean onboarding screen (no sidebar/topbar) + navigate({ to: "/welcome", replace: true }); + return; + } // Try to restore last viewed workspace const lastViewedId = localStorage.getItem("lastViewedWorkspaceId"); @@ -43,7 +47,7 @@ function WorkspaceIndexPage() { }, [workspaces, isLoading, navigate, allWorkspaces]); if (hasNoWorkspaces) { - return ; + return ; } return ; diff --git a/apps/desktop/src/renderer/routes/_authenticated/_onboarding/layout.tsx b/apps/desktop/src/renderer/routes/_authenticated/_onboarding/layout.tsx new file mode 100644 index 00000000000..f594fb62f9e --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/_onboarding/layout.tsx @@ -0,0 +1,24 @@ +import { createFileRoute, Outlet } from "@tanstack/react-router"; +import { electronTrpc } from "renderer/lib/electron-trpc"; + +export const Route = createFileRoute("/_authenticated/_onboarding")({ + component: OnboardingLayout, +}); + +function OnboardingLayout() { + const { data: platform } = electronTrpc.window.getPlatform.useQuery(); + const isMac = platform === undefined || platform === "darwin"; + + return ( +
+ {/* Drag region for window dragging (macOS traffic lights / Windows title bar) */} +
+ +
+ ); +} diff --git a/apps/desktop/src/renderer/routes/_authenticated/_onboarding/welcome/page.tsx b/apps/desktop/src/renderer/routes/_authenticated/_onboarding/welcome/page.tsx new file mode 100644 index 00000000000..64c62b1f98c --- /dev/null +++ b/apps/desktop/src/renderer/routes/_authenticated/_onboarding/welcome/page.tsx @@ -0,0 +1,10 @@ +import { createFileRoute } from "@tanstack/react-router"; +import { StartView } from "renderer/screens/main/components/StartView"; + +export const Route = createFileRoute("/_authenticated/_onboarding/welcome/")({ + component: WelcomePage, +}); + +function WelcomePage() { + return ; +} diff --git a/apps/desktop/src/renderer/screens/main/components/StartView/index.tsx b/apps/desktop/src/renderer/screens/main/components/StartView/index.tsx index 7066c0599fa..ec2b30ccdc6 100644 --- a/apps/desktop/src/renderer/screens/main/components/StartView/index.tsx +++ b/apps/desktop/src/renderer/screens/main/components/StartView/index.tsx @@ -66,6 +66,7 @@ export function StartView() { navigate({ to: "/project/$projectId", params: { projectId: result.project.id }, + replace: true, }); } }, @@ -154,6 +155,7 @@ export function StartView() { navigate({ to: "/project/$projectId", params: { projectId: result.project.id }, + replace: true, }); } }, diff --git a/bun.lock b/bun.lock index 6f2951b2eca..3116ab31ee7 100644 --- a/bun.lock +++ b/bun.lock @@ -131,7 +131,7 @@ }, "apps/desktop": { "name": "@superset/desktop", - "version": "0.0.64", + "version": "0.0.65", "dependencies": { "@better-auth/stripe": "1.4.17", "@dnd-kit/core": "^6.3.1", @@ -236,7 +236,7 @@ "os-locale": "^6.0.2", "pidtree": "^0.6.0", "posthog-js": "1.310.1", - "posthog-node": "^5.18.0", + "posthog-node": "^5.24.7", "react": "19.1.0", "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", @@ -4073,7 +4073,7 @@ "posthog-js": ["posthog-js@1.310.1", "", { "dependencies": { "@posthog/core": "1.9.0", "core-js": "^3.38.1", "fflate": "^0.4.8", "preact": "^10.19.3", "web-vitals": "^4.2.4" } }, "sha512-UkR6zzlWNtqHDXHJl2Yk062DOmZyVKTPL5mX4j4V+u3RiYbMHJe47+PpMMUsvK1R2e1r/m9uSlHaJMJRzyUjGg=="], - "posthog-node": ["posthog-node@5.24.2", "", { "dependencies": { "@posthog/core": "1.14.0" } }, "sha512-cywIUYtSIC9BilgLlZd1R2xNk6omKL6tywG/SCPmUJKeG2jhjvJHSrHXYx4x3uQsUjn8aB9UVI8km+W326Zm8g=="], + "posthog-node": ["posthog-node@5.24.7", "", { "dependencies": { "@posthog/core": "1.17.0" } }, "sha512-IJ0Zj+v+eg/JQMZ75n0Hcp4NzuQzWcZjqFjcUQs6RhW2l5FiQIq09sKJMleXX33hYxD6sfjFsDTqugJlgeAohg=="], "posthog-react-native": ["posthog-react-native@4.24.0", "", { "dependencies": { "@posthog/core": "1.14.0" }, "peerDependencies": { "@react-native-async-storage/async-storage": ">=1.0.0", "@react-navigation/native": ">= 5.0.0", "expo-application": ">= 4.0.0", "expo-device": ">= 4.0.0", "expo-file-system": ">= 13.0.0", "expo-localization": ">= 11.0.0", "posthog-react-native-session-replay": ">= 1.2.0", "react-native-device-info": ">= 10.0.0", "react-native-localize": ">= 3.0.0", "react-native-navigation": ">= 6.0.0", "react-native-safe-area-context": ">= 4.0.0", "react-native-svg": ">= 15.0.0" }, "optionalPeers": ["@react-native-async-storage/async-storage", "@react-navigation/native", "expo-application", "expo-device", "expo-file-system", "expo-localization", "posthog-react-native-session-replay", "react-native-device-info", "react-native-localize", "react-native-navigation", "react-native-safe-area-context"] }, "sha512-VHRVuLGdoPSeIPcE4Nnzekm1a7iAcG+j4aG/lzEJOhLGNbwysYR3l+3ZKftyO+XAeq+2nY+er3d5GSGozVRfsA=="], @@ -5235,8 +5235,6 @@ "@slack/web-api/eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], - "@superset/web/posthog-node": ["posthog-node@5.24.7", "", { "dependencies": { "@posthog/core": "1.17.0" } }, "sha512-IJ0Zj+v+eg/JQMZ75n0Hcp4NzuQzWcZjqFjcUQs6RhW2l5FiQIq09sKJMleXX33hYxD6sfjFsDTqugJlgeAohg=="], - "@tailwindcss/node/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], @@ -5571,7 +5569,7 @@ "postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - "posthog-node/@posthog/core": ["@posthog/core@1.14.0", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-havjGYHwL8Gy6LXIR911h+M/sYlJLQbepxP/cc1M7Cp3v8F92bzpqkbuvUIUyb7/izkxfGwc9wMqKAo0QxMTrg=="], + "posthog-node/@posthog/core": ["@posthog/core@1.17.0", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-8pDNL+/u9ojzXloA5wILVDXBCV5daJ7w2ipCALQlEEZmL752cCKhRpbyiHn3tjKXh3Hy6aOboJneYa1JdlVHrQ=="], "posthog-react-native/@posthog/core": ["@posthog/core@1.14.0", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-havjGYHwL8Gy6LXIR911h+M/sYlJLQbepxP/cc1M7Cp3v8F92bzpqkbuvUIUyb7/izkxfGwc9wMqKAo0QxMTrg=="], @@ -5983,8 +5981,6 @@ "@sentry/react/@sentry/browser/@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@10.36.0", "", { "dependencies": { "@sentry-internal/replay": "10.36.0", "@sentry/core": "10.36.0" } }, "sha512-DLGIwmT2LX+O6TyYPtOQL5GiTm2rN0taJPDJ/Lzg2KEJZrdd5sKkzTckhh2x+vr4JQyeaLmnb8M40Ch1hvG/vQ=="], - "@superset/web/posthog-node/@posthog/core": ["@posthog/core@1.17.0", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-8pDNL+/u9ojzXloA5wILVDXBCV5daJ7w2ipCALQlEEZmL752cCKhRpbyiHn3tjKXh3Hy6aOboJneYa1JdlVHrQ=="], - "@tanstack/router-plugin/unplugin/webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], "@uiw/react-markdown-preview/rehype-prism-plus/refractor": ["refractor@4.9.0", "", { "dependencies": { "@types/hast": "^2.0.0", "@types/prismjs": "^1.0.0", "hastscript": "^7.0.0", "parse-entities": "^4.0.0" } }, "sha512-nEG1SPXFoGGx+dcjftjv8cAjEusIh6ED1xhf5DG3C0x/k+rmZ2duKnc3QLpt6qeHv5fPb8uwN3VWN2BT7fr3Og=="], From 4e0c2fa6fd4a4965e8c234574760702cc4489d8e Mon Sep 17 00:00:00 2001 From: Satya Patel Date: Mon, 2 Feb 2026 19:30:50 -0800 Subject: [PATCH 2/2] WIP --- .../components/StartView/CloneRepoDialog.tsx | 107 +++++++++--------- .../main/components/StartView/index.tsx | 71 ++++++------ 2 files changed, 83 insertions(+), 95 deletions(-) diff --git a/apps/desktop/src/renderer/screens/main/components/StartView/CloneRepoDialog.tsx b/apps/desktop/src/renderer/screens/main/components/StartView/CloneRepoDialog.tsx index 2babbe0ca72..8d7012064cc 100644 --- a/apps/desktop/src/renderer/screens/main/components/StartView/CloneRepoDialog.tsx +++ b/apps/desktop/src/renderer/screens/main/components/StartView/CloneRepoDialog.tsx @@ -1,3 +1,13 @@ +import { Button } from "@superset/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@superset/ui/dialog"; +import { Input } from "@superset/ui/input"; import { useState } from "react"; import { electronTrpc } from "renderer/lib/electron-trpc"; import { useCreateWorkspace } from "renderer/react-query/workspaces"; @@ -18,6 +28,8 @@ export function CloneRepoDialog({ const cloneRepo = electronTrpc.projects.cloneRepo.useMutation(); const createWorkspace = useCreateWorkspace(); + const isLoading = cloneRepo.isPending || createWorkspace.isPending; + const handleClone = async () => { if (!url.trim()) { onError("Please enter a repository URL"); @@ -28,19 +40,16 @@ export function CloneRepoDialog({ { url: url.trim() }, { onSuccess: (result) => { - // User canceled the directory picker - silent no-op if (result.canceled) { return; } if (result.success && result.project) { - // Invalidate recents so the new/updated project appears utils.projects.getRecents.invalidate(); createWorkspace.mutate({ projectId: result.project.id }); onClose(); setUrl(""); } else if (!result.success) { - // Show user-friendly error message onError(result.error ?? "Failed to clone repository"); } }, @@ -51,61 +60,47 @@ export function CloneRepoDialog({ ); }; - if (!isOpen) return null; - - const isLoading = cloneRepo.isPending || createWorkspace.isPending; - return ( -
-
-

- Clone Repository -

- -
-
- - setUrl(e.target.value)} - placeholder="https://github.com/user/repo.git" - className="w-full px-3 py-2.5 bg-background border border-border rounded-md text-foreground placeholder:text-muted-foreground/50 focus:outline-none focus:border-ring transition-colors" - disabled={isLoading} - onKeyDown={(e) => { - if (e.key === "Enter" && !isLoading) { - handleClone(); - } - }} - /> -
+ !open && onClose()}> + + + Clone Repository + + Enter a repository URL to clone it locally. + + -
- - -
+
+ + setUrl(e.target.value)} + placeholder="https://github.com/user/repo.git" + disabled={isLoading} + onKeyDown={(e) => { + if (e.key === "Enter" && !isLoading) { + handleClone(); + } + }} + autoFocus + />
-
-
+ + + + + + + ); } diff --git a/apps/desktop/src/renderer/screens/main/components/StartView/index.tsx b/apps/desktop/src/renderer/screens/main/components/StartView/index.tsx index ec2b30ccdc6..8fe049ea023 100644 --- a/apps/desktop/src/renderer/screens/main/components/StartView/index.tsx +++ b/apps/desktop/src/renderer/screens/main/components/StartView/index.tsx @@ -1,3 +1,4 @@ +import { Button } from "@superset/ui/button"; import { cn } from "@superset/ui/utils"; import { useNavigate } from "@tanstack/react-router"; import { useCallback, useEffect, useState } from "react"; @@ -181,89 +182,81 @@ export function StartView() { onDragLeave={handleDragLeave} onDrop={handleDrop} > -
+
-
+
-

- Any folder with a .git directory -

- + + Don't have a local repo? + + +
{error && !isDragOver && ( -
- {error} +
+ {error}
)}