diff --git a/website/docs/.vitepress/config.ts b/website/docs/.vitepress/config.ts
index f1c3658..468a4b2 100644
--- a/website/docs/.vitepress/config.ts
+++ b/website/docs/.vitepress/config.ts
@@ -5,12 +5,16 @@ const SITE_URL = 'https://bvm-core.pages.dev';
export default defineConfig({
head: [
['meta', { name: 'viewport', content: 'width=device-width,initial-scale=1' }],
- ['link', { rel: 'icon', type: 'image/svg+xml', href: '/logo.svg' }],
+ ['link', { rel: 'icon', type: 'image/svg+xml', href: '/favicon.svg' }],
+ ['link', { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon-32.png' }],
+ ['link', { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicon-16.png' }],
+ ['link', { rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' }],
+ ['link', { rel: 'manifest', href: '/site.webmanifest' }],
['meta', { property: 'og:site_name', content: 'BVM' }],
['meta', { property: 'og:type', content: 'website' }],
- ['meta', { property: 'og:image', content: `${SITE_URL}/logo.svg` }],
- ['meta', { name: 'twitter:card', content: 'summary' }],
- ['meta', { name: 'twitter:image', content: `${SITE_URL}/logo.svg` }],
+ ['meta', { property: 'og:image', content: `${SITE_URL}/og.png` }],
+ ['meta', { name: 'twitter:card', content: 'summary_large_image' }],
+ ['meta', { name: 'twitter:image', content: `${SITE_URL}/og.png` }],
],
cleanUrls: true,
lastUpdated: true,
diff --git a/website/docs/index.md b/website/docs/index.md
index eae6446..bd06eb4 100644
--- a/website/docs/index.md
+++ b/website/docs/index.md
@@ -15,6 +15,9 @@ hero:
- theme: alt
text: 中文
link: /zh/
+ - theme: alt
+ text: Troubleshooting
+ link: /guide/troubleshooting
- theme: alt
text: View on GitHub
link: https://github.com/EricLLLLLL/bvm
@@ -86,6 +89,44 @@ const copy = (text, type) => {
+
+
Install methods (choose the best fit)
+
+
+
+ | Method |
+ Best for |
+ Notes |
+
+
+
+
+ | Shell (macOS/Linux) |
+ Most users |
+ Fastest mirror + auto setup |
+
+
+ | PowerShell (Windows) |
+ Windows dev |
+ Same flow as Unix installer |
+
+
+ | NPM |
+ Already using Node |
+ Runs postinstall; reopen terminal may be needed |
+
+
+
+
+
+
+
+
Having trouble with global isolation?
+
If tools still come from ~/.bun, run bvm setup and verify which bun points to BVM shims.
+
Open Troubleshooting →
+
+
+
Install methods (animated)
@@ -186,6 +227,74 @@ const copy = (text, type) => {
background: var(--vp-c-text-3);
}
+.compare-section {
+ margin-top: 3.5rem;
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 1rem;
+}
+
+.compare-table {
+ width: 100%;
+ max-width: 900px;
+ border-collapse: collapse;
+ border: 1px solid var(--vp-c-divider);
+ border-radius: 12px;
+ overflow: hidden;
+ background: var(--vp-c-bg-alt);
+}
+
+.compare-table th,
+.compare-table td {
+ padding: 0.75rem 0.9rem;
+ border-bottom: 1px solid var(--vp-c-divider);
+ vertical-align: top;
+}
+
+.compare-table th {
+ text-align: left;
+ background: var(--vp-c-bg-soft);
+ font-size: 0.9rem;
+}
+
+.compare-table td {
+ font-size: 0.95rem;
+ color: var(--vp-c-text-1);
+}
+
+.callout-section {
+ margin-top: 2rem;
+ display: flex;
+ justify-content: center;
+}
+
+.callout-card {
+ width: 100%;
+ max-width: 900px;
+ border: 1px solid var(--vp-c-divider);
+ background: var(--vp-c-bg-soft);
+ border-radius: 12px;
+ padding: 1rem 1.1rem;
+}
+
+.callout-title {
+ font-weight: 700;
+ color: var(--vp-c-text-1);
+ margin-bottom: 0.35rem;
+}
+
+.callout-body {
+ color: var(--vp-c-text-2);
+ margin-bottom: 0.6rem;
+}
+
+.callout-link {
+ color: var(--vp-c-brand-1);
+ font-weight: 600;
+}
+
.demo-section {
margin-top: 3.5rem;
display: flex;
diff --git a/website/docs/public/_headers b/website/docs/public/_headers
new file mode 100644
index 0000000..dcbcdc4
--- /dev/null
+++ b/website/docs/public/_headers
@@ -0,0 +1,31 @@
+# Default: no aggressive caching for HTML
+/*
+ Cache-Control: public, max-age=0, must-revalidate
+
+# VitePress hashed assets (immutable)
+/assets/*
+ Cache-Control: public, max-age=31536000, immutable
+
+# Large media (immutable)
+/media/*
+ Cache-Control: public, max-age=31536000, immutable
+
+# Icons and manifests (immutable)
+/favicon*
+ Cache-Control: public, max-age=31536000, immutable
+
+/apple-touch-icon.png
+ Cache-Control: public, max-age=31536000, immutable
+
+/icon-*.png
+ Cache-Control: public, max-age=31536000, immutable
+
+/site.webmanifest
+ Cache-Control: public, max-age=31536000, immutable
+
+/logo.svg
+ Cache-Control: public, max-age=31536000, immutable
+
+/og.png
+ Cache-Control: public, max-age=31536000, immutable
+
diff --git a/website/docs/public/apple-touch-icon.png b/website/docs/public/apple-touch-icon.png
new file mode 100644
index 0000000..1ff550c
Binary files /dev/null and b/website/docs/public/apple-touch-icon.png differ
diff --git a/website/docs/public/favicon-16.png b/website/docs/public/favicon-16.png
new file mode 100644
index 0000000..19ba023
Binary files /dev/null and b/website/docs/public/favicon-16.png differ
diff --git a/website/docs/public/favicon-32.png b/website/docs/public/favicon-32.png
new file mode 100644
index 0000000..e10d52a
Binary files /dev/null and b/website/docs/public/favicon-32.png differ
diff --git a/website/docs/public/favicon.ico b/website/docs/public/favicon.ico
new file mode 100644
index 0000000..37130a0
Binary files /dev/null and b/website/docs/public/favicon.ico differ
diff --git a/website/docs/public/favicon.svg b/website/docs/public/favicon.svg
new file mode 100644
index 0000000..a22818f
--- /dev/null
+++ b/website/docs/public/favicon.svg
@@ -0,0 +1,20 @@
+
+
diff --git a/website/docs/public/icon-192.png b/website/docs/public/icon-192.png
new file mode 100644
index 0000000..34278fb
Binary files /dev/null and b/website/docs/public/icon-192.png differ
diff --git a/website/docs/public/icon-512.png b/website/docs/public/icon-512.png
new file mode 100644
index 0000000..a0658c6
Binary files /dev/null and b/website/docs/public/icon-512.png differ
diff --git a/website/docs/public/logo.svg b/website/docs/public/logo.svg
index 4081449..530cacd 100644
--- a/website/docs/public/logo.svg
+++ b/website/docs/public/logo.svg
@@ -10,32 +10,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
diff --git a/website/docs/public/media/bvm-install-methods.png b/website/docs/public/media/bvm-install-methods.png
new file mode 100644
index 0000000..8b1973f
Binary files /dev/null and b/website/docs/public/media/bvm-install-methods.png differ
diff --git a/website/docs/public/og.png b/website/docs/public/og.png
new file mode 100644
index 0000000..140adaf
Binary files /dev/null and b/website/docs/public/og.png differ
diff --git a/website/docs/public/site.webmanifest b/website/docs/public/site.webmanifest
new file mode 100644
index 0000000..a6a282f
--- /dev/null
+++ b/website/docs/public/site.webmanifest
@@ -0,0 +1,20 @@
+{
+ "name": "BVM",
+ "short_name": "BVM",
+ "icons": [
+ {
+ "src": "/icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "theme_color": "#f472b6",
+ "background_color": "#0b1220",
+ "display": "standalone"
+}
+
diff --git a/website/docs/zh/index.md b/website/docs/zh/index.md
index 9420682..9cdf290 100644
--- a/website/docs/zh/index.md
+++ b/website/docs/zh/index.md
@@ -12,6 +12,9 @@ hero:
- theme: brand
text: 快速开始
link: /zh/guide/getting-started
+ - theme: alt
+ text: 排障
+ link: /zh/guide/troubleshooting
- theme: alt
text: GitHub
link: https://github.com/EricLLLLLL/bvm
@@ -83,6 +86,44 @@ const copy = (text, type) => {
+
+
安装方式对比(怎么选)
+
+
+
+ | 方式 |
+ 适合谁 |
+ 备注 |
+
+
+
+
+ | Shell(macOS/Linux) |
+ 大多数用户 |
+ 自动竞速选最快源 + 自动 setup |
+
+
+ | PowerShell(Windows) |
+ Windows 开发 |
+ 与 Unix 安装体验一致 |
+
+
+ | NPM |
+ 已在用 Node/NPM |
+ 依赖 postinstall;可能需要重开终端 |
+
+
+
+
+
+
+
+
全局隔离不生效?
+
如果命令仍来自 ~/.bun,请运行一次 bvm setup,然后检查 which bun 是否命中 BVM shims。
+
打开排障文档 →
+
+
+
安装方式对比(动画)
@@ -174,6 +215,74 @@ const copy = (text, type) => {
color: white;
}
+.compare-section {
+ margin-top: 3.5rem;
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 1rem;
+}
+
+.compare-table {
+ width: 100%;
+ max-width: 900px;
+ border-collapse: collapse;
+ border: 1px solid var(--vp-c-divider);
+ border-radius: 12px;
+ overflow: hidden;
+ background: var(--vp-c-bg-alt);
+}
+
+.compare-table th,
+.compare-table td {
+ padding: 0.75rem 0.9rem;
+ border-bottom: 1px solid var(--vp-c-divider);
+ vertical-align: top;
+}
+
+.compare-table th {
+ text-align: left;
+ background: var(--vp-c-bg-soft);
+ font-size: 0.9rem;
+}
+
+.compare-table td {
+ font-size: 0.95rem;
+ color: var(--vp-c-text-1);
+}
+
+.callout-section {
+ margin-top: 2rem;
+ display: flex;
+ justify-content: center;
+}
+
+.callout-card {
+ width: 100%;
+ max-width: 900px;
+ border: 1px solid var(--vp-c-divider);
+ background: var(--vp-c-bg-soft);
+ border-radius: 12px;
+ padding: 1rem 1.1rem;
+}
+
+.callout-title {
+ font-weight: 700;
+ color: var(--vp-c-text-1);
+ margin-bottom: 0.35rem;
+}
+
+.callout-body {
+ color: var(--vp-c-text-2);
+ margin-bottom: 0.6rem;
+}
+
+.callout-link {
+ color: var(--vp-c-brand-1);
+ font-weight: 600;
+}
+
.demo-section {
margin-top: 3.5rem;
display: flex;
@@ -190,4 +299,3 @@ const copy = (text, type) => {
background: #000;
}
-
diff --git a/website/package.json b/website/package.json
index c9f22f3..6e60612 100644
--- a/website/package.json
+++ b/website/package.json
@@ -7,7 +7,10 @@
"sync-docs": "bun run sync-docs.ts",
"dev": "bun run sync-docs && vitepress dev docs",
"build": "bun run sync-docs && vitepress build docs",
- "preview": "vitepress preview docs"
+ "preview": "vitepress preview docs",
+ "gen:favicons": "node scripts/generate-favicons.mjs",
+ "gen:og": "node scripts/generate-og.mjs",
+ "gen:assets": "node scripts/generate-favicons.mjs && node scripts/generate-og.mjs"
},
"devDependencies": {
"@types/bun": "latest",
diff --git a/website/scripts/generate-favicons.mjs b/website/scripts/generate-favicons.mjs
new file mode 100644
index 0000000..b306569
--- /dev/null
+++ b/website/scripts/generate-favicons.mjs
@@ -0,0 +1,42 @@
+import { execFileSync } from 'node:child_process';
+import { mkdirSync } from 'node:fs';
+import { join } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const here = fileURLToPath(new URL('.', import.meta.url));
+const root = join(here, '..');
+const publicDir = join(root, 'docs', 'public');
+
+const svg = join(publicDir, 'favicon.svg');
+
+mkdirSync(publicDir, { recursive: true });
+
+function magick(args) {
+ execFileSync('magick', args, { stdio: 'inherit' });
+}
+
+// PNG + ICO from favicon.svg
+magick([svg, '-resize', '16x16', join(publicDir, 'favicon-16.png')]);
+magick([svg, '-resize', '32x32', join(publicDir, 'favicon-32.png')]);
+magick([svg, '-define', 'icon:auto-resize=16,32,48', join(publicDir, 'favicon.ico')]);
+
+// Apple touch icon: MUST be non-transparent (iOS)
+magick([
+ svg,
+ '-resize',
+ '180x180',
+ '-background',
+ '#f472b6',
+ '-alpha',
+ 'remove',
+ '-alpha',
+ 'off',
+ join(publicDir, 'apple-touch-icon.png'),
+]);
+
+// PWA icons
+magick([svg, '-resize', '192x192', join(publicDir, 'icon-192.png')]);
+magick([svg, '-resize', '512x512', join(publicDir, 'icon-512.png')]);
+
+console.log('✅ Favicons generated in website/docs/public/');
+
diff --git a/website/scripts/generate-og.mjs b/website/scripts/generate-og.mjs
new file mode 100644
index 0000000..34f7463
--- /dev/null
+++ b/website/scripts/generate-og.mjs
@@ -0,0 +1,89 @@
+import { execFileSync } from 'node:child_process';
+import { mkdirSync } from 'node:fs';
+import { join } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const here = fileURLToPath(new URL('.', import.meta.url));
+const root = join(here, '..');
+const publicDir = join(root, 'docs', 'public');
+
+const out = join(publicDir, 'og.png');
+const logo = join(publicDir, 'logo.svg');
+
+mkdirSync(publicDir, { recursive: true });
+
+// Note: Font availability differs across environments.
+// Use generic fonts to avoid ImageMagick warnings.
+execFileSync(
+ 'magick',
+ [
+ '-size',
+ '1200x630',
+ 'xc:#0b1220',
+ '(',
+ '-size',
+ '1200x630',
+ 'gradient:#0b1220-#1b2a4a',
+ '-rotate',
+ '90',
+ ')',
+ '-compose',
+ 'over',
+ '-composite',
+ '(',
+ logo,
+ '-resize',
+ '320x320',
+ ')',
+ '-geometry',
+ '+70+155',
+ '-compose',
+ 'over',
+ '-composite',
+ '-fill',
+ '#ffffff',
+ '-font',
+ 'Helvetica',
+ '-pointsize',
+ '64',
+ '-gravity',
+ 'northwest',
+ '-annotate',
+ '+420+170',
+ 'BVM',
+ '-fill',
+ '#cbd5e1',
+ '-pointsize',
+ '28',
+ '-annotate',
+ '+420+250',
+ 'Bun Version Manager · zero-dependency · cross-platform',
+ '-fill',
+ '#f472b6',
+ '-pointsize',
+ '30',
+ '-annotate',
+ '+420+330',
+ 'Install:',
+ '-fill',
+ '#e2e8f0',
+ '-font',
+ 'Courier',
+ '-pointsize',
+ '24',
+ '-annotate',
+ '+420+380',
+ 'curl -fsSL https://bvm-core.pages.dev/install | bash',
+ '-annotate',
+ '+420+418',
+ 'irm https://bvm-core.pages.dev/install | iex',
+ '-annotate',
+ '+420+456',
+ 'npm install -g bvm-core@latest --foreground-scripts',
+ out,
+ ],
+ { stdio: 'inherit' },
+);
+
+console.log(`✅ Wrote ${out}`);
+
diff --git a/website/scripts/generate-og.ts b/website/scripts/generate-og.ts
new file mode 100644
index 0000000..1b2bab8
--- /dev/null
+++ b/website/scripts/generate-og.ts
@@ -0,0 +1,27 @@
+import { $ } from 'bun';
+import { mkdirSync } from 'node:fs';
+import { join } from 'node:path';
+
+const root = join(import.meta.dir, '..');
+const publicDir = join(root, 'docs', 'public');
+
+const out = join(publicDir, 'og.png');
+const logo = join(publicDir, 'logo.svg');
+
+mkdirSync(publicDir, { recursive: true });
+
+// 1200x630 is the common OG size (Twitter/Discord/etc.)
+// Keep it simple & deterministic: ImageMagick renders the SVG and draws text.
+await $`magick -size 1200x630 xc:"#0b1220" \
+ ( -size 1200x630 gradient:"#0b1220-#1b2a4a" -rotate 90 ) -compose over -composite \
+ ( "${logo}" -resize 320x320 ) -geometry +70+155 -compose over -composite \
+ -fill "#ffffff" -font "Helvetica" -pointsize 64 -gravity northwest -annotate +420+170 "BVM" \
+ -fill "#cbd5e1" -pointsize 28 -annotate +420+250 "Bun Version Manager · zero-dependency · cross-platform" \
+ -fill "#f472b6" -pointsize 30 -annotate +420+330 "Install:" \
+ -fill "#e2e8f0" -font "Menlo" -pointsize 24 -annotate +420+380 "curl -fsSL https://bvm-core.pages.dev/install | bash" \
+ -annotate +420+418 "irm https://bvm-core.pages.dev/install | iex" \
+ -annotate +420+456 "npm install -g bvm-core@latest --foreground-scripts" \
+ "${out}"`;
+
+console.log(`✅ Wrote ${out}`);
+