From d6a80224b680eb5cab5eec59133b121b6e2cb773 Mon Sep 17 00:00:00 2001 From: Lum1104 Date: Fri, 3 Apr 2026 11:49:00 +0800 Subject: [PATCH] feat: add live demo dashboard on GitHub Pages Add a demo mode to the dashboard that fetches graph data from Supabase Storage instead of the local Vite dev server, bypasses the token gate, and deploys alongside the homepage at /Understand-Anything/demo/. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/deploy-homepage.yml | 17 ++++++++- homepage/src/components/Hero.astro | 19 ++++++++++ .../packages/dashboard/package.json | 1 + .../packages/dashboard/src/App.tsx | 36 ++++++++++++++----- .../packages/dashboard/vite.config.demo.ts | 22 ++++++++++++ 5 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 understand-anything-plugin/packages/dashboard/vite.config.demo.ts diff --git a/.github/workflows/deploy-homepage.yml b/.github/workflows/deploy-homepage.yml index 2a12343..d6df0d9 100644 --- a/.github/workflows/deploy-homepage.yml +++ b/.github/workflows/deploy-homepage.yml @@ -5,6 +5,8 @@ on: branches: [main] paths: - 'homepage/**' + - 'understand-anything-plugin/packages/dashboard/**' + - 'understand-anything-plugin/packages/core/**' - '.github/workflows/deploy-homepage.yml' workflow_dispatch: @@ -34,10 +36,23 @@ jobs: - name: Install dependencies run: pnpm install - - name: Build + - name: Build homepage working-directory: homepage run: pnpm build + - name: Build core + run: pnpm --filter @understand-anything/core build + + - name: Build demo dashboard + run: pnpm --filter @understand-anything/dashboard build:demo + env: + VITE_GRAPH_URL: ${{ vars.DEMO_GRAPH_URL }} + VITE_DOMAIN_GRAPH_URL: ${{ vars.DEMO_DOMAIN_GRAPH_URL }} + VITE_META_URL: ${{ vars.DEMO_META_URL }} + + - name: Merge demo into homepage output + run: cp -r understand-anything-plugin/packages/dashboard/dist homepage/dist/demo + - uses: actions/upload-pages-artifact@v3 with: path: homepage/dist diff --git a/homepage/src/components/Hero.astro b/homepage/src/components/Hero.astro index d13a170..7844618 100644 --- a/homepage/src/components/Hero.astro +++ b/homepage/src/components/Hero.astro @@ -15,6 +15,7 @@ const githubUrl = 'https://github.com/Lum1104/Understand-Anything';

