A Semantle-style Chinese word-guessing game where the entire semantic similarity model runs in your browser — zero backend, zero API key, zero network calls (after the model downloads once).
Stack: Next.js 14 (App Router) · TypeScript · Tailwind · @xenova/transformers + BAAI bge-small-zh-v1.5
Most Semantle clones run embeddings on a server (one API call per guess). GuessZi runs the same embedding model — BAAI bge-small-zh-v1.5, the Chinese retrieval benchmark — in WebAssembly inside the player's browser.
The result:
- Privacy: 100% — guesses never leave your device
- Cost: $0 — no inference budget, no rate limits, no abuse vectors
- Scale: infinite users with no infra
- Offline: works without network after first load
This is a tiny demonstration that production-quality NLP can ship as a static site when the model fits in 100 MB.
cd guesszi
npm install
npm run dev
# open http://localhost:3000No .env required. No API keys.
First visit downloads the semantic model (~100 MB) — subsequent visits load instantly from IndexedDB cache.
- Each day has a fixed target word (1–3 Chinese characters, deterministically chosen by date hash)
- Type any Chinese word — the game returns its semantic similarity to the target (0–100%)
- 0% = semantically unrelated or out of vocabulary
- 100% = correct
- Past guesses are sorted by similarity, highest first
- Unlimited guesses until you find it
app/
page.tsx # Main game page (client component)
layout.tsx
components/
GuessInput.tsx
GuessList.tsx
lib/
dictionary.ts # 100-word vocabulary + date-based target selector
embeddings.ts # transformers.js + bge-small-zh-v1.5 + cosine + 0-100% mapping
types.ts
- Client-side embedding inference — the entire semantic computation runs in the user's browser via
@xenova/transformers(ONNX runtime in WebAssembly). No backend, no per-call cost, full privacy. - BAAI bge-small-zh-v1.5 — the standard for Chinese retrieval embeddings, ~100 MB ONNX. State-of-the-art quality at a size that fits a static deploy.
- localStorage game-state persistence — refresh-safe.
- Similarity mapping — cosine 0.30–1.00 → 0–100% (linear; bge output is already L2-normalized).
- Deterministic daily target — date hash means everyone playing on the same day gets the same word.
- No API routes — fully statically prerendered Next.js, deployable to any static host.
npm i -g vercel
vercel login
vercel --prodNo environment variables to configure. Deploy gives you a URL like https://guesszi.vercel.app — playable on mobile out of the box.
| Metric | Value |
|---|---|
| First Load JS | 91.3 kB (lightweight shell) |
| Model wasm load | ~100 MB, 30–60 s first visit (cached after) |
| Per-guess inference (laptop) | ~50 ms |
| Per-guess inference (phone) | ~200 ms |
| Per-guess cost | $0 (no API calls) |
- Theme modes (idioms / classical poetry / slang)
- LLM hints when stuck — calls hosted LLM only on explicit "give me a hint" tap (still no per-guess API cost)
- Association-chain visualisation: render past guesses as a semantic path toward the target
- Daily leaderboard (requires lightweight backend)
- PWA / offline support
- Share-result feature like Wordle's emoji grid (for WeChat)
- guesszi-mp — WeChat Mini Program version. Same product, but uses server-side
bge-large-zhvia Flask because the WeChat runtime doesn't supporttransformers.js. Different deployment topology driven entirely by platform constraints — see that repo's README for the architecture comparison.
Built for Heatescape on 2026-05-02. Single-night build as a portfolio piece demonstrating client-side ML deployment.