
# โก Zyquo Cloud Web
### *Every cloud model. One beautiful chat. Entirely in your browser.*
**The browser edition of Zyquo Cloud โ 12 AI providers, 170 models, zero backend.
Bring your own keys; nothing ever leaves your device.**
[](https://github.com/spboucher-ai/zyquo-cloud-web/releases)
[](LICENSE)
[](#-contributing)
[](https://github.com/spboucher-ai/zyquo-cloud-web/commits/main)
[](https://react.dev)
[](https://www.typescriptlang.org/)
[](https://vitejs.dev)
[](https://zustand-demo.pmnd.rs/)
[](#-features)
[](#-the-provider-fleet)
[](#-the-provider-fleet)
[](docs/VERIFICATION.md)
[](#-privacy--security-model)
[](#-tech-stack)
[](#-features)
[](#-features)
[](https://github.com/spboucher-ai/zyquo-cloud-web/actions/workflows/ci.yml)
[](https://github.com/spboucher-ai/zyquo-cloud-web/actions/workflows/deploy-pages.yml)
[](https://www.zyquo.cloud)
[](https://github.com/spboucher-ai/zyquo-cloud-web/commits/main)
[](https://github.com/spboucher-ai/zyquo-cloud-web)
**[๐ Open the app โ](https://www.zyquo.cloud)**
---
## ๐ Table of Contents
- [โจ Features](#-features)
- [๐ฐ The Provider Fleet](#-the-provider-fleet)
- [๐ Live Demo](#-live-demo)
- [๐ธ Screenshots](#-screenshots)
- [๐ Privacy & Security Model](#-privacy--security-model)
- [๐งฑ Tech Stack](#-tech-stack)
- [๐ Getting Started](#-getting-started)
- [๐ Available Scripts](#-available-scripts)
- [๐ Project Structure](#-project-structure)
- [โ๏ธ Deployment](#๏ธ-deployment)
- [โ
Verification](#-verification)
- [๐บ Roadmap](#-roadmap)
- [๐ค Contributing](#-contributing)
- [๐ License](#-license)
- [๐ค Author](#-author)
---
## โจ Features
Everything below is implemented and verified in this codebase โ no vaporware.
### ๐ฌ Chat engine
- **Streaming & non-streaming chat** against 12 providers through two faithfully
ported wire clients: one OpenAI `/chat/completions` client (11 providers +
custom endpoints, every quirk handled) and one native **Anthropic Messages
API** client โ over `fetch` + `ReadableStream` with a hand-rolled incremental
**SSE parser** (`event:`/`data:` blocks, keep-alive comments, `[DONE]`,
trailing-event flush).
- **Token-by-token rendering** with a blinking caret, live **elapsed time +
tok/s**, **Stop** (`AbortController` teardown) and **Continue**.
- **Reasoning streams** normalized from every dialect: `reasoning_content`,
`reasoning`, Mistral's array-of-thinking-chunks, DashScope `enable_thinking`,
Anthropic `thinking` blocks โ shown in a collapsible *Thought process* panel.
- **Perplexity citations** (`citations` + `search_results` merged) rendered as
numbered, clickable chips.
- **Auto-retry with backoff** on 429/5xx (honors `Retry-After`), typed
human-readable errors that name the provider, and a CORS-shaped network
error that explains the proxy/Zyquo Router fallback.
- **Auto-titling** after the first exchange using the provider's cheapest
non-reasoning model (native Zyquo Cloud behavior, ported verbatim).
### ๐ The Model Menu
- Command-palette-style picker: **fuzzy search** across name / model ID /
provider, **filter chips** (Vision ยท Tools ยท Reasoning ยท JSON ยท Long context
ยท Cheapest), **Favorites โญ / Recents / Aliases** groups, keyed-providers
first, full keyboard navigation (`โโ`, `โต` use here, `โโต` set default).
- Every row shows capability badges (๐ ๐ง ๐ ), **context window**, and
**$/1M-token pricing** straight from the catalog; un-keyed providers get an
inline **"Add key"** affordance.
### ๐งช Power features
- **Multi-model compare** โ broadcast one prompt to **2โ4 columns**, each
streaming independently with its own stop/copy/regenerate, then **promote
the best answer into your thread**.
- **Variants & branching** โ regenerate keeps the previous answer as a
swipeable variant (`โน 2/3 โบ`); branch a whole conversation from any message;
**edit & resend** forks from an earlier user turn.
- **โK command palette** โ actions (new chat, compare, focus mode, summarize,
duplicate), jump-to-conversation, model switch, personas, templates.
- **`/` slash commands** โ quick tools (`/summarize`, `/translate`,
`/rewrite`, `/explain`) + the full library with `{{input}}` substitution.
- **8 personas** and **56 prompt templates** (8 categories ร 7), ported
verbatim from native Zyquo Cloud.
- **Vision attachments** (drag/drop/paste images โ base64 parts) and **text
file attachments** (injected as fenced context blocks), gated by each
model's real capabilities.
- **Read-aloud** (Web Speech TTS) and **dictation** (SpeechRecognition).
- **Token & cost HUD** โ per-message and per-conversation token counts and
cost estimates from catalog pricing, plus a **context-window usage bar**
with **auto-trim** of the oldest turns at 90% capacity (system prompt kept).
- **Per-conversation parameters** โ temperature, top-p, max tokens,
penalties, reasoning effort, extended thinking โ the panel only shows
controls the active model actually supports; unchecked = provider default,
omitted from the request entirely.
### ๐ Rendering
- GitHub-flavored **Markdown** (tables with zebra rows, task lists,
blockquotes with accent bar), **syntax-highlighted code blocks** with
language label, copy and wrap toggles, **KaTeX math**, and **Mermaid
diagrams** (the ~1 MB renderer lazy-loads only when a diagram appears).
### ๐พ Local-first persistence
- Conversations in **IndexedDB** (schema-versioned, dependency-free wrapper),
keys and settings in namespaced `localStorage`
(`zyquo.cloud.web.*`) โ **surviving reloads and full browser restarts**
(gate-tested).
- **Export / import everything** as JSON (keys strictly opt-in with a
warning), per-conversation Markdown/JSON export, confirm-twice clear-data,
**undo** for deletes.
- Optional **passphrase lock**: the key map encrypted at rest with
**AES-GCM** (PBKDF2, 310k iterations) โ honestly framed as at-rest
protection, not a running-session vault.
### ๐จ Design
- The **ZyquoTheme** design system, ported token-for-token from the native
macOS app โ light flagship theme (`#FAFBFD` / sky-indigo `#4E6AF0`), derived
dark theme, **5 accent choices**, adjustable chat font size and density,
focus mode, `prefers-reduced-motion` respected.
- **Installable PWA** (app-shell precache, 1.15 MB) and fully **responsive** โ
the sidebar becomes a drawer on phones, code blocks scroll internally,
44 pt touch targets.
---
## ๐ฐ The Provider Fleet
| Provider | Models | Wire format | Streaming | Vision | Reasoning | Citations |
|---|:-:|---|:-:|:-:|:-:|:-:|
| ๐ข **OpenAI** | 27 | OpenAI compat | โ
| โ
| โ
| โ |
| ๐ **Anthropic** | 11 | **Messages API** | โ
| โ
| โ
| โ |
| โซ **xAI** | 5 | OpenAI compat | โ
| โ
| โ
| โ |
| ๐ต **Mistral** | 10 | OpenAI compat | โ
| โ
| โ
| โ |
| ๐ด **Google Gemini** | 14 | OpenAI compat | โ
| โ
| โ
| โ |
| ๐ฃ **Alibaba Qwen** | 32 | OpenAI compat | โ
| โ
| โ
| โ |
| ๐ **DeepSeek** | 2 | OpenAI compat | โ
| โ | โ
| โ |
| ๐ **Kimi (Moonshot)** | 12 | OpenAI compat | โ
| โ
| โ
| โ |
| ๐ **Perplexity** | 4 | OpenAI compat | โ
| โ | โ
| โ
|
| ๐งฉ **Together AI** | 16 | OpenAI compat | โ
| โ | โ
| โ |
| ๐ฆ **DeepInfra** | 34 | OpenAI compat | โ
| โ
| โ
| โ |
| โก **Cerebras** | 3 | OpenAI compat | โ
| โ
| โ
| โ |
**All 12 call the provider APIs directly from your browser** โ CORS
feasibility was empirically probed per provider (preflight + authenticated
POST + streaming), documented with official sources in
[`docs/CORS-MATRIX.md`](docs/CORS-MATRIX.md). Anthropic requires its
documented `anthropic-dangerous-direct-browser-access: true` header, which the
client sends. A **per-provider base-URL override** (Settings โ Providers &
Keys) lets you point any provider at your own proxy or a locally running
**Zyquo Router** if a policy ever changes.
---
## ๐ Live Demo
| | URL | Notes |
|---|---|---|
| ๐ **Production** | **https://www.zyquo.cloud** | Primary deployment โ HTTPS, security headers, installable PWA |
| ๐ช **GitHub Pages mirror** | https://spboucher-ai.github.io/zyquo-cloud-web/ | Auto-deployed from `main` by CI |
> Open it, add any provider API key in **Settings โ Providers & Keys** (it
> stays in *your* browser), pick a model, chat. That's the whole onboarding.
---
## ๐ธ Screenshots
| Light (flagship) | Dark |
|:-:|:-:|
|  |  |
| The Model Menu | โK Command Palette |
|:-:|:-:|
|  |  |
| ๐ฑ Mobile |
|:-:|
|

|
---
## ๐ Privacy & Security Model
**This app has no backend, no accounts, and no telemetry โ by design.**
- ๐ **Bring-your-own-key:** your API keys live in `localStorage` on your
device and are sent **only** to the provider you call, directly.
- ๐งพ **Honest first-run notice:** browser storage is *not* a secure vault โ
anyone with your browser profile (or a script running on the page) could
read it. The app says so instead of pretending otherwise.
- ๐ก **Strict CSP:** `connect-src` is locked to exactly the 12 provider
origins + `localhost` (for Zyquo Router). No inline scripts, no third-party
scripts, `object-src 'none'`, `frame-ancestors 'none'`.
- ๐ต๏ธ **Audited:** during the full 169-model verification run, the page
contacted the 12 provider origins and localhost โ **nothing else**.
- ๐ **Optional passphrase lock:** AES-GCM (WebCrypto) encryption of the key
map at rest, PBKDF2-derived key, wrong-passphrase rejection tested.
- ๐ฆ **Dependency-light on purpose:** every dependency is key-theft surface โ
no icon packs, no CSS framework, no IndexedDB wrapper lib, no auth SDKs.
---
## ๐งฑ Tech Stack
| Layer | Choice | Why |
|---|---|---|
| โ๏ธ UI | **React 19** + **TypeScript (strict)** | `noUncheckedIndexedAccess`, project references, zero `any` leaks |
| โก Build | **Vite 7** | code-split (Mermaid/KaTeX lazy), hashed assets, **288 kB gzip** core bundle |
| ๐ State | **Zustand 5** | one store: conversations, streaming, settings, UI |
| ๐จ Styling | **CSS custom properties** (ZyquoTheme tokens) | no Tailwind/framework โ tokens ported 1:1 from the native macOS app |
| ๐ Markdown | react-markdown + remark-gfm + rehype-highlight + **KaTeX** + **Mermaid** (lazy) | GFM, math, diagrams, Zyquo-mapped syntax theme |
| ๐ Networking | hand-rolled **SSE parser** over `fetch`/`ReadableStream` | one parser for OpenAI-style and Anthropic named events |
| ๐พ Storage | **IndexedDB** (own 80-line wrapper) + namespaced `localStorage` | schema versioning, no dependency |
| ๐ฒ PWA | vite-plugin-pwa (Workbox) | app-shell precache only โ **never** API responses or keys |
| ๐งช Testing | **Playwright** (Chromium/WebKit/Firefox) | live gate scripts: streaming, persistence, full provider matrix |
---
## ๐ Getting Started
### Prerequisites
- **Node.js โฅ 20** and **npm**
- At least one provider API key (OpenAI, Anthropic, xAI, Mistral, Gemini,
DashScope, DeepSeek, Moonshot, Perplexity, Together, DeepInfra or Cerebras)
### Install & run
```bash
git clone https://github.com/spboucher-ai/zyquo-cloud-web.git
cd zyquo-cloud-web
npm install
npm run dev # โ http://localhost:5173
```
Open the app, go to **Settings โ Providers & Keys**, paste a key, hit
**Test**, pick a model โ done.
### Environment variables
The app itself needs **none** โ keys are entered in the UI and stored in the
browser. Build-time only:
| Variable | Purpose | Default |
|---|---|---|
| `VITE_BASE` | Base path for subpath hosting (e.g. GitHub Pages sets `/zyquo-cloud-web/`) | `/` |
> โ ๏ธ Never put API keys in `.env` files here โ there is no server to hide
> them in. The `.gitignore` blocks `.env*` and the local test-key file anyway.
---
## ๐ Available Scripts
| Script | What it does |
|---|---|
| `npm run dev` | Vite dev server on `:5173` |
| `npm run build` | Type-check (project refs) + production build + PWA assets |
| `npm run preview` | Serve the production build locally |
| `npm run typecheck` | `tsc -b --noEmit` |
| `npm run lint` | ESLint (flat config) over `src/` |
| `npm run check` | typecheck + lint + build โ the CI gate |
| `node scripts/server.mjs 8080 dist` | Zero-dependency production server (CSP/HSTS headers, SPA fallback, `/healthz`) |
| `node scripts/gate-phase2.mjs` | Live streaming gate in headless Chromium |
| `node scripts/gate-phase3.mjs` | 13-check persistence gate (reload + browser restart + vault) |
| `node scripts/verify-matrix.mjs` | Full provider/model verification matrix (needs real keys in `.keys.local.json`) |
| `node scripts/verify-browsers.mjs` | Chromium/WebKit/Firefox responsive smoke |
---
## ๐ Project Structure
```
zyquo-cloud-web/
โโโ index.html # CSP meta, PWA/social meta
โโโ vite.config.ts # Vite + PWA (app-shell precache only)
โโโ src/
โ โโโ App.tsx # Shell: sidebar + chat, global shortcuts
โ โโโ types/ # Provider, AIModel, Conversation, Message, Settings
โ โโโ providers/ # ๐ ALL networking lives here
โ โ โโโ registry.ts # 12-provider metadata + client resolution
โ โ โโโ openaiCompatible.ts# one client, 11 providers + custom, every quirk
โ โ โโโ anthropic.ts # native Messages API + browser CORS header
โ โ โโโ sse.ts # fetch/ReadableStream SSE parser + retry
โ โ โโโ catalog.ts # the complete 170-model typed catalog
โ โ โโโ testKey.ts # key validation (/models or min completion)
โ โโโ storage/ # ๐พ the ONLY place touching localStorage/IndexedDB
โ โ โโโ keys.ts # namespaced key map (+ vault overlay)
โ โ โโโ vault.ts # AES-GCM passphrase lock
โ โ โโโ db.ts # dependency-free IndexedDB wrapper
โ โ โโโ conversations.ts # CRUD + schema migration + search
โ โ โโโ settings.ts # theme, default model, proxy overrides
โ โ โโโ backup.ts # export / import / clear-everything
โ โโโ state/store.ts # Zustand: send/stream/stop/regenerate/branch/title
โ โโโ features/ # personas, prompt library, compare, exporters, trim
โ โโโ components/ # Sidebar, ChatView, ModelMenu, CompareView, โฆ
โ โโโ design/ # ZyquoTheme tokens (CSS vars), components.css
โโโ scripts/ # prod server + live verification gates
โโโ docs/ # PLAN, PROVIDER-REUSE, CORS-MATRIX, VERIFICATION, NATIVE-UX
โโโ .github/workflows/ # CI + GitHub Pages deploy
```
Two hard architectural invariants, enforced by sweep: **all network I/O is in
`providers/`**, **all persistence is in `storage/`** โ components stay
presentational.
---
## โ๏ธ Deployment
The build is **100% static** โ host it anywhere.
### GitHub Pages (automated)
Every push to `main` triggers [`deploy-pages.yml`](.github/workflows/deploy-pages.yml):
build with `VITE_BASE=/zyquo-cloud-web/` โ deploy to
**https://spboucher-ai.github.io/zyquo-cloud-web/**.
### Self-host (any box, 30 seconds)
```bash
npm run build
node scripts/server.mjs 8080 dist
```
`server.mjs` is a zero-dependency Node server that adds the full security
header set (CSP, HSTS preload, nosniff, Referrer-Policy, Permissions-Policy),
immutable caching for hashed assets, SPA fallback, and `/healthz`.
### Production (www.zyquo.cloud)
The primary instance runs the same `server.mjs` under **PM2** behind an
**ngrok** custom domain:
```bash
pm2 start server.mjs --name zyquo-cloud-web -- 8080 dist
pm2 start "ngrok http --url=www.zyquo.cloud 8080" --name zyquo-cloud-ngrok
pm2 save
```
### Static hosts
Cloudflare Pages / Netlify / Vercel: build command `npm run build`, output
`dist/`. Add the security headers from `scripts/server.mjs` via your host's
headers config for parity.
---
## โ
Verification
This app was verified **live, with real keys, from a real browser** โ full
report in [`docs/VERIFICATION.md`](docs/VERIFICATION.md):
| Check | Result |
|---|---|
| ๐ Streaming, token-by-token | **169 / 169 tested models** โ
|
| ๐ฌ Non-streaming completion | 12 / 12 providers โ
|
| โน Stop / `AbortController` | 12 / 12 providers โ
|
| ๐ Vision (base64 image parts) | 9 / 9 vision-capable providers โ
|
| ๐ง Reasoning deltas | all thinking models โ
|
| ๐ Perplexity citations | โ
(19 chips on one query) |
| ๐ CORS direct-from-browser | 12 / 12 โ
|
| ๐พ Persistence (reload + restart + vault) | 13 / 13 checks โ
|
| ๐งญ Cross-browser (Chromium/WebKit/Firefox) | 15 / 15 checks โ
|
| ๐ต๏ธ Network audit | provider origins + localhost, **nothing else** โ
|
---
## ๐บ Roadmap
- [ ] Function calling / tools UI (the catalog already tracks `tools` capability)
- [ ] Model aliases editor in Settings (aliases already surface in the Model Menu)
- [ ] Client-side PDF export (Markdown/JSON exports ship today)
- [ ] Transcript virtualization for 1,000+ message threads
- [ ] Conversation tags & archive surfaces (data model ready)
- [ ] i18n (FR first)
---
## ๐ค Contributing
Contributions are welcome!
1. **Fork** and create a branch: `git checkout -b feat/my-feature`
2. Keep the invariants: networking only in `providers/`, persistence only in
`storage/`, design tokens only (no raw hex in components), and the file
header on every code file.
3. `npm run check` must be green.
4. Open a PR with a clear description.
> ๐ Never commit keys. `.keys.local.json`, `.env*` and friends are
> gitignored; CI contains a history secret-scan precedent.
---
## ๐ License
Released under the [MIT License](LICENSE) โ ยฉ 2026 Simon-Pierre Boucher.
---
## ๐ค Author

**Simon-Pierre Boucher**
๐ซ **Contact:** [contact@spboucher.ai](mailto:contact@spboucher.ai)
*Zyquo Cloud Web is part of the Zyquo family โ native **Zyquo Cloud** (macOS),
**Zyquo Router** (local gateway), and friends.*
โญ **If this project is useful to you, a star makes my day.** โญ