Skip to content

Commit ee208b9

Browse files
authored
Merge pull request #148 from alibaba/feat/drop-hash-router
feat(website): drop hash route; upgrade styling
2 parents 5f74f98 + 6ad20c8 commit ee208b9

File tree

31 files changed

+533
-336
lines changed

31 files changed

+533
-336
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ The GUI Agent Living in Your Webpage. Control web interfaces with natural langua
1111

1212
🌐 **English** | [中文](./docs/README-zh.md)
1313

14-
👉 <a href="https://alibaba.github.io/page-agent/" target="_blank"><b>🚀 Demo</b></a> | <a href="https://alibaba.github.io/page-agent/#/docs/introduction/overview" target="_blank"><b>📖 Documentation</b></a>
14+
👉 <a href="https://alibaba.github.io/page-agent/" target="_blank"><b>🚀 Demo</b></a> | <a href="https://alibaba.github.io/page-agent/docs/introduction/overview" target="_blank"><b>📖 Documentation</b></a>
1515

1616
<video id="demo-video" src="https://github.com/user-attachments/assets/34d8444d-cbfb-44a3-a24e-fd5c167bb0bf" controls crossorigin muted></video>
1717

@@ -28,14 +28,14 @@ The GUI Agent Living in Your Webpage. Control web interfaces with natural langua
2828
- No special permissions required.
2929
- **🧠 Bring your own LLMs**
3030
- **🎨 Pretty UI with human-in-the-loop**
31-
- **🐙 Optional [chrome extension](https://alibaba.github.io/page-agent/#/docs/features/chrome-extension) for multi-page tasks.**
31+
- **🐙 Optional [chrome extension](https://alibaba.github.io/page-agent/docs/features/chrome-extension) for multi-page tasks.**
3232

3333
## 💡 Use Cases
3434

3535
- **SaaS AI Copilot** — Ship an AI copilot in your product in lines of code. No backend rewrite needed.
3636
- **Smart Form Filling** — Turn 20-click workflows into one sentence. Perfect for ERP, CRM, and admin systems.
3737
- **Accessibility** — Make any web app accessible through natural language. Voice commands, screen readers, zero barrier.
38-
- **Multi-page Agent** — Extend your agent's reach across browser tabs with the optional [chrome extension](https://alibaba.github.io/page-agent/#/docs/features/chrome-extension).
38+
- **Multi-page Agent** — Extend your agent's reach across browser tabs with the optional [chrome extension](https://alibaba.github.io/page-agent/docs/features/chrome-extension).
3939

4040
## 🚀 Quick Start
4141

@@ -73,7 +73,7 @@ const agent = new PageAgent({
7373
await agent.execute('Click the login button')
7474
```
7575

76-
For more programmatic usage, see [📖 Documentations](https://alibaba.github.io/page-agent/#/docs/introduction/overview).
76+
For more programmatic usage, see [📖 Documentations](https://alibaba.github.io/page-agent/docs/introduction/overview).
7777

7878
## 🤝 Contributing
7979

docs/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ interface PageAgentConfig {
146146
- Single-page application only (cannot navigate across pages)
147147
- No visual recognition (relies on DOM structure)
148148
- Limited interaction support (no hover, drag-drop, canvas operations)
149-
- See [Limitations](https://alibaba.github.io/page-agent/#/docs/introduction/limitations) for details
149+
- See [Limitations](https://alibaba.github.io/page-agent/docs/introduction/limitations) for details
150150

151151
### Acknowledgments
152152

docs/README-zh.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
🌐 [English](../README.md) | **中文**
1313

14-
👉 <a href="https://alibaba.github.io/page-agent/" target="_blank"><b>🚀 Demo</b></a> | <a href="https://alibaba.github.io/page-agent/#/docs/introduction/overview" target="_blank"><b>📖 Documentation</b></a>
14+
👉 <a href="https://alibaba.github.io/page-agent/" target="_blank"><b>🚀 Demo</b></a> | <a href="https://alibaba.github.io/page-agent/docs/introduction/overview" target="_blank"><b>📖 Documentation</b></a>
1515

1616
<video id="demo-video" src="https://github.com/user-attachments/assets/34d8444d-cbfb-44a3-a24e-fd5c167bb0bf" controls crossorigin muted></video>
1717

@@ -28,14 +28,14 @@
2828
- 无需特殊权限。
2929
- **🧠 用你自己的 LLM**
3030
- **🎨 精美 UI,支持人机协同**
31-
- **🐙 可选的 [Chrome 扩展](https://alibaba.github.io/page-agent/#/docs/features/chrome-extension),支持跨页面任务。**
31+
- **🐙 可选的 [Chrome 扩展](https://alibaba.github.io/page-agent/docs/features/chrome-extension),支持跨页面任务。**
3232

3333
## 💡 应用场景
3434

3535
- **SaaS AI 副驾驶** — 几行代码为你的产品加上 AI 副驾驶,不需要重写后端。
3636
- **智能表单填写** — 把 20 次点击变成一句话。ERP、CRM、管理后台的最佳拍档。
3737
- **无障碍增强** — 用自然语言让任何网页无障碍。语音指令、屏幕阅读器,零门槛。
38-
- **跨页面 Agent** — 通过可选的 [Chrome 扩展](https://alibaba.github.io/page-agent/#/docs/features/chrome-extension),让你的 Agent 跨标签页工作。
38+
- **跨页面 Agent** — 通过可选的 [Chrome 扩展](https://alibaba.github.io/page-agent/docs/features/chrome-extension),让你的 Agent 跨标签页工作。
3939

4040
## 🚀 快速开始
4141

@@ -73,7 +73,7 @@ const agent = new PageAgent({
7373
await agent.execute('点击登录按钮')
7474
```
7575

76-
更多编程用法,请参阅 [📖 文档](https://alibaba.github.io/page-agent/#/docs/introduction/overview)
76+
更多编程用法,请参阅 [📖 文档](https://alibaba.github.io/page-agent/docs/introduction/overview)
7777

7878
## 🤝 贡献
7979

packages/extension/src/entrypoints/sidepanel/components/misc.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export function EmptyState() {
125125
</svg>
126126
</a>
127127
<a
128-
href="https://alibaba.github.io/page-agent/#/docs/features/chrome-extension"
128+
href="https://alibaba.github.io/page-agent/docs/features/chrome-extension"
129129
target="_blank"
130130
rel="noopener noreferrer"
131131
className="hover:text-foreground transition-colors"

packages/llms/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export function parseLLMConfig(config: LLMConfig): Required<LLMConfig> {
1111
if (!config.baseURL || !config.apiKey || !config.model) {
1212
throw new Error(
1313
'[PageAgent] LLM configuration required. Please provide: baseURL, apiKey, model. ' +
14-
'See: https://alibaba.github.io/page-agent/#/docs/features/models'
14+
'See: https://alibaba.github.io/page-agent/docs/features/models'
1515
)
1616
}
1717

packages/website/AGENTS.md

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
- **React** with TypeScript
66
- **Vite** for dev server and build
77
- **Tailwind CSS** for styling
8-
- **shadcn/ui** (new-york style) for UI components
8+
- **shadcn/ui** (new-york style) for UI components**do NOT hand-edit `src/components/ui/` files**
99
- **Magic UI** for animations and effects
10-
- **wouter** with hash routing for static hosting
10+
- **wouter** with browser routing (`base: "/page-agent"`)
1111
- **lucide-react** for icons
1212

1313
## Component Guidelines
@@ -53,58 +53,74 @@ Located in `src/components/ui/`:
5353
### Styling Rules
5454

5555
1. **Prefer Tailwind classes** over custom CSS
56-
2. Use CSS modules only for complex component-specific styles
57-
3. Support dark mode via `dark:` classes
58-
4. Use CSS variables from `src/index.css` for theme colors
56+
2. Support dark mode via `dark:` classes
57+
3. Use CSS variables from `src/index.css` for theme colors
5958

6059
## Project Structure
6160

6261
```
6362
src/
6463
├── pages/
65-
│ ├── Home.tsx # Homepage
64+
│ ├── home/
65+
│ │ ├── HomeContent.tsx # Homepage sections
66+
│ │ └── ...Section.tsx
6667
│ └── docs/
67-
│ ├── Layout.tsx # Documentation sidebar
68+
│ ├── index.tsx # Docs route switch
69+
│ ├── Layout.tsx # Sidebar navigation
6870
│ └── [section]/[topic]/page.tsx
6971
├── components/
70-
│ ├── ui/ # shadcn/ui + Magic UI components
72+
│ ├── ui/ # shadcn/ui + Magic UI (DO NOT hand-edit)
73+
│ ├── Heading.tsx # Anchor heading for doc pages
7174
│ ├── Header.tsx # Site header
7275
│ └── Footer.tsx # Site footer
7376
├── i18n/ # Internationalization
74-
├── router.tsx # Central routing
77+
├── router.tsx # Root layout + routing
7578
└── main.tsx # App entry
7679
```
7780

78-
## Adding New Pages
81+
## Routing
7982

80-
### Documentation Page
83+
Uses wouter browser routing with base path for GitHub Pages deployment at `https://alibaba.github.io/page-agent/`.
8184

82-
1. Create `src/pages/docs/<section>/<slug>/page.tsx`
83-
2. Add route to `src/router.tsx` with `<Header /> + <DocsLayout>` wrapper
84-
3. Add navigation item to `pages/docs/Layout.tsx`
85+
```tsx
86+
// main.tsx
87+
<Router base="/page-agent">
88+
<PagesRouter />
89+
</Router>
90+
```
8591

86-
## Routing
92+
**Key rules:**
8793

88-
Uses hash-based routing for static hosting:
94+
- Header and Footer live in `router.tsx` **outside** `<Switch>`, so they always see the root router context (`base="/page-agent"`)
95+
- Docs pages are nested via `<Route path="/docs" nest>`, which creates a child context (`base="/page-agent/docs"`)
96+
- Inside the docs nest, Link hrefs are relative to `/docs` (e.g. `href="/features/models"`, NOT `href="/docs/features/models"`)
97+
- **Never use `~` prefix** in Link hrefs — it bypasses the base path entirely
98+
- Doc page headings use `<Heading id="slug" level={2}>` for anchor links
8999

90-
```tsx
91-
import { Router } from 'wouter'
92-
import { useHashLocation } from 'wouter/use-hash-location'
100+
### SPA on GitHub Pages
93101

94-
;<Router hook={useHashLocation}>{/* routes */}</Router>
95-
```
102+
Instead of `404.html` redirects, the build copies `index.html` into every route directory. Add new routes to the `SPA_ROUTES` array in `vite.config.js`.
103+
104+
## Adding New Pages
105+
106+
### Documentation Page
107+
108+
1. Create `src/pages/docs/<section>/<slug>/page.tsx`
109+
2. Add route in `src/pages/docs/index.tsx`
110+
3. Add navigation item in `src/pages/docs/Layout.tsx`
111+
4. Add path to `SPA_ROUTES` in `vite.config.js`
96112

97113
## Configuration Files
98114

99115
| File | Purpose |
100116
| ----------------- | ----------------------- |
101117
| `components.json` | shadcn/ui configuration |
102-
| `vite.config.js` | Vite build settings |
118+
| `vite.config.js` | Vite build + SPA routes |
103119
| `tsconfig.json` | TypeScript config |
104120

105121
## Commands
106122

107123
```bash
108-
npm start # Dev server (from root)
124+
npm start # Dev server (from root)
109125
npm run build:website # Build website (from root)
110126
```

packages/website/src/components/Header.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export default function Header() {
2323
<div className="flex items-center justify-between gap-2">
2424
{/* Logo */}
2525
<Link
26-
href="~/"
26+
href="/"
2727
className="flex items-center gap-2 sm:gap-3 group shrink-0"
2828
aria-label={isZh ? 'page-agent 首页' : 'page-agent home'}
2929
onClick={() => setMobileMenuOpen(false)}
@@ -56,7 +56,7 @@ export default function Header() {
5656
aria-label="Mobile navigation"
5757
>
5858
<Link
59-
href="~/docs/introduction/overview"
59+
href="/docs/introduction/overview"
6060
className="p-2 rounded-lg text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200 shrink-0"
6161
aria-label={isZh ? '文档' : 'Docs'}
6262
>
@@ -90,7 +90,7 @@ export default function Header() {
9090
{import.meta.env.VERSION}
9191
</span>
9292
<Link
93-
href="~/docs/introduction/overview"
93+
href="/docs/introduction/overview"
9494
className="flex items-center gap-1.5 text-gray-600 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200"
9595
>
9696
<BookOpen className="w-4 h-4" />
@@ -138,7 +138,7 @@ export default function Header() {
138138
role="navigation"
139139
>
140140
<Link
141-
href="~/docs/introduction/overview"
141+
href="/docs/introduction/overview"
142142
className="flex items-center gap-2 px-3 py-2 rounded-lg text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors duration-200"
143143
onClick={() => setMobileMenuOpen(false)}
144144
>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { ComponentPropsWithoutRef, useEffect, useRef } from 'react'
2+
3+
import { cn } from '@/lib/utils'
4+
5+
type Level = 2 | 3
6+
7+
interface HeadingProps extends Omit<ComponentPropsWithoutRef<'h2'>, 'children'> {
8+
id: string
9+
level?: Level
10+
children: React.ReactNode
11+
}
12+
13+
const levelStyles = {
14+
2: { tag: 'h2', className: 'text-2xl font-semibold mb-4' },
15+
3: { tag: 'h3', className: 'text-xl font-semibold mb-3' },
16+
} as const
17+
18+
export function Heading({ id, level = 2, className, children, ...props }: HeadingProps) {
19+
const ref = useRef<HTMLHeadingElement>(null)
20+
const { tag: Tag, className: defaultClassName } = levelStyles[level]
21+
22+
useEffect(() => {
23+
if (window.location.hash === `#${id}`) {
24+
ref.current?.scrollIntoView({ behavior: 'smooth' })
25+
}
26+
}, [id])
27+
28+
return (
29+
<Tag
30+
ref={ref}
31+
id={id}
32+
className={cn('group relative scroll-mt-20', defaultClassName, className)}
33+
{...props}
34+
>
35+
<a
36+
href={`#${id}`}
37+
className="absolute -left-5 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 text-gray-400 hover:text-blue-500 transition-opacity no-underline"
38+
aria-label={`Link to ${id}`}
39+
>
40+
#
41+
</a>
42+
{children}
43+
</Tag>
44+
)
45+
}

packages/website/src/components/ui/magic-card.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export function MagicCard({
8585
`,
8686
}}
8787
/>
88-
<div className="bg-background absolute inset-px rounded-[inherit]" />
88+
<div className="absolute inset-px rounded-[inherit] bg-white dark:bg-neutral-900" />
8989
<motion.div
9090
className="pointer-events-none absolute inset-px rounded-[inherit] opacity-0 transition-opacity duration-300 group-hover:opacity-100"
9191
style={{

packages/website/src/main.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
import { createRoot } from 'react-dom/client'
22
import { Router } from 'wouter'
3-
import { useHashLocation } from 'wouter/use-hash-location'
43

54
import { LanguageProvider } from './i18n/context'
65
import { default as PagesRouter } from './router'
76

87
import './index.css'
98

9+
// Redirect legacy hash routes (e.g. /#/docs/foo) to clean paths
10+
const { hash } = window.location
11+
if (hash.length > 1 && hash.includes('/')) {
12+
const path = hash.replace(/^#\/?/, '/')
13+
history.replaceState(null, '', '/page-agent' + path)
14+
}
15+
1016
createRoot(document.getElementById('root')!).render(
1117
<LanguageProvider>
12-
<Router hook={useHashLocation}>
18+
<Router base="/page-agent">
1319
<PagesRouter />
1420
</Router>
1521
</LanguageProvider>

0 commit comments

Comments
 (0)