Get Started + Live Demo → View on GitHub → @@ -107,6 +108,24 @@ const githubUrl = 'https://github.com/Lum1104/Understand-Anything'; transform: translateY(-2px); } + .hero-demo { + border: 1.5px solid var(--accent); + color: var(--accent); + padding: 0.85rem 2.5rem; + border-radius: 8px; + font-weight: 600; + font-size: 1.1rem; + text-decoration: none; + transition: background 0.3s ease, box-shadow 0.3s ease, transform 0.2s ease; + } + + .hero-demo:hover { + background: rgba(212, 165, 116, 0.1); + box-shadow: 0 0 20px var(--accent-glow); + transform: translateY(-2px); + text-decoration: none; + } + .hero-secondary { color: var(--text-muted); font-size: 1rem; diff --git a/understand-anything-plugin/packages/dashboard/package.json b/understand-anything-plugin/packages/dashboard/package.json index 960000c..b9bdbe4 100644 --- a/understand-anything-plugin/packages/dashboard/package.json +++ b/understand-anything-plugin/packages/dashboard/package.json @@ -6,6 +6,7 @@ "scripts": { "dev": "vite", "build": "tsc -b && vite build", + "build:demo": "tsc -b && vite build --config vite.config.demo.ts", "preview": "vite preview" }, "dependencies": { diff --git a/understand-anything-plugin/packages/dashboard/src/App.tsx b/understand-anything-plugin/packages/dashboard/src/App.tsx index d3d472d..c6e262e 100644 --- a/understand-anything-plugin/packages/dashboard/src/App.tsx +++ b/understand-anything-plugin/packages/dashboard/src/App.tsx @@ -24,13 +24,31 @@ import { ThemeProvider } from "./themes/index.ts"; import { ThemePicker } from "./components/ThemePicker.tsx"; import type { ThemeConfig } from "./themes/index.ts"; +const DEMO_MODE = import.meta.env.VITE_DEMO_MODE === "true"; const SESSION_TOKEN_KEY = "understand-anything-token"; +/** Resolve data file URL — in demo mode, use env var URLs; otherwise use local paths with token. */ +function dataUrl(fileName: string, token: string | null): string { + if (DEMO_MODE) { + const envMap: Record = { + "knowledge-graph.json": import.meta.env.VITE_GRAPH_URL, + "domain-graph.json": import.meta.env.VITE_DOMAIN_GRAPH_URL, + "meta.json": import.meta.env.VITE_META_URL, + "diff-overlay.json": import.meta.env.VITE_DIFF_OVERLAY_URL, + }; + const url = envMap[fileName]; + if (url) return url; + } + const path = `/${fileName}`; + return token ? `${path}?token=${encodeURIComponent(token)}` : path; +} + /** * Resolve the access token from the URL query string or sessionStorage. * If found in the URL, persist to sessionStorage and strip the param from the address bar. */ function resolveInitialToken(): string | null { + if (DEMO_MODE) return "__demo__"; const params = new URLSearchParams(window.location.search); const urlToken = params.get("token"); if (urlToken) { @@ -46,11 +64,6 @@ function resolveInitialToken(): string | null { return sessionStorage.getItem(SESSION_TOKEN_KEY); } -/** Build a URL with the token query param appended. */ -function tokenUrl(path: string, token: string | null): string { - return token ? `${path}?token=${encodeURIComponent(token)}` : path; -} - function App() { const [accessToken, setAccessToken] = useState(resolveInitialToken); @@ -59,6 +72,11 @@ function App() { setAccessToken(token); }, []); + // In demo mode, skip token gate entirely + if (DEMO_MODE) { + return ; + } + // Show the token gate when no token is available if (accessToken === null) { return ; @@ -90,7 +108,7 @@ function Dashboard({ accessToken }: { accessToken: string }) { const setDomainGraph = useDashboardStore((s) => s.setDomainGraph); useEffect(() => { - fetch(tokenUrl("/meta.json", accessToken)) + fetch(dataUrl("meta.json", accessToken)) .then((r) => (r.ok ? r.json() : null)) .then((meta) => { if (meta?.theme) setMetaTheme(meta.theme); @@ -215,7 +233,7 @@ function Dashboard({ accessToken }: { accessToken: string }) { useKeyboardShortcuts(shortcuts); useEffect(() => { - fetch(tokenUrl("/knowledge-graph.json", accessToken)) + fetch(dataUrl("knowledge-graph.json", accessToken)) .then((res) => res.json()) .then((data: unknown) => { const result = validateGraph(data); @@ -244,7 +262,7 @@ function Dashboard({ accessToken }: { accessToken: string }) { }, [setGraph]); useEffect(() => { - fetch(tokenUrl("/diff-overlay.json", accessToken)) + fetch(dataUrl("diff-overlay.json", accessToken)) .then((res) => { if (!res.ok) return null; return res.json(); @@ -270,7 +288,7 @@ function Dashboard({ accessToken }: { accessToken: string }) { }, [setDiffOverlay]); useEffect(() => { - fetch(tokenUrl("/domain-graph.json", accessToken)) + fetch(dataUrl("domain-graph.json", accessToken)) .then((res) => { if (!res.ok) return null; return res.json(); diff --git a/understand-anything-plugin/packages/dashboard/vite.config.demo.ts b/understand-anything-plugin/packages/dashboard/vite.config.demo.ts new file mode 100644 index 0000000..aa616bc --- /dev/null +++ b/understand-anything-plugin/packages/dashboard/vite.config.demo.ts @@ -0,0 +1,22 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import tailwindcss from "@tailwindcss/vite"; +import path from "path"; + +export default defineConfig({ + base: "/Understand-Anything/demo/", + + resolve: { + alias: { + "@understand-anything/core/schema": path.resolve(__dirname, "../core/dist/schema.js"), + "@understand-anything/core/search": path.resolve(__dirname, "../core/dist/search.js"), + "@understand-anything/core/types": path.resolve(__dirname, "../core/dist/types.js"), + }, + }, + + define: { + "import.meta.env.VITE_DEMO_MODE": JSON.stringify("true"), + }, + + plugins: [react(), tailwindcss()], +});