Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
name: CI

on:
pull_request:
branches: [main]
push:
branches: [main]

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
verify:
runs-on: ubuntu-24.04
timeout-minutes: 20

steps:
- name: Check out the repository
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- name: Set up pnpm
uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4
with:
version: 10.33.4

- name: Set up Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version-file: .node-version
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Run static checks and unit tests
run: pnpm check

- name: Build and validate the static site
run: pnpm --filter @weapp.dev/web build

- name: Install the Playwright browser
run: pnpm --filter @weapp.dev/web exec playwright install --with-deps chromium

- name: Run end-to-end tests
run: pnpm --filter @weapp.dev/web test:e2e
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,9 +12,9 @@
"lint": "eslint .",
"lint:styles": "stylelint 'src/**/*.css'",
"metrics": "tsx scripts/generate-metrics.ts",
"metrics:sync": "tsx scripts/generate-metrics.ts --update-fallback --require-fresh",
"media:generate": "tsx scripts/generate-media.ts",
"metrics:update-fallback": "tsx scripts/generate-metrics.ts --update-fallback",
"metrics:sync": "tsx scripts/generate-metrics.ts --update-fallback --require-fresh",
"og:generate": "tsx scripts/generate-og.ts",
"preview": "astro preview",
"test": "vitest run",
Expand Down
9 changes: 9 additions & 0 deletions apps/web/scripts/generate-metrics.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,6 +8,7 @@ interface ProjectSource {
slug: string
packageName: string
github: string
npmUrl?: string
}

const root = resolve(import.meta.dirname, '..')
Expand All@@ -26,6 +27,7 @@ async function loadProjectSources(): Promise<ProjectSource[]> {
slug: basename(file, '.json'),
packageName: definition.packageName,
github: definition.github,
npmUrl: typeof definition.npmUrl === 'string' ? definition.npmUrl : undefined,
}
}))
}
Expand DownExpand Up@@ -85,6 +87,13 @@ const requireFresh = process.argv.includes('--require-fresh')
const updateFallback = process.argv.includes('--update-fallback')

