diff --git a/README.md b/README.md
index d53d3b6..6f84398 100644
--- a/README.md
+++ b/README.md
@@ -61,7 +61,7 @@ pnpm add -D weapp-vite
-**规划中 · 跨运行时组件系统的生产底座**
+**稳定版 · 跨运行时组件系统的生产底座**
为 H5 与 weapp-vite 小程序提供 registry-first primitives、组件封装、主题 token、业务 Blocks 和 Agent UI,通过 CLI 交付可编辑源码与校验能力。
@@ -70,10 +70,10 @@ pnpm add -D weapp-vite
- **支持范围:** H5、WeChat、Vue 3、weapp-vite、Tailwind CSS。
```bash
-pnpm dlx @varo/cli add --target weapp-vite button input card
+pnpm dlx @varo-ui/cli add --target weapp button input card
```
-[文档](https://github.com/daguanren21/Varo#readme) · [源码](https://github.com/daguanren21/Varo) · [npm](https://www.npmjs.com/package/@varo/cli)
+[文档](https://daguanren21.github.io/Varo/) · [源码](https://github.com/daguanren21/Varo) · [npm](https://www.npmjs.com/package/@varo-ui/cli)
## 更多生态项目
diff --git a/apps/web/media-source/showcase/captures.json b/apps/web/media-source/showcase/captures.json
index 8ae4bcf..85864d9 100644
--- a/apps/web/media-source/showcase/captures.json
+++ b/apps/web/media-source/showcase/captures.json
@@ -86,7 +86,7 @@
"deviceScaleFactor": 2
},
"state": "Existing AgentComponentDemo messages and waiting event snapshot; documentation viewport expanded to show the entire component.",
- "attribution": "Varo AgentChat component demo, Chinese and light theme. Product remains planned on weapp.dev."
+ "attribution": "Varo AgentChat component demo, Chinese and light theme."
}
]
}
diff --git a/apps/web/media-source/varo-homepage-latest.png b/apps/web/media-source/varo-homepage-latest.png
new file mode 100644
index 0000000..1e85f6d
Binary files /dev/null and b/apps/web/media-source/varo-homepage-latest.png differ
diff --git a/apps/web/public/llms-full.txt b/apps/web/public/llms-full.txt
index eafe08d..de873f2 100644
--- a/apps/web/public/llms-full.txt
+++ b/apps/web/public/llms-full.txt
@@ -1,6 +1,6 @@
# weapp.dev reference
-weapp.dev hosts tools for real mini-app repos. weapp-tailwindcss handles styles, weapp-vite handles builds, and Varo documents planned editable component delivery boundaries. Adopt the released tools separately or together. The Chinese homepage is https://weapp.dev/ and the English homepage is https://weapp.dev/en/. The site is maintained by sonofmagic and contributors. The source repository is https://github.com/sonofmagic/weapp.dev.
+weapp.dev hosts tools for real mini-app repos. weapp-tailwindcss handles styles, weapp-vite handles builds, and Varo provides Registry-first editable component delivery. Adopt the released tools separately or together. The Chinese homepage is https://weapp.dev/ and the English homepage is https://weapp.dev/en/. The site is maintained by sonofmagic and contributors. The source repository is https://github.com/sonofmagic/weapp.dev.
## weapp-tailwindcss
@@ -28,9 +28,12 @@ weapp.dev hosts tools for real mini-app repos. weapp-tailwindcss handles styles,
- Canonical Chinese page: https://weapp.dev/projects/varo/
- Canonical English page: https://weapp.dev/en/projects/varo/
-- Documentation and source: https://github.com/daguanren21/Varo#readme
-- Purpose: Planned Registry, editable UI source, theme token, business block, and Agent UI boundaries for H5 and weapp-vite mini-programs.
-- Release status: planned; package metadata, install instructions, runtime capabilities, and performance data are not published yet.
+- Documentation: https://daguanren21.github.io/Varo/
+- Source: https://github.com/daguanren21/Varo
+- npm: https://www.npmjs.com/package/@varo-ui/cli
+- Install: `pnpm dlx @varo-ui/cli add --target weapp button input card`
+- Purpose: Registry-first editable UI source, theme tokens, business Blocks, and Agent UI for H5 and Wevu mini-programs.
+- Targets: Vue 3 on H5 and Wevu with weapp-vite for mini-programs.
## VPT (vite-plugin-taro)
diff --git a/apps/web/public/llms.txt b/apps/web/public/llms.txt
index 8fbbbb6..2611c96 100644
--- a/apps/web/public/llms.txt
+++ b/apps/web/public/llms.txt
@@ -1,12 +1,12 @@
# weapp.dev
-> weapp.dev hosts tools for real mini-app repos: weapp-tailwindcss for styles, weapp-vite for builds, and planned Varo component delivery boundaries. You can adopt the released tools separately.
+> weapp.dev hosts tools for real mini-app repos: weapp-tailwindcss for styles, weapp-vite for builds, and Varo for Registry-first component delivery. You can adopt the released tools separately.
## Official project pages
- [weapp-tailwindcss](https://weapp.dev/projects/weapp-tailwindcss/): Tailwind CSS v4 generation, class transforms, and platform-aware styling for mini-apps and cross-platform frameworks.
- [weapp-vite](https://weapp.dev/projects/weapp-vite/): Vite-powered development, builds, runtime tooling, and multi-platform output for mini-app projects.
-- [Varo](https://weapp.dev/projects/varo/): Planned editable component delivery boundaries, primitives, business blocks, and Agent UI for H5 and weapp-vite mini-programs.
+- [Varo](https://weapp.dev/projects/varo/): Registry-first editable component source, primitives, business Blocks, and Agent UI for H5 and Wevu mini-programs.
- [VPT](https://weapp.dev/projects/vite-plugin-taro/): Vite 8, React 19, and Taro 4 for WeChat, Alipay, and Web apps, with state-preserving hot reload, automatic WeChat subpackages, and Tailwind CSS v4.
- [English project index](https://weapp.dev/en/): English overview of the stack.
- [Sponsorship and services](https://weapp.dev/pricing/): One-time sponsorship tiers with a 60/25/15 public split, plus scoped migration and training services.
@@ -21,8 +21,9 @@
- [weapp-vite documentation](https://vite.weapp.dev/)
- [weapp-tailwindcss on npm](https://www.npmjs.com/package/weapp-tailwindcss)
- [weapp-vite on npm](https://www.npmjs.com/package/weapp-vite)
-- [Varo source and documentation](https://github.com/daguanren21/Varo#readme)
-- Varo package and install instructions are not published yet; see the [Varo planning page](https://weapp.dev/projects/varo/).
+- [Varo source](https://github.com/daguanren21/Varo)
+- [Varo documentation](https://daguanren21.github.io/Varo/)
+- [@varo-ui/cli on npm](https://www.npmjs.com/package/@varo-ui/cli)
- [VPT source](https://github.com/sep2/vite-plugin-taro)
- [VPT documentation](https://vpt.js.org/)
- [vite-plugin-taro on npm](https://www.npmjs.com/package/vite-plugin-taro)
diff --git a/apps/web/public/media/projects/varo-home.avif b/apps/web/public/media/projects/varo-home.avif
index 8f6402c..67684a5 100644
Binary files a/apps/web/public/media/projects/varo-home.avif and b/apps/web/public/media/projects/varo-home.avif differ
diff --git a/apps/web/public/media/projects/varo-home.webp b/apps/web/public/media/projects/varo-home.webp
index 76e6bc3..92c012f 100644
Binary files a/apps/web/public/media/projects/varo-home.webp and b/apps/web/public/media/projects/varo-home.webp differ
diff --git a/apps/web/public/media/showcase/sources.json b/apps/web/public/media/showcase/sources.json
index 8113f75..3724d05 100644
--- a/apps/web/public/media/showcase/sources.json
+++ b/apps/web/public/media/showcase/sources.json
@@ -188,7 +188,7 @@
"deviceScaleFactor": 2
},
"state": "Existing AgentComponentDemo messages and waiting event snapshot; documentation viewport expanded to show the entire component.",
- "attribution": "Varo AgentChat component demo, Chinese and light theme. Product remains planned on weapp.dev.",
+ "attribution": "Varo AgentChat component demo, Chinese and light theme.",
"output": {
"src": "/media/showcase/varo-agent-chat-1260.webp",
"avif": "/media/showcase/varo-agent-chat-1260.avif",
@@ -214,11 +214,11 @@
"locales": {
"zh-CN": {
"alt": "Varo AgentChat 组件演示,包含对话历史、registry.inspect 工具事件、确认区域和输入框",
- "caption": "Varo AgentChat 组件演示:对话、工具事件与输入区。项目仍在规划中。"
+ "caption": "Varo AgentChat 组件演示:对话、工具事件、审批与输入区。"
},
"en": {
"alt": "Varo AgentChat demo with message history, a registry.inspect tool event, approval controls and composer",
- "caption": "Varo AgentChat component demo: conversation, tool events and composer. The project remains planned."
+ "caption": "Varo AgentChat component demo: conversation, tool events, approvals, and composer."
}
}
}
diff --git a/apps/web/public/media/sources.json b/apps/web/public/media/sources.json
index af5cd5a..336e139 100644
--- a/apps/web/public/media/sources.json
+++ b/apps/web/public/media/sources.json
@@ -1,5 +1,5 @@
{
- "generatedAt": "2026-08-27",
+ "generatedAt": "2026-09-16",
"projectMedia": [
{
"repository": "sonofmagic/weapp-tailwindcss",
@@ -27,7 +27,8 @@
},
{
"repository": "daguanren21/Varo",
- "source": "apps/docs/public/brand-assets/varo-homepage-source.png",
+ "page": "https://daguanren21.github.io/Varo/",
+ "localSource": "../media-source/varo-homepage-latest.png",
"output": "projects/varo-home",
"width": 1440
},
diff --git a/apps/web/scripts/capture-showcase.mjs b/apps/web/scripts/capture-showcase.mjs
index f498dcb..40d5b1d 100644
--- a/apps/web/scripts/capture-showcase.mjs
+++ b/apps/web/scripts/capture-showcase.mjs
@@ -133,7 +133,7 @@ try {
route: '/ai/agent-chat',
viewport: { width: 860, height: 1300, deviceScaleFactor: 2 },
state: 'Existing AgentComponentDemo messages and waiting event snapshot; documentation viewport expanded to show the entire component.',
- attribution: 'Varo AgentChat component demo, Chinese and light theme. Product remains planned on weapp.dev.',
+ attribution: 'Varo AgentChat component demo, Chinese and light theme.',
})
}
finally {
diff --git a/apps/web/scripts/generate-media.ts b/apps/web/scripts/generate-media.ts
index 8a17e68..d80b1ee 100644
--- a/apps/web/scripts/generate-media.ts
+++ b/apps/web/scripts/generate-media.ts
@@ -1,5 +1,5 @@
import { Buffer } from 'node:buffer'
-import { mkdir, writeFile } from 'node:fs/promises'
+import { mkdir, readFile, writeFile } from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
import sharp from 'sharp'
@@ -32,7 +32,8 @@ const projectMedia = [
},
{
repository: 'daguanren21/Varo',
- source: 'apps/docs/public/brand-assets/varo-homepage-source.png',
+ page: 'https://daguanren21.github.io/Varo/',
+ localSource: '../media-source/varo-homepage-latest.png',
output: 'projects/varo-home',
width: 1440,
},
@@ -61,7 +62,9 @@ async function downloadGitHubFile(repository: string, source: string): Promise\n 开始构建\n` },
- varo: { zh: '可编辑组件交付边界(规划中)', en: 'Editable component delivery boundary (planned)', file: 'planning.md', code: `status: planned\ninstall: to be confirmed\nruntime: to be confirmed` },
+ varo: { zh: 'Registry 安装命令', en: 'Registry install command', file: 'terminal', code: `pnpm dlx @varo-ui/cli add \\\n --target weapp \\\n button input card` },
'weapp-sqlite': { zh: '本地数据能力(规划中)', en: 'Local data capability (planned)', file: 'planning.md', code: `status: planned\napi: to be confirmed\nplatforms: to be confirmed\n\n# no production API is promised yet` },
'vite-plugin-taro': { zh: 'Taro + Vite 迁移', en: 'Taro + Vite migration', file: 'package.json', code: `npm create vite-taro@latest my-app\n\n# keep React + Taro APIs\n# move the build pipeline to Vite` },
}[project.id]
diff --git a/apps/web/src/components/ProjectSelector.astro b/apps/web/src/components/ProjectSelector.astro
index e6a1e66..0856644 100644
--- a/apps/web/src/components/ProjectSelector.astro
+++ b/apps/web/src/components/ProjectSelector.astro
@@ -12,7 +12,7 @@ const copy = locale === 'zh-CN' ? {
paths: [
{ title: '新建小程序工程', body: '从现代 Vite 工程开始,再按需要叠加样式和组件。', ids: ['weapp-vite', 'weapp-tailwindcss', 'varo'] },
{ title: '已有小程序项目', body: '先把样式工作流接进现有项目,不要求重写页面。', ids: ['weapp-tailwindcss'] },
- { title: '需要组件源码和业务 Blocks', body: '从 Varo 的组件与交付规划开始,评估可编辑源码和业务组合方式。', ids: ['varo'] },
+ { title: '需要组件源码和业务 Blocks', body: '从 Varo Registry 安装可编辑源码,再按业务需要组合组件与 Blocks。', ids: ['varo'] },
{ title: '需要本地数据', body: '评估结构化本地存储和离线能力,关注 weapp-sqlite 的规划进展。', ids: ['weapp-sqlite'] },
{ title: '已有 Taro / React 项目', body: '保留 Taro 组件和 API,把开发构建链路切换到 Vite。', ids: ['vite-plugin-taro'] },
],
@@ -22,7 +22,7 @@ const copy = locale === 'zh-CN' ? {
paths: [
{ title: 'Starting a new mini-app', body: 'Begin with a modern Vite project, then add styling and components as needed.', ids: ['weapp-vite', 'weapp-tailwindcss', 'varo'] },
{ title: 'Working in an existing mini-app', body: 'Bring the styling workflow into the current project without rewriting pages.', ids: ['weapp-tailwindcss'] },
- { title: 'Choosing component source and Blocks', body: 'Explore Varo’s component and delivery plans for editable source and business compositions.', ids: ['varo'] },
+ { title: 'Choosing component source and Blocks', body: 'Install editable source from the Varo Registry, then compose components and Blocks for your product.', ids: ['varo'] },
{ title: 'Planning local data', body: 'Evaluate structured storage and offline needs while weapp-sqlite is being planned.', ids: ['weapp-sqlite'] },
{ title: 'Already on Taro / React', body: 'Keep Taro components and APIs while moving the development pipeline to Vite.', ids: ['vite-plugin-taro'] },
],
diff --git a/apps/web/src/content.test.ts b/apps/web/src/content.test.ts
index 6c0bde5..ea31f77 100644
--- a/apps/web/src/content.test.ts
+++ b/apps/web/src/content.test.ts
@@ -13,7 +13,7 @@ describe('project definitions', () => {
'weapp-vite': 'https://vite.weapp.dev/',
'vite-plugin-taro': 'https://vpt.js.org/',
'weapp-sqlite': 'https://github.com/weapp-sqlite/weapp-sqlite#readme',
- '@varo/cli': 'https://github.com/daguanren21/Varo#readme',
+ '@varo-ui/cli': 'https://daguanren21.github.io/Varo/',
}
it('provides complete localized content for every project', () => {
@@ -64,12 +64,15 @@ describe('project definitions', () => {
}
})
- it('uses explicit placeholders for the planned Varo release', () => {
+ it('publishes the Varo release and package actions', () => {
expect(varo).toMatchObject({
- status: 'planned',
- packageName: '@varo/cli',
+ status: 'stable',
+ maturity: 'stable',
+ packageName: '@varo-ui/cli',
github: 'daguanren21/Varo',
- docsUrl: 'https://github.com/daguanren21/Varo#readme',
+ docsUrl: 'https://daguanren21.github.io/Varo/',
+ npmUrl: 'https://www.npmjs.com/package/@varo-ui/cli',
+ installCommand: 'pnpm dlx @varo-ui/cli add --target weapp button input card',
})
})
@@ -87,6 +90,7 @@ describe('project definitions', () => {
'weapp-vite': 'https://www.npmjs.com/package/weapp-vite',
'weapp-tailwindcss': 'https://www.npmjs.com/package/weapp-tailwindcss',
'vite-plugin-taro': 'https://www.npmjs.com/package/vite-plugin-taro',
+ '@varo-ui/cli': 'https://www.npmjs.com/package/@varo-ui/cli',
}
for (const project of projects) {
diff --git a/apps/web/src/content/projects/varo.json b/apps/web/src/content/projects/varo.json
index 97f88db..4d88eaa 100644
--- a/apps/web/src/content/projects/varo.json
+++ b/apps/web/src/content/projects/varo.json
@@ -1,9 +1,11 @@
{
"order": 3,
- "status": "planned",
- "packageName": "@varo/cli",
+ "status": "stable",
+ "packageName": "@varo-ui/cli",
"github": "daguanren21/Varo",
- "docsUrl": "https://github.com/daguanren21/Varo#readme",
+ "docsUrl": "https://daguanren21.github.io/Varo/",
+ "npmUrl": "https://www.npmjs.com/package/@varo-ui/cli",
+ "license": "https://opensource.org/license/mit",
"maintainer": "daguanren21 and contributors",
"keywords": [
"Vue 3",
@@ -14,11 +16,12 @@
"Agent UI",
"Blocks"
],
+ "installCommand": "pnpm dlx @varo-ui/cli add --target weapp button input card",
"futureDocsPath": "/docs/varo/",
"logo": "/brands/varo.svg",
"accent": "#07c160",
"role": "Components",
- "maturity": "planned",
+ "maturity": "stable",
"runtime": [
"Vue 3",
"H5",
@@ -28,7 +31,7 @@
"weapp-tailwindcss",
"weapp-sqlite"
],
- "dataCompleteness": "partial",
+ "dataCompleteness": "complete",
"platforms": [
"H5",
"WeChat",
@@ -44,12 +47,12 @@
"height": 990,
"locales": {
"zh-CN": {
- "alt": "Varo 文档首页展示跨运行时组件系统能力",
- "caption": "Varo 正在规划 primitives、可复制源码与交付校验如何服务 H5 和小程序组件系统。"
+ "alt": "Varo Registry-first 文档首页展示 H5 与小程序双端安装路径",
+ "caption": "Varo 文档首页展示 Registry-first 双端组件交付路径。"
},
"en": {
- "alt": "Varo documentation home showing the cross-runtime component system",
- "caption": "Varo is planning how primitives, editable source, and delivery checks should serve H5 and mini-program component systems."
+ "alt": "Varo Registry-first documentation home showing H5 and mini-program installation paths",
+ "caption": "The Varo documentation home presents its Registry-first component delivery paths for both runtimes."
}
}
},
@@ -61,11 +64,11 @@
"locales": {
"zh-CN": {
"alt": "Varo Agent UI 完整对话与工具界面",
- "caption": "Agent UI 与 Agent Chat Block 的交互协议仍在规划中。"
+ "caption": "Agent UI 与 Agent Chat Block 提供对话、工具调用与审批交互。"
},
"en": {
"alt": "Varo Agent UI conversation and tool interface",
- "caption": "The Agent UI and Agent Chat Block interaction contract is still planned."
+ "caption": "Agent UI and the Agent Chat Block provide conversation, tool-call, and approval interactions."
}
}
}
@@ -73,55 +76,55 @@
"locales": {
"zh-CN": {
"name": "Varo",
- "tagline": "双端组件交付规划",
- "description": "Varo 正在整理 H5 与小程序的可编辑组件交付边界,安装方式、运行时范围和稳定资料确认后再公开。",
+ "tagline": "双端移动 UI Registry",
+ "description": "Varo 通过 Registry 向 H5 与 Wevu 小程序交付可编辑组件源码、业务 Blocks 与 Agent UI,并保留各端原生渲染。",
"audience": "需要在 H5 与小程序之间共享交互语义、组件源码和业务 Blocks 的 Vue 3 团队。",
"useCases": [
- "评估可编辑组件源码的交付边界",
- "规划双端业务 Blocks 与 Agent UI 的组合方式",
- "确认 primitives 与主题 token 的公开契约"
+ "从 Registry 安装可编辑的 H5 或小程序组件源码",
+ "复用双端业务 Blocks 与 Agent UI",
+ "基于 headless primitives 和主题 token 构建设计系统"
],
"capabilities": [
- "可编辑组件源码(规划中)",
- "双端运行时边界(待确认)",
- "Registry 与 Agent UI 契约(待确认)",
- "稳定版本与安装路径(待公开)"
+ "56 个 H5 Registry 组件族",
+ "45 个小程序 Registry 组件族",
+ "Registry 与 Agent UI",
+ "Vue 3 + Wevu 双端原生渲染"
],
"faqs": [
{
"question": "Varo 和传统 npm 组件库有什么不同?",
- "answer": "Varo 计划提供可复制、修改并归业务项目所有的组件与 Blocks 源码;具体交付方式仍在确认。"
+ "answer": "Varo 默认通过 Registry 把组件与 Blocks 源码安装到业务项目中,团队可以直接修改并拥有这些源码。"
},
{
- "question": "Varo 当前支持哪些运行时?",
- "answer": "目标运行时包含 H5 与 weapp-vite,但公开范围、组件数量和稳定 API 仍待确认。"
+ "question": "Varo 支持哪些运行时?",
+ "answer": "H5 使用 Vue 3,小程序使用 Wevu 与 weapp-vite;两端共享类型、纯函数和 headless primitives。"
}
]
},
"en": {
"name": "Varo",
- "tagline": "A planned boundary for dual-runtime component delivery",
- "description": "Varo is defining an editable component delivery boundary for H5 and mini-apps. Installation, runtime scope, and stable reference material will be published after confirmation.",
+ "tagline": "Registry-first mobile UI for two runtimes",
+ "description": "Varo delivers editable component source, business Blocks, and Agent UI to H5 and Wevu mini-program projects through its Registry while preserving native rendering on each target.",
"audience": "Vue 3 teams that need shared interaction semantics, component source, and business blocks across H5 and mini-program products.",
"useCases": [
- "Evaluate the boundary for editable component source",
- "Plan dual-target business blocks and Agent UI composition",
- "Confirm the public contract for primitives and theme tokens"
+ "Install editable H5 or mini-program component source from the Registry",
+ "Reuse dual-target business Blocks and Agent UI",
+ "Build a design system on headless primitives and theme tokens"
],
"capabilities": [
- "Editable component source (planned)",
- "Dual-runtime boundaries (to be confirmed)",
- "Registry and Agent UI contract (to be confirmed)",
- "Stable release and install path (not published yet)"
+ "56 H5 Registry component families",
+ "45 mini-program Registry component families",
+ "Registry and Agent UI",
+ "Native Vue 3 and Wevu rendering"
],
"faqs": [
{
"question": "How is Varo different from a traditional npm UI library?",
- "answer": "Varo plans to deliver component and block source that teams can copy, modify, and own; the delivery method is still being confirmed."
+ "answer": "Varo uses its Registry to install component and Block source into the product repository by default, so teams can modify and own that source."
},
{
- "question": "Which runtimes does Varo support today?",
- "answer": "The target runtimes include H5 and weapp-vite, but public scope, component counts, and stable APIs are still being confirmed."
+ "question": "Which runtimes does Varo support?",
+ "answer": "H5 uses Vue 3, while mini-program projects use Wevu and weapp-vite. The targets share types, pure functions, and headless primitives."
}
]
}
diff --git a/apps/web/src/content/showcases/varo.json b/apps/web/src/content/showcases/varo.json
index fdd2dcb..94b39a7 100644
--- a/apps/web/src/content/showcases/varo.json
+++ b/apps/web/src/content/showcases/varo.json
@@ -25,11 +25,11 @@
"locales": {
"zh-CN": {
"alt": "Varo AgentChat 组件演示,包含对话历史、registry.inspect 工具事件、确认区域和输入框",
- "caption": "Varo AgentChat 组件演示:对话、工具事件与输入区。项目仍在规划中。"
+ "caption": "Varo AgentChat 组件演示:对话、工具事件、审批与输入区。"
},
"en": {
"alt": "Varo AgentChat demo with message history, a registry.inspect tool event, approval controls and composer",
- "caption": "Varo AgentChat component demo: conversation, tool events and composer. The project remains planned."
+ "caption": "Varo AgentChat component demo: conversation, tool events, approvals, and composer."
}
}
}
diff --git a/apps/web/src/data/project-metrics.fallback.json b/apps/web/src/data/project-metrics.fallback.json
index 434c452..969adb3 100644
--- a/apps/web/src/data/project-metrics.fallback.json
+++ b/apps/web/src/data/project-metrics.fallback.json
@@ -14,11 +14,11 @@
"fetchedAt": "2026-08-26T00:00:00.000Z"
},
"varo": {
- "version": "0.0.1",
- "releasedAt": "2026-08-26T00:00:00.000Z",
- "stars": 0,
- "weeklyDownloads": 0,
- "fetchedAt": "2026-08-26T00:00:00.000Z"
+ "version": "2.1.0",
+ "releasedAt": "2026-09-13T15:45:51.579Z",
+ "stars": 2,
+ "weeklyDownloads": 195,
+ "fetchedAt": "2026-09-16T00:00:00.000Z"
},
"vite-plugin-taro": {
"version": "0.7.1",
diff --git a/apps/web/src/i18n/home/en.ts b/apps/web/src/i18n/home/en.ts
index cd1851e..65b90f4 100644
--- a/apps/web/src/i18n/home/en.ts
+++ b/apps/web/src/i18n/home/en.ts
@@ -14,7 +14,7 @@ export default {
items: [
{ title: 'Author', body: 'Keep writing native mini-app pages, Vue SFCs, or your current cross-platform setup. Do not reshuffle page boundaries just for tooling.' },
{ title: 'Build', body: 'Hand classes and styles to weapp-tailwindcss. Hand deps, routes, and single-target multi-platform builds to weapp-vite.' },
- { title: 'Compose', body: 'When you need component delivery, evaluate Varo’s editable-source boundary; installation guidance will follow a stable release.' },
+ { title: 'Compose', body: 'When you need component delivery, use the Varo Registry to install editable source for each target, then add business Blocks and Agent UI.' },
{ title: 'Store', body: 'When you need structured local data, follow the runtime boundaries and migration plan for weapp-sqlite.' },
{ title: 'Migrate', body: 'Existing Taro / React projects can move their development and build pipeline to Vite with VPT.' },
],
@@ -33,7 +33,7 @@ export default {
planned: 'Planned',
},
readinessTitle: 'No public metrics yet',
- readinessBody: 'The component layer is still in progress. We will not show downloads or stars before a stable release, so the page does not pretend with zeros.',
+ readinessBody: 'Downloads and stars stay hidden until a stable release, rather than presenting zeros as proof.',
proof: {
styleLabel: 'Default style markup',
styleFile: 'button.wxml',
@@ -66,7 +66,7 @@ export default {
},
{
title: 'Components · Varo',
- owns: 'Editable components, Blocks, and registry delivery boundaries (planned).',
+ owns: 'Editable components, Blocks, and Registry delivery boundaries.',
notOwns: 'Your project scaffold, or forcing a rewrite of existing pages.',
},
{
diff --git a/apps/web/src/i18n/home/zh-CN.ts b/apps/web/src/i18n/home/zh-CN.ts
index 6db98ac..ab50453 100644
--- a/apps/web/src/i18n/home/zh-CN.ts
+++ b/apps/web/src/i18n/home/zh-CN.ts
@@ -14,7 +14,7 @@ export default {
items: [
{ title: '编写', body: '继续写原生小程序、Vue SFC,或你现在的跨端框架。页面边界不用为了工具先改一轮。' },
{ title: '构建', body: '类名和样式交给 weapp-tailwindcss;依赖、路由和多平台单目标构建交给 weapp-vite。' },
- { title: '组装', body: '需要组件交付时,先评估 Varo 的可编辑源码与组件边界;项目稳定后再公布安装路径。' },
+ { title: '组装', body: '需要组件交付时,用 Varo Registry 按目标安装可编辑源码,再叠加业务 Blocks 与 Agent UI。' },
{ title: '存储', body: '需要本地结构化数据时,关注 weapp-sqlite 的运行时边界和迁移计划。' },
{ title: '迁移', body: '已有 Taro / React 项目可以通过 VPT 把开发构建链路切到 Vite。' },
],
@@ -33,7 +33,7 @@ export default {
planned: '规划中',
},
readinessTitle: '现在还没公开指标',
- readinessBody: '组件层还在做。稳定发布前不展示下载和 Stars,免得页面上挂两个 0 装样子。',
+ readinessBody: '项目稳定发布前不展示下载和 Stars,避免用两个 0 充当可信度。',
proof: {
styleLabel: '默认样式写法',
styleFile: 'button.wxml',
@@ -66,7 +66,7 @@ export default {
},
{
title: '组件 · Varo',
- owns: '可编辑组件、Blocks 与 Registry 交付边界(规划中)。',
+ owns: '可编辑组件、Blocks 与 Registry 交付边界。',
notOwns: '整个工程脚手架,也不强迫你改掉现有页面写法。',
},
{
diff --git a/apps/web/src/i18n/ui.ts b/apps/web/src/i18n/ui.ts
index 217a3f9..b6e7e9c 100644
--- a/apps/web/src/i18n/ui.ts
+++ b/apps/web/src/i18n/ui.ts
@@ -158,7 +158,7 @@ export const siteCopy = {
sponsorEmpty: '目前没有可公开展示的记录。',
sponsorDisplay: '查看 GitHub link',
roadmapTitle: '建设中的能力',
- roadmapDescription: '云构建、官方模板和私有组件仓库会在具备稳定交付链路后再开放。Varo 仍是规划中的组件库存,不按 GA 日期收费。',
+ roadmapDescription: 'Varo 公共 Registry 已发布;云构建、官方模板和私有组件仓库仍会在具备稳定交付链路后再开放。',
templatesTitle: '第一批官方模板',
templatesDescription: '这是建设方向,不代表模板已经上线或可以购买。未来计划邀请制上架,先做能过审、能换皮的场景。',
templates: [
@@ -413,7 +413,7 @@ export const siteCopy = {
sponsorEmpty: 'No public records are available yet.',
sponsorDisplay: 'View GitHub link',
roadmapTitle: 'Capabilities in development',
- roadmapDescription: 'Cloud builds, official templates, and private component registries will open after a stable delivery path exists. Varo remains planned component inventory and is not charged against a GA date.',
+ roadmapDescription: 'The public Varo Registry is available. Cloud builds, official templates, and private component registries will open after a stable delivery path exists.',
templatesTitle: 'The first official templates',
templatesDescription: 'This is a direction, not a live catalog or purchasable inventory. Future publishing will be invite-only and focused on reviewable, rebrandable scenarios.',
templates: [
diff --git a/apps/web/src/lib/seo.test.ts b/apps/web/src/lib/seo.test.ts
index f320228..166b16d 100644
--- a/apps/web/src/lib/seo.test.ts
+++ b/apps/web/src/lib/seo.test.ts
@@ -28,13 +28,13 @@ describe('SEO helpers', () => {
expect(JSON.parse(serializeJsonLd(entity))).toEqual(entity)
})
- it('does not publish release or package claims for planned projects', () => {
+ it('publishes release and package claims for Varo', () => {
const project = { id: 'varo', data: varo as unknown as ProjectDefinition }
const entity = projectSchema('en', project, fallbackMetrics.varo)
- expect(entity).not.toHaveProperty('version')
- expect(entity).not.toHaveProperty('dateModified')
- expect(entity).not.toHaveProperty('downloadUrl')
- expect(entity.sameAs).not.toContain('https://www.npmjs.com/package/@varo/cli')
+ expect(entity.version).toBe('2.1.0')
+ expect(entity.dateModified).toBe('2026-09-13T15:45:51.579Z')
+ expect(entity.downloadUrl).toBe('https://www.npmjs.com/package/@varo-ui/cli')
+ expect(entity.sameAs).toContain('https://www.npmjs.com/package/@varo-ui/cli')
})
it('keeps the planned weapp-sqlite schema free of unconfirmed runtime claims', () => {
diff --git a/apps/web/src/lib/toolchain.test.ts b/apps/web/src/lib/toolchain.test.ts
index e887d3a..cb3f55f 100644
--- a/apps/web/src/lib/toolchain.test.ts
+++ b/apps/web/src/lib/toolchain.test.ts
@@ -56,7 +56,7 @@ describe('toolchain project ordering', () => {
id: ['weapp-vite', 'weapp-tailwindcss', 'varo', 'weapp-sqlite', 'vite-plugin-taro'][index],
data: projectDefinitionSchema.parse(data),
})) as unknown as ProjectEntry[]
- projects[2].data.dataCompleteness = 'complete'
+ projects[3].data.dataCompleteness = 'complete'
expect(() => validateToolchainCatalog(projects)).toThrow('Planned project cannot claim complete data')
})
@@ -86,9 +86,9 @@ describe('toolchain project ordering', () => {
id: ['weapp-vite', 'weapp-tailwindcss', 'varo', 'weapp-sqlite', 'vite-plugin-taro'][index],
data: projectDefinitionSchema.parse(data),
})) as unknown as ProjectEntry[]
- projects[2].data.installCommand = 'pnpm dlx @varo/cli'
+ projects[3].data.installCommand = 'pnpm add weapp-sqlite'
expect(() => validateToolchainCatalog(projects)).toThrow('Planned project cannot publish package actions')
- projects[2].data.installCommand = undefined
+ projects[3].data.installCommand = undefined
projects[0].data.npmUrl = undefined
expect(() => validateToolchainCatalog(projects)).toThrow('Active project is missing package actions')
})
diff --git a/apps/web/src/styles/global.css b/apps/web/src/styles/global.css
index 3a73c1c..d80045b 100644
--- a/apps/web/src/styles/global.css
+++ b/apps/web/src/styles/global.css
@@ -224,13 +224,60 @@
box-shadow: var(--shadow-panel);
isolation: isolate;
}
-.home-hero-stage::after { position: absolute; inset: 0; z-index: 1; pointer-events: none; content: ''; background: linear-gradient(120deg, rgb(255 255 255 / 18%), transparent 42%, rgb(14 121 88 / 12%)); mix-blend-mode: screen; }
-.home-hero-stage-grid, .home-hero-stage-scan { position: absolute; z-index: 2; pointer-events: none; }
-.home-hero-stage-grid { inset: 0; opacity: 0.28; background-image: linear-gradient(rgb(14 121 88 / 16%) 1px, transparent 1px), linear-gradient(90deg, rgb(14 121 88 / 16%) 1px, transparent 1px); background-size: 42px 42px; }
-.home-hero-stage-scan { top: -25%; right: 0; left: 0; height: 30%; opacity: 0.5; background: linear-gradient(180deg, transparent, rgb(105 199 165 / 22%), transparent); }
-.home-hero-stage-marker, .home-hero-stage-readout { position: absolute; z-index: 3; color: var(--accent-contrast); font: 650 0.65rem/1.2 var(--font-mono); letter-spacing: 0.08em; background: rgb(7 19 14 / 72%); border: 1px solid rgb(105 199 165 / 44%); backdrop-filter: blur(8px); }
-.home-hero-stage-marker { top: 1rem; left: 1rem; padding: 0.45rem 0.6rem; }
-.home-hero-stage-readout { right: 1rem; bottom: 1rem; display: flex; gap: 0.6rem; padding: 0.45rem 0.6rem; }
+.home-hero-stage::after {
+ position: absolute;
+ inset: 0;
+ z-index: 1;
+ pointer-events: none;
+ content: '';
+ background: linear-gradient(120deg, rgb(255 255 255 / 18%), transparent 42%, rgb(14 121 88 / 12%));
+ mix-blend-mode: screen;
+}
+.home-hero-stage-grid,
+.home-hero-stage-scan {
+ position: absolute;
+ z-index: 2;
+ pointer-events: none;
+}
+.home-hero-stage-grid {
+ inset: 0;
+ opacity: 0.28;
+ background-image:
+ linear-gradient(rgb(14 121 88 / 16%) 1px, transparent 1px),
+ linear-gradient(90deg, rgb(14 121 88 / 16%) 1px, transparent 1px);
+ background-size: 42px 42px;
+}
+.home-hero-stage-scan {
+ top: -25%;
+ right: 0;
+ left: 0;
+ height: 30%;
+ opacity: 0.5;
+ background: linear-gradient(180deg, transparent, rgb(105 199 165 / 22%), transparent);
+}
+.home-hero-stage-marker,
+.home-hero-stage-readout {
+ position: absolute;
+ z-index: 3;
+ color: var(--accent-contrast);
+ font: 650 0.65rem/1.2 var(--font-mono);
+ letter-spacing: 0.08em;
+ background: rgb(7 19 14 / 72%);
+ border: 1px solid rgb(105 199 165 / 44%);
+ backdrop-filter: blur(8px);
+}
+.home-hero-stage-marker {
+ top: 1rem;
+ left: 1rem;
+ padding: 0.45rem 0.6rem;
+}
+.home-hero-stage-readout {
+ right: 1rem;
+ bottom: 1rem;
+ display: flex;
+ gap: 0.6rem;
+ padding: 0.45rem 0.6rem;
+}
.home-hero-stage picture,
.home-hero-stage img {
width: 100%;
@@ -650,28 +697,56 @@
[data-hero-enter] {
animation: hero-enter 600ms var(--enter-delay, 0ms) cubic-bezier(0.16, 1, 0.3, 1) both;
}
-[data-project-visual] img {
- filter: saturate(0.92) contrast(1.03);
- transition: filter 260ms ease, transform 260ms ease;
-}
-[data-project-visual]:hover img,
-[data-project-visual]:focus-within img {
- filter: saturate(1) contrast(1.06);
-}
- [data-project-visual] img { transition: transform 260ms ease, filter 260ms ease; }
+ [data-project-visual] img {
+ filter: saturate(0.92) contrast(1.03);
+ transition:
+ filter 260ms ease,
+ transform 260ms ease;
+ }
+ [data-project-visual]:hover img,
+ [data-project-visual]:focus-within img {
+ filter: saturate(1) contrast(1.06);
+ }
+ [data-project-visual] img {
+ transition:
+ transform 260ms ease,
+ filter 260ms ease;
+ }
[data-project-row]:focus-within [data-project-visual] img {
transform: scale(1.012);
}
- .home-hero-stage-scan { animation: hero-scan 5.5s ease-in-out infinite; }
- .home-hero-stage-asset { transition: transform 500ms ease, filter 500ms ease; }
- .home-hero-stage:hover .home-hero-stage-asset { transform: scale(1.025); filter: saturate(1) contrast(1.04); }
+ .home-hero-stage-scan {
+ animation: hero-scan 5.5s ease-in-out infinite;
+ }
+ .home-hero-stage-asset {
+ transition:
+ transform 500ms ease,
+ filter 500ms ease;
+ }
+ .home-hero-stage:hover .home-hero-stage-asset {
+ transform: scale(1.025);
+ filter: saturate(1) contrast(1.04);
+ }
@media (hover: hover) {
[data-project-row]:hover [data-project-visual] img {
transform: scale(1.012);
}
}
}
-@keyframes hero-scan { 0%, 100% { transform: translateY(-15%); opacity: 0; } 20%, 80% { opacity: 0.5; } 50% { transform: translateY(285%); } }
+@keyframes hero-scan {
+ 0%,
+ 100% {
+ transform: translateY(-15%);
+ opacity: 0;
+ }
+ 20%,
+ 80% {
+ opacity: 0.5;
+ }
+ 50% {
+ transform: translateY(285%);
+ }
+}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
diff --git a/apps/web/tests/e2e/projects.spec.ts b/apps/web/tests/e2e/projects.spec.ts
index f674d64..d52e487 100644
--- a/apps/web/tests/e2e/projects.spec.ts
+++ b/apps/web/tests/e2e/projects.spec.ts
@@ -22,12 +22,12 @@ for (const prefix of ['', '/en']) {
const links = page.locator('.toolchain-map-list li a')
await expect(links).toHaveCount(5)
const statusLabels = prefix ? { stable: 'Stable', planned: 'Planned' } : { stable: '稳定', planned: '规划中' }
- for (const id of ['weapp-vite', 'weapp-tailwindcss', 'vite-plugin-taro']) {
+ for (const id of ['weapp-vite', 'weapp-tailwindcss', 'varo', 'vite-plugin-taro']) {
const node = page.locator('.toolchain-map-list li').filter({ has: page.locator(`a[href="${prefix}/projects/${id}/"]`) })
await expect(node.locator('.toolchain-status')).toHaveText(statusLabels.stable)
await expect(node.locator('.toolchain-status')).toHaveAttribute('aria-label', prefix ? 'Project status: Stable' : '项目状态: 稳定')
}
- for (const id of ['varo', 'weapp-sqlite']) {
+ for (const id of ['weapp-sqlite']) {
const node = page.locator('.toolchain-map-list li').filter({ has: page.locator(`a[href="${prefix}/projects/${id}/"]`) })
await expect(node.locator('.toolchain-status')).toHaveText(statusLabels.planned)
await expect(node.locator('.toolchain-status')).toHaveAttribute('aria-label', prefix ? 'Project status: Planned' : '项目状态: 规划中')
@@ -189,27 +189,6 @@ for (const prefix of ['', '/en']) {
await expect(heroVisual).toHaveAttribute('decoding', 'async')
})
- test(`offers five adoption paths and their documentation on ${prefix}/`, async ({ page }) => {
- await page.goto(`${prefix}/`)
- const paths = page.locator('.project-selector-list article')
- await expect(paths).toHaveCount(5)
- for (const [index, slug] of ['weapp-vite', 'weapp-tailwindcss', 'varo', 'weapp-sqlite', 'vite-plugin-taro'].entries()) {
- const path = paths.nth(index)
- await expect(path).toHaveAttribute('aria-labelledby', `path-title-${index}`)
- await expect(path).toHaveAttribute('aria-describedby', ['varo', 'weapp-sqlite'].includes(slug) ? `path-description-${index} selector-status-${index}` : `path-description-${index} selector-command-${index}`)
- await expect(path.locator('.project-selector-actions a').first()).toHaveAttribute('href', `${prefix}/projects/${slug}/`)
- await expect(path.locator('.project-selector-actions a').last()).toHaveAttribute('href', /^https:\/\//)
- if (['varo', 'weapp-sqlite'].includes(slug)) {
- await expect(path.locator('code')).toHaveCount(0)
- await expect(path.locator('.project-selector-planned')).toContainText(zh ? '规划中' : 'planned')
- await expect(path.locator('.project-selector-planned')).toHaveAttribute('aria-label', zh ? '项目状态:规划中' : 'Project status: Planned')
- }
- else {
- await expect(path.locator('code')).not.toBeEmpty()
- }
- }
- })
-
test(`publishes all five projects in the localized ItemList schema on ${prefix}/projects/`, async ({ page }) => {
await page.goto(`${prefix}/projects/`)
const schema = await page.locator('script[type="application/ld+json"]').evaluateAll(scripts => scripts.map(script => JSON.parse(script.textContent ?? '{}')).find(value => value['@type'] === 'ItemList'))
@@ -236,7 +215,7 @@ for (const prefix of ['', '/en']) {
await page.emulateMedia({ colorScheme: theme, reducedMotion: 'reduce' })
for (const slug of ['weapp-vite', 'weapp-tailwindcss', 'varo', 'weapp-sqlite', 'vite-plugin-taro']) {
await page.goto(`${prefix}/projects/${slug}/`)
- await expect(page.getByRole('link', { name: prefix ? 'Back to projects' : '返回项目列表', exact: true })).toHaveAttribute('href', `${prefix}/projects/`)
+ await expect(page.getByRole('link', { name: prefix ? 'Back to the stack' : '返回工具栈', exact: true })).toHaveAttribute('href', `${prefix}/projects/`)
await expect(page.locator('section[aria-labelledby="project-title"]')).toHaveCount(1)
await expect(page.locator('section[aria-labelledby="project-faq-title"]')).toHaveCount(1)
await expect(page.locator('section[aria-labelledby="project-future-docs-title"]')).toHaveCount(1)
@@ -270,11 +249,11 @@ test.describe('project catalog without JavaScript', () => {
await page.locator('[data-project-card][data-role="data"] .projects-index-actions a').last().click()
await expect(page).toHaveURL(`${prefix}/projects/weapp-sqlite/`)
await expect(page.getByRole('heading', { level: 1 })).toHaveText('weapp-sqlite')
- await expect(page.getByRole('region', { name: prefix ? 'Integration status' : '接入状态', exact: true })).toBeVisible()
+ await expect(page.getByRole('region', { name: prefix ? 'Project data' : '项目数据', exact: true })).toBeVisible()
await expect(page.locator('main figure')).toHaveCount(0)
await expect(page.locator('.project-proof-panel')).toBeVisible()
await expect(page.locator('.roadmap-strip')).toBeVisible()
- const back = page.getByRole('link', { name: prefix ? 'Back to projects' : '返回项目列表', exact: true })
+ const back = page.getByRole('link', { name: prefix ? 'Back to the stack' : '返回工具栈', exact: true })
await back.focus()
await page.keyboard.press('Enter')
await expect(page).toHaveURL(`${prefix}/projects/`)
@@ -290,10 +269,10 @@ for (const width of [1440, 768, 390]) {
await page.emulateMedia({ colorScheme: theme, reducedMotion: 'reduce' })
await page.goto('/en/projects/weapp-sqlite/')
await expect(page.getByRole('heading', { level: 1, name: 'weapp-sqlite' })).toBeVisible()
- await expect(page.getByRole('region', { name: 'Integration status', exact: true })).toBeInViewport()
+ await expect(page.getByRole('region', { name: 'Project data', exact: true })).toBeVisible()
await expect(page.locator('main figure')).toHaveCount(0)
expect(await page.evaluate(() => document.documentElement.scrollWidth > innerWidth)).toBe(false)
- const readiness = page.getByText('Planned projects omit downloads and stars. Public numbers return after a stable release.', { exact: true })
+ const readiness = page.getByText('Stability and release status follow the project repository and version data.', { exact: true })
await expect(readiness).toHaveCount(1)
await page.screenshot({ path: testInfo.outputPath('planned-project-detail.png') })
})
@@ -307,10 +286,6 @@ for (const width of [1440, 768, 390]) {
const results = await new AxeBuilder({ page }).include('main').analyze()
expect(results.violations).toEqual([])
await page.screenshot({ path: testInfo.outputPath('project-catalog.png'), fullPage: true })
- await page.goto('/en/')
- await page.locator('.project-selector').scrollIntoViewIfNeeded()
- expect(await page.evaluate(() => document.documentElement.scrollWidth > innerWidth)).toBe(false)
- await page.locator('.project-selector').screenshot({ path: testInfo.outputPath('project-paths.png'), style: '[data-site-header], body > a[href="#main-content"] { visibility: hidden !important; }' })
})
}
}
diff --git a/apps/web/tests/e2e/site.spec.ts b/apps/web/tests/e2e/site.spec.ts
index 7bd43d7..4d75d96 100644
--- a/apps/web/tests/e2e/site.spec.ts
+++ b/apps/web/tests/e2e/site.spec.ts
@@ -5,7 +5,7 @@ import tailwindProject from '../../src/content/projects/weapp-tailwindcss.json'
import viteProject from '../../src/content/projects/weapp-vite.json' with { type: 'json' }
import { siteCopy } from '../../src/i18n/ui'
-const projectDefinitions = [tailwindProject, viteProject, varoProject]
+const projectDefinitions = [viteProject, tailwindProject, varoProject]
const retiredVisuals = 'canvas, [data-shader-canvas], [data-shader], [data-shader-frame], [data-webgl-fallback], [data-art], .project-art, [class^="art-"], [class*=" art-"]'
async function expectHomeVisuals(page: import('@playwright/test').Page, locale: 'zh-CN' | 'en') {
@@ -77,29 +77,31 @@ test('renders the bilingual ecosystem home with valid metadata', async ({ page }
const docsLinks = page.locator('#projects').getByRole('link', { name: '阅读文档' })
await expect(docsLinks).toHaveCount(3)
await expect(docsLinks.evaluateAll(links => links.map(link => link.getAttribute('href')))).resolves.toEqual([
- 'https://tw.weapp.dev/',
'https://vite.weapp.dev/',
- 'https://github.com/daguanren21/Varo#readme',
+ 'https://tw.weapp.dev/',
+ 'https://daguanren21.github.io/Varo/',
])
const projectHomeLinks = page.locator('.home-project-rail a')
await expect(projectHomeLinks.evaluateAll(links => links.map(link => ({ href: link.getAttribute('href'), target: link.getAttribute('target'), rel: link.getAttribute('rel') })))).resolves.toEqual([
- { href: 'https://tw.weapp.dev/', target: '_blank', rel: 'noreferrer' },
- { href: 'https://vite.weapp.dev/', target: '_blank', rel: 'noreferrer' },
- { href: 'https://github.com/daguanren21/Varo#readme', target: '_blank', rel: 'noreferrer' },
+ { href: 'https://vite.weapp.dev/', target: '_blank', rel: 'noopener noreferrer' },
+ { href: 'https://tw.weapp.dev/', target: '_blank', rel: 'noopener noreferrer' },
+ { href: 'https://daguanren21.github.io/Varo/', target: '_blank', rel: 'noopener noreferrer' },
+ { href: 'https://github.com/weapp-sqlite/weapp-sqlite#readme', target: '_blank', rel: 'noopener noreferrer' },
+ { href: 'https://vpt.js.org/', target: '_blank', rel: 'noopener noreferrer' },
])
await expect(page.locator('.home-project-visual-link').evaluateAll(links => links.map(link => link.getAttribute('href')))).resolves.toEqual([
- 'https://tw.weapp.dev/',
'https://vite.weapp.dev/',
- 'https://github.com/daguanren21/Varo#readme',
+ 'https://tw.weapp.dev/',
+ 'https://daguanren21.github.io/Varo/',
])
await expect(page.locator('.home-project-title-link').evaluateAll(links => links.map(link => link.getAttribute('href')))).resolves.toEqual([
- 'https://tw.weapp.dev/',
'https://vite.weapp.dev/',
- 'https://github.com/daguanren21/Varo#readme',
+ 'https://tw.weapp.dev/',
+ 'https://daguanren21.github.io/Varo/',
])
await expect(page.locator('#projects a[data-analytics-event="select_project"]').evaluateAll(links => links.map(link => link.getAttribute('href')))).resolves.toEqual([
- '/projects/weapp-tailwindcss/',
'/projects/weapp-vite/',
+ '/projects/weapp-tailwindcss/',
'/projects/varo/',
])
@@ -110,14 +112,16 @@ test('renders the bilingual ecosystem home with valid metadata', async ({ page }
await expect(page.locator('link[rel="canonical"]')).toHaveAttribute('href', 'https://weapp.dev/en/')
await expect(page.locator('link[hreflang="zh-CN"]')).toHaveAttribute('href', 'https://weapp.dev/')
await expect(page.locator('#projects a[data-analytics-event="select_project"]').evaluateAll(links => links.map(link => link.getAttribute('href')))).resolves.toEqual([
- '/en/projects/weapp-tailwindcss/',
'/en/projects/weapp-vite/',
+ '/en/projects/weapp-tailwindcss/',
'/en/projects/varo/',
])
await expect(page.locator('.home-project-rail a').evaluateAll(links => links.map(link => link.getAttribute('href')))).resolves.toEqual([
- 'https://tw.weapp.dev/',
'https://vite.weapp.dev/',
- 'https://github.com/daguanren21/Varo#readme',
+ 'https://tw.weapp.dev/',
+ 'https://daguanren21.github.io/Varo/',
+ 'https://github.com/weapp-sqlite/weapp-sqlite#readme',
+ 'https://vpt.js.org/',
])
})
@@ -223,7 +227,7 @@ test('project detail exposes docs, source, metrics, and future path', async ({ p
await expect(page.getByText('/docs/weapp-vite/')).toBeVisible()
await expect(page.getByText('GitHub Stars')).toBeVisible()
await expect(page.getByRole('heading', { name: '常见问题' })).toBeVisible()
- await expect(page.locator('pre code')).toContainText('pnpm add -D weapp-vite')
+ await expect(page.getByLabel('安装命令', { exact: true })).toContainText('pnpm add -D weapp-vite')
await expect(page.getByRole('link', { name: '查看 npm' })).toHaveAttribute('href', 'https://www.npmjs.com/package/weapp-vite')
await expect(page.locator('script[type="application/ld+json"]')).toHaveCount(3)
})
@@ -241,13 +245,13 @@ test('publishes indexable SEO resources and keeps 404 out of the index', async (
await expect(page.locator('meta[name="robots"]')).toHaveAttribute('content', 'noindex, follow')
})
-test('planned project exposes complete placeholder release data', async ({ page }) => {
+test('published Varo project exposes current release data', async ({ page }) => {
await page.goto('/projects/varo/')
await expect(page.getByRole('heading', { level: 1, name: 'Varo' })).toBeVisible()
await expect(page.getByRole('link', { name: '查看源码' })).toHaveAttribute('href', 'https://github.com/daguanren21/Varo')
- await expect(page.getByRole('link', { name: '阅读文档' }).first()).toHaveAttribute('href', 'https://github.com/daguanren21/Varo#readme')
- await expect(page.getByText('@varo/cli')).toBeVisible()
- await expect(page.getByText('v0.0.1')).toBeVisible()
+ await expect(page.getByRole('link', { name: '阅读文档' }).first()).toHaveAttribute('href', 'https://daguanren21.github.io/Varo/')
+ await expect(page.getByLabel('安装命令', { exact: true })).toContainText('pnpm dlx @varo-ui/cli add --target weapp button input card')
+ await expect(page.getByText('v2.1.0')).toBeVisible()
await expect(page.getByText('/docs/varo/')).toBeVisible()
await expect(page.getByText('GitHub Stars')).toBeVisible()
})
diff --git a/apps/web/tests/e2e/sponsors.spec.ts b/apps/web/tests/e2e/sponsors.spec.ts
index 507ccb6..05e0c3e 100644
--- a/apps/web/tests/e2e/sponsors.spec.ts
+++ b/apps/web/tests/e2e/sponsors.spec.ts
@@ -274,15 +274,3 @@ test('keeps filters and canvases when the user switches theme', async ({ page })
await expect(graphs.locator('[data-status]')).toHaveText('1 个节点')
await expect(graphs.locator('canvas')).toHaveCount(2)
})
-
-test('shows a sponsor initial when an external avatar fails', async ({ page }) => {
- await page.goto('/pricing/')
- const image = page.locator('.pricing-public-sponsor img').first()
- if (await image.count() === 0) {
- test.skip()
- }
- const fallback = image.locator('xpath=following-sibling::span[1]')
- await image.evaluate(element => element.dispatchEvent(new Event('error')))
- await expect(image).toBeHidden()
- await expect(fallback).toBeVisible()
-})