From ca68be7a56f8a09082bdb2f7a45ebbfc23e8cc44 Mon Sep 17 00:00:00 2001 From: Simon <10131203+gaomeng1900@users.noreply.github.com> Date: Thu, 12 Mar 2026 20:01:00 +0800 Subject: [PATCH] feat(website): basic SEO --- packages/website/public/robots.txt | 4 ++++ packages/website/src/lib/useDocumentTitle.ts | 9 +++++++++ packages/website/src/pages/docs/Layout.tsx | 7 +++++++ packages/website/src/pages/home/index.tsx | 4 ++++ packages/website/vite.config.js | 17 ++++++++++++++++- 5 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 packages/website/public/robots.txt create mode 100644 packages/website/src/lib/useDocumentTitle.ts diff --git a/packages/website/public/robots.txt b/packages/website/public/robots.txt new file mode 100644 index 0000000..fa1ce2b --- /dev/null +++ b/packages/website/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://alibaba.github.io/page-agent/sitemap.xml diff --git a/packages/website/src/lib/useDocumentTitle.ts b/packages/website/src/lib/useDocumentTitle.ts new file mode 100644 index 0000000..1e18324 --- /dev/null +++ b/packages/website/src/lib/useDocumentTitle.ts @@ -0,0 +1,9 @@ +import { useEffect } from 'react' + +const DEFAULT_TITLE = 'PageAgent - The GUI Agent Living in Your Webpage' + +export function useDocumentTitle(title?: string) { + useEffect(() => { + document.title = title ? `${title} - PageAgent` : DEFAULT_TITLE + }, [title]) +} diff --git a/packages/website/src/pages/docs/Layout.tsx b/packages/website/src/pages/docs/Layout.tsx index 0a4210f..e9abee8 100644 --- a/packages/website/src/pages/docs/Layout.tsx +++ b/packages/website/src/pages/docs/Layout.tsx @@ -4,6 +4,7 @@ import { Link, useLocation } from 'wouter' import { SparklesText } from '@/components/ui/sparkles-text' import { useLanguage } from '@/i18n/context' +import { useDocumentTitle } from '@/lib/useDocumentTitle' interface DocsLayoutProps { children: ReactNode @@ -65,6 +66,12 @@ export default function DocsLayout({ children }: DocsLayoutProps) { }, ] + const activeTitle = navigationSections + .flatMap((s) => s.items) + .find((item) => item.path === location)?.title + + useDocumentTitle(activeTitle) + return (
diff --git a/packages/website/src/pages/home/index.tsx b/packages/website/src/pages/home/index.tsx index c6589a7..9781e6b 100644 --- a/packages/website/src/pages/home/index.tsx +++ b/packages/website/src/pages/home/index.tsx @@ -1,5 +1,7 @@ import { Suspense, lazy } from 'react' +import { useDocumentTitle } from '@/lib/useDocumentTitle' + import HeroSection from './HeroSection' const FeaturesSection = lazy(() => import('./FeaturesSection')) @@ -7,6 +9,8 @@ const ScenariosSection = lazy(() => import('./ScenariosSection')) const OneMoreThingSection = lazy(() => import('./OneMoreThingSection')) export default function HomePage() { + useDocumentTitle() + return ( <> diff --git a/packages/website/vite.config.js b/packages/website/vite.config.js index d200751..f5cdeec 100644 --- a/packages/website/vite.config.js +++ b/packages/website/vite.config.js @@ -1,7 +1,7 @@ import tailwindcss from '@tailwindcss/vite' import react from '@vitejs/plugin-react-swc' import { config as dotenvConfig } from 'dotenv' -import { copyFileSync, mkdirSync, readFileSync } from 'node:fs' +import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs' import process from 'node:process' import { dirname, join, resolve } from 'path' import { fileURLToPath } from 'url' @@ -35,6 +35,8 @@ const SPA_ROUTES = [ 'docs/advanced/security-permissions', ] +const SITE_URL = 'https://alibaba.github.io/page-agent' + function spaRoutes() { return { name: 'spa-routes', @@ -47,6 +49,19 @@ function spaRoutes() { copyFileSync(src, join(dir, 'index.html')) } console.log(` ✓ Copied index.html to ${SPA_ROUTES.length} SPA routes`) + + const today = new Date().toISOString().split('T')[0] + const urls = ['', ...SPA_ROUTES] + .map( + (route) => + ` \n ${SITE_URL}/${route}\n ${today}\n ` + ) + .join('\n') + writeFileSync( + join(dist, 'sitemap.xml'), + `\n\n${urls}\n\n` + ) + console.log(` ✓ Generated sitemap.xml with ${SPA_ROUTES.length + 1} URLs`) }, } }