await Promise.all(projectSources.map(async (project) => {
if (!project.npmUrl) {
if (!fallback[project.slug]) {
failures.push(project.slug)
}
console.log(`Using fallback metrics for ${project.slug}: no public npm package`)
return
}
try {
next[project.slug] = await fetchMetrics(project)
console.log(`Updated metrics for ${project.slug}`)
Expand Down
13 changes: 13 additions & 0 deletions apps/web/src/components/Header.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -92,4 +92,17 @@ const navLink = 'inline-flex items-center gap-1.5 whitespace-nowrap py-2 text-sm
document.querySelectorAll('[data-mobile-menu] nav a').forEach((link) => {
link.addEventListener('click', () => link.closest('details')?.removeAttribute('open'))
})

document.querySelectorAll('[data-mobile-menu]').forEach((menu) => {
menu.addEventListener('toggle', () => {
if (!menu.open) return
const closeOnEscape = (event) => {
if (event.key !== 'Escape') return
menu.removeAttribute('open')
menu.querySelector('summary')?.focus()
document.removeEventListener('keydown', closeOnEscape)
}
document.addEventListener('keydown', closeOnEscape)
})
})
</script>
27 changes: 10 additions & 17 deletions apps/web/src/components/HomePage.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,8 +19,8 @@ const numberLocale = locale === 'zh-CN' ? 'zh-CN' : 'en-US'
const stepIcons = [Layers2, ScanLine, Package]
const principleIcons = [Layers2, ShieldCheck, BadgeCheck]
const projectStages: Record<string, string> = locale === 'zh-CN'
? { 'weapp-tailwindcss': '样式', 'weapp-vite': '构建', varo: '组件' }
: { 'weapp-tailwindcss': 'STYLE', 'weapp-vite': 'BUILD', varo: 'COMPOSE' }
? { 'weapp-tailwindcss': '样式', 'weapp-vite': '构建', varo: '组件', 'weapp-sqlite': '数据' }
: { 'weapp-tailwindcss': 'STYLE', 'weapp-vite': 'BUILD', varo: 'COMPOSE', 'weapp-sqlite': 'DATA' }
---

<main id="main-content">
Expand DownExpand Up@@ -105,16 +105,11 @@ const projectStages: Record<string, string> = locale === 'zh-CN'
<a class:list={['home-project-visual-link', index === 1 ? 'order-2 max-[800px]:order-none' : '']} href={project.data.docsUrl} target="_blank" rel="noreferrer" data-analytics-event="click_outbound" data-analytics-target="project_home_visual" data-analytics-project={project.id} aria-label={locale === 'zh-CN' ? `打开 ${content.name} 官方站点` : `Open ${content.name} official site`}>
<figure data-reveal data-project-visual class="relative m-0 overflow-hidden rounded-panel border border-line bg-panel-soft">
<div class="project-art" data-art={project.id} data-shader-frame aria-label={visualCopy.alt}>
<ShaderCanvas
preset={project.id === 'weapp-tailwindcss' ? 'marble' : project.id === 'weapp-vite' ? 'tunnel' : 'orbit'}
label={visualCopy.alt}
class="project-shader"
scale={0.72}
/>
<div class="art-chrome"><span></span><span></span><span></span><b>{project.data.packageName}</b></div>
{project.id === 'weapp-tailwindcss' && <div class="art-tailwind"><div class="art-sidebar"><i></i><i></i><i></i><i></i></div><div class="art-canvas"><strong>utility-first</strong><span class="art-line w-4/5"></span><span class="art-line w-3/5"></span><span class="art-line w-11/12"></span><div class="art-chip-row"><em>p-4</em><em>flex</em><em>gap-2</em></div></div></div>}
{project.id === 'weapp-vite' && <div class="art-vite"><div class="art-terminal"><span class="art-prompt">$</span> vite build --mode weapp<strong>✓ built in 1.42s</strong><small>dist/weapp / 24 modules</small></div><div class="art-bars"><i></i><i></i><i></i><i></i><i></i></div></div>}
{project.id === 'varo' && <div class="art-varo"><div class="art-component"><span class="art-avatar"></span><span class="art-line w-3/5"></span><span class="art-line w-4/5"></span><button type="button">Install block</button></div><div class="art-registry"><i></i><i></i><i></i><i></i><i></i><i></i></div></div>}
<picture>
<source srcset={visual.avif} type="image/avif" />
<img class="size-full object-cover object-top" src={visual.src} width={visual.width} height={visual.height} alt={visualCopy.alt} loading="lazy" />
</picture>
<span class="project-art-label">{project.data.packageName}</span>
</div>
<figcaption class="border-t border-line bg-panel px-4 py-3 text-xs text-copy-muted">{visualCopy.caption}</figcaption>
</figure>
Expand DownExpand Up@@ -151,6 +146,7 @@ const projectStages: Record<string, string> = locale === 'zh-CN'
)
})}
</div>

</section>

