browser-preview
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBrowser Preview
浏览器预览
You already know and . This skill fills the gap: what happens after preview_serve returns a URL — how the user actually sees it.
preview_servepreview_stop你已经了解和。本内容填补了空白:当返回URL之后会发生什么——用户实际是如何查看预览的。
preview_servepreview_stoppreview_serveWhat is Browser
什么是Browser
The frontend has a right-side panel with two tabs: Workspace and Browser. Browser renders preview URLs inside an iframe. When you call , the frontend automatically opens a Browser tab loading that URL.
preview_serveKey facts:
- Each call creates one Browser tab
preview_serve - URL format:
https://<host>/preview/{id}/ - Browser panel has a ⋮ menu (top-right) showing "RUNNING SERVICES" list
- Browser tab can be closed by the user without stopping the backend service
- Backend service stopping → Browser tab shows an error page
前端右侧面板有两个标签页:Workspace和Browser。Browser标签页通过iframe渲染预览URL。当你调用时,前端会自动打开加载该URL的Browser标签页。
preview_serve关键信息:
- 每次调用会创建一个Browser标签页
preview_serve - URL格式:
https://<host>/preview/{id}/ - Browser面板右上角有一个**⋮菜单**,显示“RUNNING SERVICES”(运行中的服务)列表
- 用户可以在不停止后端服务的情况下关闭Browser标签页
- 后端服务停止后,Browser标签页会显示错误页面
⚠️ CRITICAL: Never Tell Users to Access localhost
⚠️ 重要提醒:切勿告知用户访问localhost
The user's browser CANNOT access or . These addresses point to the server container, not the user's machine. The preview architecture uses a reverse proxy:
localhost127.0.0.1User's Browser → https://<host>/preview/{id}/path → (reverse proxy) → 127.0.0.1:{port}/pathRules:
- NEVER tell the user to visit or
http://localhost:{port}— they cannot reach ithttp://127.0.0.1:{port} - ALWAYS direct users to the preview URL: (or the full URL
/preview/{id}/)https://<host>/preview/{id}/ - is for your own server-side diagnostics only — never suggest it to the user as a way to "test" the preview
curl http://localhost:{port} - When a preview is running, tell the user: "Check the Browser panel, or refresh the Browser panel"
- If you need to give the user a URL, use the field returned by
url(format:preview_serve)/preview/{id}/
用户的浏览器无法访问或。这些地址指向服务器容器,而非用户的本地机器。预览架构采用反向代理:
localhost127.0.0.1用户浏览器 → https://<host>/preview/{id}/path → (反向代理) → 127.0.0.1:{port}/path规则:
- 绝对不要告知用户访问或
http://localhost:{port}——他们无法访问http://127.0.0.1:{port} - 务必引导用户使用预览URL:(或完整URL
/preview/{id}/)https://<host>/preview/{id}/ - 仅用于你自己的服务器端诊断——切勿建议用户以此方式“测试”预览
curl http://localhost:{port} - 当预览运行时,告知用户:“请查看Browser面板,或刷新Browser面板”
- 若需要给用户提供URL,请使用返回的
preview_serve字段(格式:url)/preview/{id}/
⚠️ Static Assets Must Use Relative Paths
⚠️ 静态资源必须使用相对路径
Because previews are served under , absolute paths in HTML/JS/CSS will break. The reverse proxy strips the prefix before forwarding to the backend, but the browser resolves absolute paths from the domain root.
/preview/{id}//preview/{id}Example of the problem:
html
<!-- ❌ BROKEN: browser requests https://host/static/app.js → 404 (bypasses preview proxy) -->
<script src="/static/app.js"></script>
<!-- ✅ WORKS: browser requests https://host/preview/{id}/static/app.js → proxied correctly -->
<script src="static/app.js"></script>
<script src="./static/app.js"></script>Common patterns to fix:
| Broken (absolute) | Fixed (relative) |
|---|---|
| |
| |
| |
| |
| |
Check ALL places where paths appear:
- HTML ,
srcattributeshref - JavaScript ,
fetch(), dynamic importsXMLHttpRequest - CSS references
url() - JavaScript string literals (e.g., in template strings or concatenation)
'/static/' - Framework config files (e.g., ,
publicPath,base)assetPrefix
⚠️ Be thorough — it's common to fix CSS but miss JS string literals like (with single quotes). Search for ALL occurrences of absolute paths across all file types.
url()'/static/'由于预览通过路径提供服务,HTML/JS/CSS中的绝对路径会导致页面失效。反向代理在转发请求到后端前会移除前缀,但浏览器会从域名根目录解析绝对路径。
/preview/{id}//preview/{id}问题示例:
html
<!-- ❌ 失效:浏览器请求https://host/static/app.js → 404(绕过预览代理) -->
<script src="/static/app.js"></script>
<!-- ✅ 有效:浏览器请求https://host/preview/{id}/static/app.js → 正确代理 -->
<script src="static/app.js"></script>
<script src="./static/app.js"></script>修复方案:
| 失效(绝对路径) | 有效(相对路径) |
|---|---|
| |
| |
| |
| |
| |
检查所有出现路径的位置:
- HTML的、
src属性href - JavaScript的、
fetch()、动态导入XMLHttpRequest - CSS的引用
url() - JavaScript字符串字面量(例如模板字符串或拼接中的)
'/static/' - 框架配置文件(例如、
publicPath、base)assetPrefix
⚠️ 务必彻底检查——常见问题是修复了CSS的但遗漏了JS中的字符串字面量(带单引号)。搜索所有文件类型中的绝对路径实例。
url()'/static/'⚠️ Do NOT Browse Filesystem to Debug Previews
⚠️ 请勿通过浏览文件系统调试预览
Never look at workspace directories like , , or random folders to understand preview state. Those are user data, not preview service state.
preview/output/The only sources of truth:
- Registry file: (running services)
/data/previews.json - History file: (all past services)
/data/preview_history.json - /
preview_servetoolspreview_stop - Port checks via (server-side only, for your diagnostics)
curl
Do NOT use / on workspace directories to diagnose preview issues. Do NOT call unrelated tools like . Stay focused.
lsfindlist_scheduled_tasks绝对不要查看、或随机文件夹来了解预览状态。这些是用户数据,而非预览服务状态。
preview/output/唯一可信的信息来源:
- 注册表文件:(运行中的服务)
/data/previews.json - 历史文件:(所有过往服务)
/data/preview_history.json - /
preview_serve工具preview_stop - 通过检查端口(仅用于服务器端诊断)
curl
请勿使用/命令查看工作区目录来诊断预览问题。请勿调用无关工具如。请专注于相关操作。
lsfindlist_scheduled_tasksStep-by-Step: Diagnosing Browser Issues
分步诊断浏览器问题
When a user reports any Browser problem, follow this exact sequence:
当用户报告任何Browser问题时,请严格按照以下步骤操作:
Step 1: Read the registry (running services)
步骤1:查看注册表(运行中的服务)
bash
cat /data/previews.json 2>/dev/null || echo "NO_REGISTRY"⚠️ Your bash CWD is . The registry is at (absolute path, one level up). Always use the absolute path.
/data/workspace//data/previews.jsonJSON structure:
json
{
"previews": [
{"id": "f343befc", "title": "My App", "dir": "/data/workspace/my-project", "command": "npm run dev", "port": 9080, "is_builtin": false}
]
}bash
cat /data/previews.json 2>/dev/null || echo "NO_REGISTRY"⚠️ 你的bash当前工作目录是。注册表位于(绝对路径,上一级目录)。请始终使用绝对路径。
/data/workspace//data/previews.jsonJSON结构:
json
{
"previews": [
{"id": "f343befc", "title": "My App", "dir": "/data/workspace/my-project", "command": "npm run dev", "port": 9080, "is_builtin": false}
]
}Step 2: Branch based on registry state
步骤2:根据注册表状态分支处理
If registry has entries → Go to Step 3 (verify services)
If registry is empty or missing → Go to Step 4 (check history)
若注册表有条目 → 进入步骤3(验证服务)
若注册表为空或不存在 → 进入步骤4(查看历史记录)
Step 3: Registry has entries — verify and fix
步骤3:注册表有条目——验证并修复
For each preview in the registry, check if the port is responding server-side (this is your diagnostic, not for the user):
bash
curl -s -o /dev/null -w "%{http_code}" http://localhost:{port}If port responds (200):
- The service IS running. Tell the user:
- "You have a running service: {title}"
- "Click the ⋮ menu at the top-right of the Browser panel, then click it in the RUNNING SERVICES list to reopen"
- Preview URL:
/preview/{id}/
- If user says the ⋮ menu is empty or doesn't show the service → frontend lost sync. Fix by recreating: then
preview_stop(id)using the info from the registry. This forces the frontend to re-register the tab.preview_serve(dir, title, command)
If port does NOT respond:
- Process crashed but registry entry remains. Recreate:
preview_stop(id="{id}") preview_serve(dir="{dir}", title="{title}", command="{command}")
对于注册表中的每个预览,检查端口是否在服务器端响应(此操作仅用于你的诊断,不面向用户):
bash
curl -s -o /dev/null -w "%{http_code}" http://localhost:{port}若端口响应(返回200):
- 服务正在运行。告知用户:
- "你有一个运行中的服务:{title}"
- "点击Browser面板右上角的⋮菜单,然后在RUNNING SERVICES列表中点击该服务重新打开"
- 预览URL:
/preview/{id}/
- 若用户表示⋮菜单为空或未显示该服务 → 前端失去同步。通过重新创建预览修复:使用注册表中的信息调用,然后调用
preview_stop(id)。此操作会强制前端重新注册标签页。preview_serve(dir, title, command)
若端口无响应:
- 进程已崩溃但注册表条目仍存在。重新创建预览:
preview_stop(id="{id}") preview_serve(dir="{dir}", title="{title}", command="{command}")
Step 4: No running services — check history first, then scan workspace
步骤4:无运行中的服务——先查看历史记录,再扫描工作区
When there are no running services, use a two-tier lookup to find projects the user can preview:
当没有运行中的服务时,使用两级查找找到用户可以预览的项目:
Tier 1: Read preview history (preferred — fast and accurate)
第一级:查看预览历史记录(优先选择——快速准确)
bash
cat /data/preview_history.json 2>/dev/null || echo "NO_HISTORY"JSON structure:
json
{
"history": [
{
"id": "f343befc",
"title": "Trading System",
"dir": "/data/workspace/my-project",
"command": "python main.py",
"port": 8000,
"is_builtin": false,
"created_at": 1709100000.0,
"last_started_at": 1709200000.0
}
]
}History entries are never removed by — they persist across restarts. Entries are automatically pruned only when the project directory no longer exists.
preview_stopIf history has entries:
- List all history entries to the user with title, directory, and last started time
- Ask which one they want to restart
- Call with the
preview_serve,dir, andtitlefrom the history entrycommand
If user says a project is missing from history → fall through to Tier 2.
bash
cat /data/preview_history.json 2>/dev/null || echo "NO_HISTORY"JSON结构:
json
{
"history": [
{
"id": "f343befc",
"title": "Trading System",
"dir": "/data/workspace/my-project",
"command": "python main.py",
"port": 8000,
"is_builtin": false,
"created_at": 1709100000.0,
"last_started_at": 1709200000.0
}
]
}历史记录条目不会被删除——会在重启后保留。仅当项目目录不存在时,条目才会被自动清理。
preview_stop若历史记录有条目:
- 向用户列出所有历史记录条目,包括标题、目录和最后启动时间
- 询问用户要重启哪一个
- 使用历史记录条目中的、
dir和title调用commandpreview_serve
若用户表示历史记录中缺少某个项目 → 进入第二级查找。
Tier 2: Scan workspace (fallback — when history is empty or incomplete)
第二级:扫描工作区(备选方案——当历史记录为空或不完整时)
bash
find /data/workspace -maxdepth 2 \( -name "package.json" -o -name "index.html" -o -name "*.html" -o -name "app.py" -o -name "main.py" -o -name "vite.config.*" \) -not -path "*/node_modules/*" -not -path "*/skills/*" -not -path "*/memory/*" -not -path "*/prompt/*" -not -path "*/.git/*" 2>/dev/nullThen:
- List discovered projects with brief descriptions
- Ask the user which one to preview
- Call with the appropriate directory
preview_serve
Don't just say "no services running" and stop. Always check history first, then scan, and offer options.
bash
find /data/workspace -maxdepth 2 \( -name "package.json" -o -name "index.html" -o -name "*.html" -o -name "app.py" -o -name "main.py" -o -name "vite.config.*" \) -not -path "*/node_modules/*" -not -path "*/skills/*" -not -path "*/memory/*" -not -path "*/prompt/*" -not -path "*/.git/*" 2>/dev/null然后:
- 列出发现的项目及简要描述
- 询问用户要预览哪一个
- 使用相应目录调用
preview_serve
不要只说“无运行中的服务”就停止操作。请始终先查看历史记录,再进行扫描,并为用户提供选项。
Quick Reference
快速参考
| User says | You do |
|---|---|
| "tab disappeared" / "tab 不见了" | Step 1 → 2 → 3 or 4 |
| "blank page" / "白屏" | Check port (server-side), if dead → recreate; if alive → check for absolute path issues |
| "not updating" / "内容没更新" | Suggest refresh button in Browser tab, or recreate preview |
| "port conflict" / "端口冲突" | |
| "can't see service" / "⋮ menu empty" | |
| "where's my project" / "what did I build" | Read |
| "resource load failed" / "JS/CSS 404" | Check for absolute paths ( |
| 用户反馈 | 你的操作 |
|---|---|
| "tab disappeared" / "tab 不见了" | 步骤1 → 2 → 3或4 |
| "blank page" / "白屏" | 检查端口(服务器端),若端口无响应则重新创建预览;若端口正常则检查绝对路径问题 |
| "not updating" / "内容没更新" | 建议用户点击Browser标签页中的刷新按钮,或重新创建预览 |
| "port conflict" / "端口冲突" | |
| "can't see service" / "⋮ menu empty" | |
| "where's my project" / "what did I build" | 读取 |
| "resource load failed" / "JS/CSS 404" | 检查绝对路径( |
What You Cannot Do
你无法执行的操作
- Cannot directly open/close/refresh Browser tabs (frontend UI)
- Cannot force-refresh the iframe
- Cannot read what the iframe displays
When you can't do something, tell the user the manual action (e.g., "click refresh in Browser tab"). If manual action doesn't work, recreate the preview with + .
preview_stoppreview_serve- 无法直接打开/关闭/刷新Browser标签页(前端UI操作)
- 无法强制刷新iframe
- 无法读取iframe显示的内容
当你无法执行某项操作时,请告知用户手动操作(例如“点击Browser标签页中的刷新按钮”)。若手动操作无效,请使用 + 重新创建预览。
preview_stoppreview_serveCommon Mistakes to Avoid
需避免的常见错误
- ❌ Telling user to "visit http://localhost:18791/" — user cannot access localhost
- ❌ Saying "refresh the page at localhost" — meaningless to the user
- ❌ Only fixing CSS paths but missing JS string literals with absolute paths
url() - ❌ Forgetting to check ALL file types (HTML, JS, CSS, config) for absolute paths
- ✅ Always use as the user-facing URL
/preview/{id}/ - ✅ Always use only for your own server-side diagnostics
curl localhost:{port} - ✅ After fixing paths, call +
preview_stopto restart, then tell user to check Browser panelpreview_serve
- ❌ 告知用户“访问http://localhost:18791/”——用户无法访问localhost
- ❌ 说“刷新localhost上的页面”——对用户无意义
- ❌ 仅修复CSS的路径但遗漏JS中的绝对路径字符串字面量
url() - ❌ 忘记检查所有文件类型(HTML、JS、CSS、配置文件)中的绝对路径
- ✅ 始终使用作为面向用户的URL
/preview/{id}/ - ✅ 仅将用于服务器端诊断
curl localhost:{port} - ✅ 修复路径后,调用+
preview_stop重启服务,然后告知用户查看Browser面板preview_serve