diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
new file mode 100644
index 0000000..248d6ab
--- /dev/null
+++ b/.github/workflows/pages.yml
@@ -0,0 +1,41 @@
+name: deploy-site
+
+# Publishes the static showcase site in site/ to GitHub Pages.
+# One-time setup: repo Settings β Pages β Build and deployment β Source: GitHub Actions.
+on:
+ push:
+ branches: [main]
+ paths:
+ - "site/**"
+ - ".github/workflows/pages.yml"
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: pages
+ cancel-in-progress: true
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Configure Pages
+ uses: actions/configure-pages@v5
+
+ - name: Upload site artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: site
+
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.gitignore b/.gitignore
index b7364b1..c0cff62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,3 +30,6 @@ dist/
# Logs
*.log
/tmp/wcm*.log
+
+# Local screenshot previews of the showcase site (rendered on demand, not deployed)
+site/.preview/
diff --git a/README.md b/README.md
index 7575560..001ff55 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,13 @@ surviving restarts.
## What the menu looks like
+
+
+
+
+The whole app lives in your menu bar. Left- or right-click the icon for the
+popover above; the older text sketch below shows every action it exposes:
+
```
π¬ WC 2 β° 9:41
ββββββββββββββββββββββββββββββββββββββββ
@@ -83,6 +90,14 @@ automatically by CI whenever a new release is published. To remove it later,
`brew uninstall --cask wechat-multi` (add `--zap` to also delete clones and
their signed-in sessions).
+## Website
+
+A showcase site lives in [`site/`](site/) β a dependency-free static page you
+can deploy anywhere. It ships with both a GitHub Pages workflow and Vercel
+config; see [`site/README.md`](site/README.md) for details.
+
+[](https://vercel.com/new/clone?repository-url=https://github.com/ashinno/wechat-multi&root-directory=site&project-name=wechat-multi&repository-name=wechat-multi)
+
## Features
- π **Native menu bar app** β no Dock clutter, no Electron, ~190 KB binary
diff --git a/docs/menu-popover.png b/docs/menu-popover.png
new file mode 100644
index 0000000..4f4a758
Binary files /dev/null and b/docs/menu-popover.png differ
diff --git a/site/README.md b/site/README.md
new file mode 100644
index 0000000..1b9cff2
--- /dev/null
+++ b/site/README.md
@@ -0,0 +1,57 @@
+# WeChat Multi β showcase site
+
+A single-page, dependency-free static site that showcases the app. No build
+step: it's plain HTML, CSS, and a few lines of JS.
+
+```
+site/
+βββ index.html # the page
+βββ styles.css # design tokens mirror the app's Brand enum + slot palette
+βββ app.js # copy-to-clipboard buttons (progressive enhancement)
+βββ vercel.json # static config for Vercel (clean URLs, cache + security headers)
+βββ assets/
+ βββ icon.png # app icon (copied from docs/icon.png)
+ βββ favicon.svg # jade "stack" mark
+```
+
+## Preview locally
+
+```bash
+cd site
+python3 -m http.server 8000
+# open http://localhost:8000
+```
+
+Or just open `site/index.html` directly in a browser.
+
+## Deploy
+
+The site is a plain static folder, so any static host works. Two are wired up:
+
+### Vercel (recommended)
+
+[](https://vercel.com/new/clone?repository-url=https://github.com/ashinno/wechat-multi&root-directory=site&project-name=wechat-multi&repository-name=wechat-multi)
+
+The button above pre-fills the **Root Directory** as `site`, so Vercel serves
+this folder directly β no build step. `vercel.json` adds clean URLs plus cache
+and security headers.
+
+From the CLI instead:
+
+```bash
+cd site
+vercel # preview deploy
+vercel --prod # production deploy
+```
+
+> If you import the repo manually in the Vercel dashboard, set **Root
+> Directory β `site`** and framework preset **Other** (no build command).
+
+### GitHub Pages
+
+`.github/workflows/pages.yml` publishes this folder on every push to `main`
+that touches `site/`. One-time setup:
+
+> **Settings β Pages β Build and deployment β Source: GitHub Actions**
+
+Then the site goes live at `https://ashinno.github.io/wechat-multi/`.
diff --git a/site/app.js b/site/app.js
new file mode 100644
index 0000000..e4acb28
--- /dev/null
+++ b/site/app.js
@@ -0,0 +1,28 @@
+// Copy-to-clipboard for code blocks. Progressive enhancement only β the page
+// is fully functional (and the commands fully selectable) without JS.
+document.querySelectorAll(".copy").forEach((btn) => {
+ btn.addEventListener("click", async () => {
+ const code = btn.parentElement.querySelector("code");
+ if (!code) return;
+ const text = code.innerText.trim();
+ try {
+ await navigator.clipboard.writeText(text);
+ } catch {
+ // Fallback for older browsers / insecure contexts.
+ const range = document.createRange();
+ range.selectNodeContents(code);
+ const sel = window.getSelection();
+ sel.removeAllRanges();
+ sel.addRange(range);
+ try { document.execCommand("copy"); } catch {}
+ sel.removeAllRanges();
+ }
+ const original = btn.textContent;
+ btn.textContent = "Copied!";
+ btn.classList.add("is-copied");
+ setTimeout(() => {
+ btn.textContent = original;
+ btn.classList.remove("is-copied");
+ }, 1600);
+ });
+});
diff --git a/site/assets/favicon.svg b/site/assets/favicon.svg
new file mode 100644
index 0000000..4bc4513
--- /dev/null
+++ b/site/assets/favicon.svg
@@ -0,0 +1,16 @@
+
diff --git a/site/assets/icon.png b/site/assets/icon.png
new file mode 100644
index 0000000..8d87ea0
Binary files /dev/null and b/site/assets/icon.png differ
diff --git a/site/index.html b/site/index.html
new file mode 100644
index 0000000..6f7476b
--- /dev/null
+++ b/site/index.html
@@ -0,0 +1,293 @@
+
+
+
+
+
+ WeChat Multi β Run multiple WeChat accounts on macOS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Skip to content
+
+
+
+
+ WeChat Multi
+
+
+
+
+
+
+
+
+
+
+ macOS 13+ Β· Native Β· Open source
+
Run every WeChat account side by side on macOS.
+
+ WeChat for Mac only lets you launch one copy at a time. WeChat Multi
+ clones the app into isolated, uniquely-identified copies β so work, personal, two
+ phone numbers, a burner can each stay signed in, in their own window, from a single
+ menu bar icon.
+
Everything you'd expect from a native menu bar app β and nothing you wouldn't.
+
+
+
+
+
π
+
Native menu bar app
+
AppKit + SwiftUI, ~190 KB. No Dock clutter, no Electron, no background bloat.
+
+
+
β‘
+
One click to launch
+
Spin up a fresh, fully-isolated WeChat instance from the popover β βN and you're in.
+
+
+
π·οΈ
+
Per-slot custom names
+
Name a clone βWorkβ or βPersonalβ. The name shows up in Cmd+Tab and the Dock.
+
+
+
π¨
+
Color-coded avatars
+
Each clone gets a distinct dot color so you can tell instances apart at a glance.
+
+
+
+
+
+
+
π
+
Auto-detects updates
+
When WeChat updates itself, one click rebuilds stale clones β preserving every signed-in session.
+
+
+
π
+
Launch at login
+
Built on SMAppService β no helper app, persists across reboots.
+
+
+
πͺ
+
Manage every instance
+
Bring any window to the front, quit one instance, or quit them all. PIDs and start times listed live.
+
+
+
π
+
Isolated sessions
+
Each clone gets its own macOS sandbox container β separate logins, separate chat history.
+
+
+
+
+
+
+
+ How it works
+
Cloning, not cracking.
+
+ WeChat enforces a singleton: launch a second copy and it silently dies. WeChat Multi
+ sidesteps that by giving each instance its own identity β so macOS treats it as a
+ genuinely separate app.
+
+
+
+
+
+ 1
+
+
Copy-on-write clone
+
cp -Rc from /Applications/WeChat.app into ~/Applications/WeChat Multi/. APFS makes it instant and uses no extra disk until WeChat writes.
+
+
+
+ 2
+
+
Rewrite the identity
+
CFBundleIdentifier β com.wechatmulti.cloneN, plus your custom display name. A unique bundle ID means a fresh sandbox container.
+
+
+
+ 3
+
+
Re-sign & de-quarantine
+
Ad-hoc codesign (the original Tencent signature is invalidated by the plist edit) and strip the Gatekeeper quarantine flag.
+
+
+
+ 4
+
+
Launch in isolation
+
open -na the clone. WeChat's βanother instance is runningβ check never fires β it's a different app now.
+
+
+
+
+
+ The original /Applications/WeChat.app is left untouched β keep launching it
+ from the Dock as your βMain accountβ. This tool is unofficial and not affiliated with Tencent.
+
+
+
+
+
+
+ Install
+
Up and running in a minute.
+
Three ways in, all free. macOS 13 Ventura or later required.
+
+
+
+
+
Homebrew
+
The easiest path β and it auto-updates with each release.
+
+
+
brew tap ashinno/wechat-multi https://github.com/ashinno/wechat-multi
+brew install --cask wechat-multi
+
+
Both lines are required β the tap isn't optional, since the cask lives in this repo rather than homebrew/cask. Upgrade later with brew upgrade --cask wechat-multi.
+
+
+
+
Download the app
+
Grab the pre-built, universal .app from the latest release, then drag it into /Applications.
Needs Xcode Command Line Tools. swift test runs the 61-test core suite.
+
+
+
+
+
+
+
+
+ On the way
+
A Windows port is in development.
+
+ Windows has no app-bundle cloning, so the port uses a different technique β releasing
+ WeChat's named-mutex single-instance lock. It's a .NET core with native interop and a
+ tray app, already under windows/ with CI.
+