<section class="border-y border-line bg-panel-soft" id="commercial">
Expand DownExpand Up@@ -217,9 +213,9 @@ const projectStages: Record<string, string> = locale === 'zh-CN'
<p class="mb-0 text-xs text-copy-muted">{copy.releases.released} {formatReleaseDate(projectMetrics.releasedAt, numberLocale)}</p>
</div>
<strong class="font-mono text-sm">v{projectMetrics.version}</strong>
<a class:list={[iconControl, 'max-[520px]:hidden']} href={`https://www.npmjs.com/package/${project.data.packageName}`} aria-label={`${copy.releases.viewPackage}: ${project.data.packageName}`} target="_blank" rel="noreferrer" data-analytics-event="click_outbound" data-analytics-target="package" data-analytics-project={project.id}>
{project.data.npmUrl && <a class:list={[iconControl, 'max-[520px]:hidden']} href={project.data.npmUrl} aria-label={`${copy.releases.viewPackage}: ${project.data.packageName}`} target="_blank" rel="noreferrer" data-analytics-event="click_outbound" data-analytics-target="package" data-analytics-project={project.id}>
<ArrowUpRight size={19} stroke-width={1.8} aria-hidden="true" />
</a>
</a>}
</article>
)
})}
Expand DownExpand Up@@ -258,8 +254,5 @@ const projectStages: Record<string, string> = locale === 'zh-CN'
.home-project-link, .home-project-link:first-child { grid-template-columns: 1.4rem 2rem minmax(0, 1fr) auto; padding: .85rem 0; border-right: 0; border-bottom: 1px solid color-mix(in srgb, var(--surface) 18%, transparent); }
.home-project-link:last-child { border-bottom: 0; }
.home-project-link img { width: 2rem; height: 2rem; }
.art-vite, .art-varo { padding: .85rem; }
.art-component { padding: .85rem; }
.art-canvas { padding: 1rem; }
}
</style>
4 changes: 2 additions & 2 deletions apps/web/src/components/ProjectPage.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,10 +48,10 @@ const secondaryVisualCopy = secondaryVisual.locales[locale]
<GitFork size={18} stroke-width={1.9} aria-hidden="true" />
{copy.project.source}
</a>
<a class={buttonSecondary} href={project.data.npmUrl} target="_blank" rel="noreferrer" data-analytics-event="click_outbound" data-analytics-target="package" data-analytics-project={project.id}>
{project.data.npmUrl && <a class={buttonSecondary} href={project.data.npmUrl} target="_blank" rel="noreferrer" data-analytics-event="click_outbound" data-analytics-target="package" data-analytics-project={project.id}>
<Package size={18} stroke-width={1.9} aria-hidden="true" />
{copy.project.npm}
</a>
</a>}
</div>
</div>

Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/content.config.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -34,7 +34,7 @@ const projects = defineCollection({
packageName: z.string().min(1),
github: z.string().regex(/^[\w.-]+\/[\w.-]+$/),
docsUrl: z.url(),
npmUrl: z.url(),
npmUrl: z.url().optional(),
license: z.url().optional(),
maintainer: z.string().min(1),
keywords: z.array(z.string().min(1)).min(1),
Expand Down
21 changes: 17 additions & 4 deletions apps/web/src/content.test.ts
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
import { describe, expect, it } from 'vitest'
import varo from './content/projects/varo.json'
import sqlite from './content/projects/weapp-sqlite.json'
import tailwind from './content/projects/weapp-tailwindcss.json'
import vite from './content/projects/weapp-vite.json'

describe('project definitions', () => {
const projects = [tailwind, vite, varo]
const projects = [tailwind, vite, sqlite, varo]
const officialDocsUrls: Record<string, string> = {
'weapp-tailwindcss': 'https://tw.weapp.dev/',
'weapp-vite': 'https://vite.weapp.dev/',
'weapp-sqlite': 'https://sqlite.weapp.dev/',
'@varo-ui/cli': 'https://daguanren21.github.io/Varo/',
}

Expand All@@ -21,15 +23,16 @@ describe('project definitions', () => {
expect(project.locales[locale].capabilities.length).toBeGreaterThan(0)
expect(project.locales[locale].faqs.length).toBeGreaterThan(0)
}
expect(project.npmUrl).toMatch(/^https:\/\//)
const npmUrl = 'npmUrl' in project ? project.npmUrl : undefined
npmUrl && expect(npmUrl).toMatch(/^https:\/\//)
const license = 'license' in project ? project.license : undefined
expect(project.status === 'planned' || license).toBeTruthy()
license && expect(license).toMatch(/^https:\/\//)
expect(project.installCommand).toContain(project.packageName)
expect(project.keywords.length).toBeGreaterThan(0)
for (const visual of Object.values(project.visuals)) {
expect(visual.src).toMatch(/^\/media\/projects\/.+\.webp$/)
expect(visual.avif).toMatch(/^\/media\/projects\/.+\.avif$/)
expect(visual.src).toMatch(/^\/media\/(projects|brand)\/.+\.webp$/)
expect(visual.avif).toMatch(/^\/media\/(projects|brand)\/.+\.avif$/)
expect(visual.width).toBeGreaterThan(0)
expect(visual.height).toBeGreaterThan(0)
expect(visual.locales['zh-CN'].alt).not.toHaveLength(0)
Expand All@@ -56,4 +59,14 @@ describe('project definitions', () => {
installCommand: 'pnpm dlx @varo-ui/cli add --target weapp button input card',
})
})

it('marks weapp-sqlite as beta without a public npm package', () => {
expect(sqlite).toMatchObject({
status: 'beta',
packageName: 'weapp-sqlite',
github: 'weapp-sqlite/weapp-sqlite',
docsUrl: 'https://sqlite.weapp.dev/',
})
expect('npmUrl' in sqlite ? sqlite.npmUrl : undefined).toBeUndefined()
})
})
2 changes: 1 addition & 1 deletion apps/web/src/content/projects/varo.json
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
{
"order": 3,
"order": 4,
"status": "stable",
"packageName": "@varo-ui/cli",
"github": "daguanren21/Varo",
Expand Down
63 changes: 63 additions & 0 deletions apps/web/src/content/projects/weapp-sqlite.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
{
"order": 3,
"status": "beta",
"packageName": "weapp-sqlite",
"github": "weapp-sqlite/weapp-sqlite",
"docsUrl": "https://sqlite.weapp.dev/",
"license": "https://opensource.org/license/mit",
"maintainer": "weapp-sqlite contributors",
"keywords": ["SQLite", "WASM", "mini-program", "Web runtime", "local data"],
"installCommand": "pnpm add weapp-sqlite",
"futureDocsPath": "/docs/weapp-sqlite/",
"logo": "/logo.svg",
"accent": "#d6a528",
"platforms": ["WeChat", "Web", "weapp-vite"],
"visuals": {
"primary": {
"src": "/media/brand/build-lens.webp",
"avif": "/media/brand/build-lens.avif",
"width": 1280,
"height": 916,
"locales": {
"zh-CN": { "alt": "weapp-sqlite 本地数据层与运行时构建视觉", "caption": "weapp-sqlite 当前处于 Beta 阶段,持续验证本地 SQLite 数据能力。" },
"en": { "alt": "weapp-sqlite local data layer and runtime build visual", "caption": "weapp-sqlite is currently in Beta while its local SQLite data layer is being validated." }
}
},
"secondary": {
"src": "/media/brand/build-lens.webp",
"avif": "/media/brand/build-lens.avif",
"width": 1280,
"height": 916,
"locales": {
"zh-CN": { "alt": "weapp-sqlite 构建与运行时验证视觉", "caption": "先在真实运行时验证,再逐步扩大平台支持范围。" },
"en": { "alt": "weapp-sqlite build and runtime validation visual", "caption": "Validate the runtime first, then expand platform coverage step by step." }
}
}
},
"locales": {
"zh-CN": {
"name": "weapp-sqlite",
"tagline": "把本地 SQLite 能力带到多端运行时",
"description": "面向小程序与 Web runtime 的本地数据层,当前处于 Beta 阶段,API 与平台支持仍在持续验证。",
"audience": "需要在小程序和 Web runtime 中共享本地数据能力、并愿意参与 Beta 验证的工程团队。",
"useCases": ["在多端运行时读写本地 SQLite 数据", "为离线或弱网场景提供可复用的数据层", "在 weapp-vite 工程中验证本地数据能力"],
"capabilities": ["本地 SQLite 数据层", "WebAssembly runtime", "多端运行时验证", "Beta API 迭代"],
"faqs": [
{ "question": "weapp-sqlite 当前可以用于生产吗?", "answer": "weapp-sqlite 当前处于 Beta 阶段,API、平台覆盖和运行时边界仍在验证。正式生产接入前请先根据项目风险进行评估。" },
{ "question": "在哪里查看最新进展?", "answer": "请访问 sqlite.weapp.dev 查看文档与最新说明,也可以在 GitHub 仓库提交反馈和问题。" }
]
},
"en": {
"name": "weapp-sqlite",
"tagline": "Bring local SQLite data to multi-platform runtimes",
"description": "A local data layer for mini-apps and the Web runtime. It is currently in Beta while APIs and platform support are being validated.",
"audience": "Engineering teams that need shared local data across mini-app and Web runtimes and are willing to validate a Beta tool.",
"useCases": ["Read and write local SQLite data across runtimes", "Support offline or weak-network workflows", "Validate local data capabilities in weapp-vite projects"],
"capabilities": ["Local SQLite data layer", "WebAssembly runtime", "Multi-runtime validation", "Iterating Beta APIs"],
"faqs": [
{ "question": "Is weapp-sqlite ready for production?", "answer": "weapp-sqlite is currently in Beta. Its APIs, platform coverage, and runtime boundaries are still being validated, so assess the risk before production adoption." },
{ "question": "Where can I follow the latest progress?", "answer": "Visit sqlite.weapp.dev for documentation and current notes, or open an issue in the GitHub repository." }
]
}
}
}
7 changes: 7 additions & 0 deletions apps/web/src/data/project-metrics.fallback.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,5 +19,12 @@
"stars": 2,
"weeklyDownloads": 561,
"fetchedAt": "2026-09-02T03:50:32.074Z"
},
"weapp-sqlite": {
"version": "0.0.0-beta",
"releasedAt": "2026-08-26T00:00:00.000Z",
"stars": 0,
"weeklyDownloads": 0,
"fetchedAt": "2026-08-26T00:00:00.000Z"
}
}
Loading
Loading