CLAUDE.md — Zyquo Cloud Web
Project Identity
Zyquo Cloud Web is the browser edition of Zyquo Cloud: a legendary, fast, beautiful React web app that delivers the same multi-provider AI chat experience as the native macOS Zyquo Cloud — but running entirely in the browser, with no authentication, no accounts, and no backend. Everything lives on the user's device: the user enters their own provider API keys, which are stored in localStorage, and their conversation history is also stored locally (localStorage / IndexedDB). There is no server, no login, no user database — open the page, add your keys, start chatting.
It fronts the same 12 providers and the exact same models as native Zyquo Cloud, with streaming and non-streaming chat, model switching, Markdown + code rendering, and the family's premium design language. Because there is no backend, API calls go directly from the browser to each provider's API using the user's keys.
⚠️ Reality of a keyless, backend-less browser app (design around this honestly):
- API keys in
localStorageare not strongly secure — any script running on the page (or someone with device access) can read them. Be transparent about this in the UI (a clear one-time notice), keep the app dependency-light and CSP-hardened to reduce XSS risk, and never transmit keys anywhere except directly to the chosen provider. This is a deliberate "bring-your-own-key, local-only" model, not a secure vault. - CORS: some providers' APIs do not allow direct browser (cross-origin) calls. During Phase 0 you MUST determine, per provider, whether direct browser calls work, and document the reality + the optional fallback (a user-supplied proxy URL / the option to run Zyquo Router locally and point the web app at it). Do not pretend all 12 work browser-side without checking.
Naming conventions (use consistently everywhere):
- Display name / product name:
Zyquo Cloud Web - App title / PWA name:
Zyquo Cloud - Deployment domain:
www.zyquo.cloud(canonical, HTTPS; redirect apexzyquo.cloud→www) - Repo module prefix in file headers:
Zyquo Cloud Web - Storage key namespace:
zyquo.cloud.web.*(e.g.,zyquo.cloud.web.keys,zyquo.cloud.web.conversations,zyquo.cloud.web.settings)
📋 MANDATORY FILE HEADER — EVERY CODE FILE
Every single code file you write (all .ts, .tsx, .js, .jsx, .css, config files, Makefile, shell/build scripts — anything containing code) MUST begin with this header comment, adapted to the file's comment syntax:
/*
* <FileName>
* Zyquo Cloud Web
*
* Author: Simon-Pierre Boucher
* Mail: contact@spboucher.ai
*/For shell scripts / Makefiles / YAML (# comments):
#
# <filename>
# Zyquo Cloud Web
#
# Author: Simon-Pierre Boucher
# Mail: contact@spboucher.ai
#No exceptions. If you ever create or refactor a file and the header is missing, add it. Before declaring the project done, run a sweep over the repository to verify every code file carries the header.
🧭 METHODOLOGY — WORK METHODICALLY, KEEP EVERYTHING COHERENT
You must execute this project strictly in phase order (0 → 8). Do not jump ahead, do not interleave phases, do not build the full UI before one provider streams a real completion in the browser, and do not write provider code before Phase 0 research + Zyquo Cloud study are complete.
Working rules:
- One phase at a time. At the start of each phase, write a checklist into
docs/PLAN.md; check items off as you go. At the end of each phase, run a phase checkpoint: build (npm run build), type-check, lint, fix everything, write a 3–5 line phase summary indocs/PLAN.mdbefore moving on. - Phase gates: Phase 0 is complete only when
docs/PROVIDER-REUSE.mdanddocs/CORS-MATRIX.mdare complete. Phase 2 is complete only when a real streaming completion works browser-side against at least one provider. Phase 3 is complete only when local persistence (keys + conversations) round-trips reliably. Phase 4 spec is the contract for all UI in Phase 6. Phase 7 is complete only when the provider matrix is verified with real keys. Phase 8 is complete only when the production build + deployment are done. - Single source of truth, everywhere:
- Provider/model behavior → ported from the native Zyquo Cloud repo (Phase 0.B), adapted to browser
fetch/streaming; never re-invent request formats. All Zyquo Cloud models are available. - Colors, fonts, spacing, radii → only from
ZyquoThemedesign tokens (the same family system). Zero raw hex or magic numbers in components. - All storage access → only through a
storage/layer (never calllocalStoragedirectly from components). - All provider networking → only in the
providers/layer. - Naming → per the conventions above.
- Provider/model behavior → ported from the native Zyquo Cloud repo (Phase 0.B), adapted to browser
- Coherence sweeps: after Phases 3, 6, and 8 (consistent naming — always
Provider,AIModel,Conversation,Message; no dead code; headers present; one reusable message/bubble component; folders match Phase 2). - Build early, build often. Keep the type-checker and linter green; never accumulate more than one file of unbuilt changes.
- Commit discipline: one logical unit per commit, phase-prefixed. Never commit any API keys or
.envwith secrets. - Local-only is a hard invariant: no analytics that capture prompt content, no backend calls except directly to the user's chosen provider (and an optional user-configured proxy). Keys and history never leave the device except as part of a provider request the user initiated.
⚠️ PHASE 0 — MANDATORY RESEARCH + ZYQUO CLOUD STUDY (DO THIS FIRST, BEFORE ANY CODE)
Two mandatory tracks, two documents. No React until both are done.
0.B — docs/PROVIDER-REUSE.md — study the native Zyquo Cloud repo and reuse its providers
Before writing provider code, read and study the native Zyquo Cloud repository (the macOS app already built from its own CLAUDE.md). Locate it on disk (check the user's projects folder; if not found, ask the user for its path). Document and reuse:
- Exactly how each provider's API is called in Zyquo Cloud: base URLs, endpoints, auth headers (
Bearervsx-api-key,anthropic-version, Gemini key param), request/response shapes, the shared OpenAI-compatible client, the native Anthropic (Messages API) and Gemini (generateContent) clients, and the SSE streaming formats. The web app must call providers the same way, re-implemented with the browserfetchAPI +ReadableStreamfor SSE (instead of URLSession). - The complete model catalog (
ModelCatalog/docs/PROVIDERS.md) with capabilities (vision, tools, reasoning, context, max output) and pricing. Include ALL of these models in the web app's catalog. Reproduce it as a typed TS catalog. - Provider-specific streaming/parse quirks (Anthropic event blocks, Gemini chunks, DeepSeek/Qwen reasoning fields, Perplexity citations) so the browser streaming layer normalizes them behind one interface.
- The native app's design tokens and UX (light-theme flagship, layout, message rendering, model chip) so the web app matches the family look. (The web app re-implements the vault concept as plain localStorage — see the honesty note in Identity — NOT the machine-bound encryption, since a browser has no equivalent; be explicit about this difference.)
0.A — docs/CORS-MATRIX.md — browser feasibility per provider (INTENSIVE WEB RESEARCH)
Because calls go directly from the browser, you MUST research and document, per provider, the CURRENT reality:
- CORS support: does the provider's API send
Access-Control-Allow-Originallowing direct browser calls? Test/verify from official docs and community reports for each of the 12 providers (OpenAI, Anthropic, xAI, Mistral, Gemini, Qwen/DashScope, DeepSeek, Kimi, Perplexity, Together, DeepInfra, Cerebras). Note that some providers explicitly support browser use (and may need a special header like Anthropic'santhropic-dangerous-direct-browser-access— verify current requirement) and some block CORS entirely. - Per-provider verdict: ✅ direct browser call works / ⚠️ works with a specific header or caveat / ❌ blocked by CORS.
- Fallback design: for ❌/⚠️ providers, document the optional user-configurable proxy: a base-URL override per provider so a user can point at their own CORS proxy or at a locally running Zyquo Router (the family's local gateway) which exposes an OpenAI-compatible endpoint. The app ships fully client-side; the proxy is opt-in and user-supplied. Make the UI surface this clearly ("This provider can't be called directly from the browser — set a proxy URL or run Zyquo Router locally").
- Streaming over fetch: confirm SSE-over-
fetchReadableStreamparsing works for each shape (OpenAI SSE, Anthropic events, Gemini stream) in the browser, incl. cancellation viaAbortController.
PHASE 1 — Project Setup (React)
- Stack: React + TypeScript (strict) + Vite. Styling: Tailwind CSS (or CSS variables + tokens) implementing
ZyquoTheme. State: lightweight (Zustand or React context + reducers) — no heavy framework. Routing minimal (single-page; optional hash routes for settings). Markdown: a well-maintained renderer (react-markdown + remark/rehype) with a syntax highlighter (Shiki or highlight.js) and copy buttons. No backend, no auth libraries. - PWA (recommended): installable, offline shell (the app UI works offline; only provider calls need network),
manifest.webmanifest, service worker for the app shell (NOT for caching API responses/keys). - Scripts:
npm run dev,build,preview,lint,typecheck,check. - Security posture from the start: strict Content-Security-Policy (allow connections only to the known provider API origins + a user-set proxy origin; no inline scripts; no third-party script tags), Subresource Integrity where applicable, and no dependencies that aren't needed (every dependency is XSS surface for stored keys).
- Deployment target: static hosting (served as static assets). If deployed under the Zyquo platform, coordinate with the Node+ngrok topology on
m2u64used by the main site, OR any static host — document in Phase 8.
PHASE 2 — Architecture + Browser Provider Layer
src/
├── main.tsx, App.tsx
├── design/ # ZyquoTheme tokens, global styles, theme (light default) + dark toggle
├── types/ # Provider, AIModel, Conversation, Message, Settings…
├── providers/ # PORTED FROM NATIVE ZYQUO CLOUD (browser fetch/stream)
│ ├── types.ts # ProviderClient interface (send, stream)
│ ├── openaiCompatible.ts # OpenAI, xAI, Mistral, DashScope, DeepSeek, Kimi, Perplexity, Together, DeepInfra, Cerebras, Gemini-compat
│ ├── anthropic.ts # native Messages API + browser header
│ ├── gemini.ts # native generateContent
│ ├── sse.ts # fetch + ReadableStream SSE parser, AbortController cancel
│ └── catalog.ts # ALL models from Zyquo Cloud (typed)
├── storage/ # the ONLY place that touches localStorage/IndexedDB
│ ├── keys.ts # get/set/remove provider keys (localStorage, namespaced)
│ ├── conversations.ts # CRUD conversations/messages (IndexedDB for scale, or localStorage)
│ └── settings.ts # theme, default model, per-provider proxy base URLs
├── state/ # store (Zustand): conversations, activeModel, streaming state, settings
├── features/ # ai orchestration: send message, stream, stop, regenerate, title-gen
├── components/ # UI (see Phase 4)
├── hooks/
└── lib/- Streaming with
fetch+AbortController: parse SSE from aReadableStream; normalize every provider's stream into a common token/tool/usage event; cancel on stop or when the user sends a new message. - PHASE GATE: a real streaming completion renders token-by-token in a bare test view against at least one ✅-CORS provider, using a key from
localStorage.
PHASE 3 — LOCAL PERSISTENCE (KEYS + HISTORY, NO BACKEND)
All state is local. PHASE GATE: keys and full conversation history survive a page reload and browser restart, and can be exported/imported.
3.A — Keys (storage/keys.ts)
- Store per-provider keys in
localStorageunderzyquo.cloud.web.keys(a JSON map). Provide get/set/remove, masked display (last 4 chars), and a per-provider Test action. - Optional light obfuscation at rest (e.g., encrypt with a key derived from a user-set passphrase via WebCrypto AES-GCM) offered as an opt-in "lock with passphrase" feature — but be honest in the UI that without a passphrase the keys are stored in plaintext, and even with one, a compromised page can read them once unlocked. Default is plain localStorage with a clear first-run notice; passphrase lock is a bonus.
3.B — Conversations (storage/conversations.ts)
- Persist conversations and messages locally. Prefer IndexedDB (via a tiny wrapper or
idb) for capacity and performance with long histories; fall back to localStorage for small data. Namespacezyquo.cloud.web.conversations. - Store: conversation id, title, created/updated, model per conversation, system prompt, params, and the full message list (role, content, images as base64/blob refs, usage, reasoning, citations, timestamps).
- CRUD + search across all conversations; autosave on every change; safe migration/versioning of the stored schema.
3.C — Settings & data portability
storage/settings.ts: theme (light default), default model, per-provider proxy base URLs (from the CORS matrix), UI prefs.- Export / Import all data (keys optional, conversations, settings) as a JSON file — the only "backup" mechanism since there's no cloud. Clearly warn that exported files may contain API keys if the user includes them.
- Clear data controls (per-conversation, all conversations, all keys, everything) with confirmation.
PHASE 4 — DESIGN SYSTEM & UI (LIGHT THEME FLAGSHIP, RESPONSIVE)
Match native Zyquo Cloud's look via the family ZyquoTheme tokens; light theme is the default and flagship, dark is a secondary opt-in toggle. The app is a chat client and must be responsive / mobile-friendly (usable on a phone browser).
4.1 — Light theme (family standard)
Reuse Zyquo Cloud's light palette: airy off-white background (#FAFBFD), white surfaces, sky-indigo accent (#4E6AF0), 0.5pt-equivalent hairlines, ultra-soft shadows on floating elements only, generous body line-height (1.45). Typography/spacing/radii identical to the family. Dark theme derived. Default = light, never dark-auto.
4.2 — Layout & screens
- Shell: a chat layout with a sidebar (conversations: search, new chat, pinned/date groups, rename/delete, model badge) and a chat area (header with editable title + centered model chip → the full Model Menu in 4.2.1; transcript; input bar). Matches native Zyquo Cloud's structure.
4.2.1 — The Model Menu (a headline surface — make it exceptional)
Clicking the model chip opens a rich, fast command-palette-style model picker (⌘/Ctrl+K also opens it):
- Instant search/filter by model name, provider, or capability; fuzzy match; keyboard-navigable (arrows + Enter), Esc to close.
- Grouped by provider with the provider glyph/logo, collapsible sections; a Favorites group pinned at top (star any model); a Recents group.
- Filter chips/toggles: Vision, Tools/Function-calling, Reasoning, JSON mode, Long-context, Cheapest, Fastest — filter the list live (data from the ported catalog capabilities).
- Each row shows: model name, provider, capability badges (👁 vision / 🛠 tools / 🧠 reasoning), context window, max output, and price per 1M tokens (in/out) from the catalog; a subtle "not configured" state if the provider has no key yet (with a quick "Add key" affordance), and a "needs proxy" flag for CORS-blocked providers.
- Set as default, use for this conversation, or use for this one message (regenerate with a different model right from the menu).
- Compare picker: a "Compare…" action to select 2–4 models for side-by-side compare mode.
- Aliases: user-defined friendly aliases (e.g.,
fast,smart) mapping to a chosen model, surfaced at the top. - Beautiful empty/loading/error states; virtualized list so 100+ models stay instant.
- Transcript: user bubbles right (accent-subtle), assistant left on surface; full Markdown with tables, blockquotes, and syntax-highlighted code blocks with copy; collapsible reasoning/"thinking" section for reasoning models; Perplexity citations as numbered chips; per-message token/cost (from
usage+ catalog pricing) on hover; message actions (copy, edit & resend, regenerate — optionally with another model, delete). - Input bar: floating card, multiline auto-grow, image attach/paste for vision-capable models (base64), attachment thumbnails, params quick-toggle, circular accent send (⌘/Ctrl+Enter), Stop during streaming.
- Settings (modal or route): tabs — Providers & Keys (per-provider masked field, Test button + status dot, proxy base URL field for ⚠️/❌ providers, the honesty notice about localStorage), Models (full catalog, capability badges, pricing, favorites, default model), Appearance (light/dark/system + accent choices + chat font size), Data (export/import, clear data), Advanced (passphrase lock toggle, streaming toggle, default params).
- First-run: a clean, honest welcome — "Your keys and history stay in this browser (localStorage). Add a provider key to begin." + quick model pick. Beautiful, not scary, but transparent.
- Empty chat state: centered Zyquo mark, greeting, a few suggested prompts, model chip.
4.3 — Responsive & motion
- Responsive: sidebar collapses to a drawer on phones; transcript and input bar adapt full-width; ≥44pt touch targets; code blocks scroll internally; no horizontal overflow; works portrait/landscape. Mobile is a real target.
- Motion: smooth streaming (no jitter, blinking caret), 150ms message-in, 80ms hovers, snappy popovers, 60fps; respect
prefers-reduced-motion.
4.4 — Quality gate
Review every state at phone + desktop widths in light (default) and dark: consistent tokens, no overflow, working drawer nav, streaming, stop, error (bad key → clear message, CORS-blocked → explain proxy/Router), empty/loading, long conversation performance (virtualize the transcript if needed), export/import, passphrase lock/unlock. Confirm light default. If it looks templated or breaks on a phone, iterate.
PHASE 5 — BRAND ASSETS
- Favicon set +
manifest.webmanifest(installable PWA) using the Zyquo mark (chunky charcoal-black Z with electric-blue base) and the Cloud accent; apple-touch-icon;theme-colorlight. - App wordmark as crisp inline SVG (light/dark); reuse the Zyquo Cloud icon for the PWA/install icon so it matches the native app in the Dock/home screen.
- OG/social meta for the hosted URL (static image, on-brand).
PHASE 6 — Features (Parity with native Zyquo Cloud, browser-native)
Cool chat features (make this genuinely delightful — go beyond a basic chat box)
- Rich Model Menu (Phase 4.2.1): searchable, capability-filtered, priced, favorites/recents, per-message model override, aliases.
- Branching / regenerate variants: regenerate a response (same or different model) and keep multiple variants you can swipe/tab between; branch a conversation from any message to explore alternatives without losing the original thread.
- Edit & fork: edit any earlier user message and re-run from that point (forking the thread); edit assistant messages for note-taking.
- Streaming niceties: token-by-token with a blinking caret, live tokens/sec and elapsed timer, Stop and Continue (ask the model to keep going), and scroll-lock with a "jump to latest" pill.
- Multi-model compare mode: send one prompt to 2–4 models side-by-side in columns, each streaming independently, with per-column copy/regenerate and a quick "promote this answer into the thread" action.
- Prompt Library & slash commands: ship ≥40 quality templates; type
/in the input for a slash-command menu (templates, personas, tools like/summarize,/translate,/rewrite,/explain); templates support{{variables}}with a quick fill form. - Personas: named assistants = system prompt + preferred model + params; switch persona per conversation; ship a few great defaults (Coder, Writer, Analyst, Tutor…).
- Attachments: drag/drop or paste images (vision models) with thumbnails; attach text/code/CSV/JSON/MD files injected as context; paste large text as a collapsible block.
- Rich rendering: GitHub-flavored Markdown, tables, task lists, footnotes; syntax-highlighted code with language label, copy button, and per-block "copy"/"wrap" toggles; math via KaTeX; Mermaid diagram rendering; collapsible reasoning/"thinking" panels; Perplexity citations as numbered, clickable chips.
- Message actions: copy (as text or Markdown), quote-reply, pin/star a message, add a note, delete, and read-aloud (Web Speech API TTS) with voice/speed controls; optional speech-to-text input (Web Speech API) for dictation.
- Conversation tools: auto-generated titles, summarize this conversation, conversation-level search and in-conversation find, tags/folders, pin, archive, duplicate, and export a single conversation to Markdown / JSON / (client-side) PDF; shareable export link is NOT server-based — export is a file since there's no backend.
- Token & cost HUD: live per-message and per-conversation token counts and estimated cost (from catalog pricing), plus a context-window usage bar showing how full the context is, with auto-trim oldest turns (keeping system prompt) when near the limit.
- Parameter controls: per-conversation temperature, top_p, max tokens, penalties, seed, JSON mode/
response_format, and reasoning effort where supported — the panel only shows params the active model/provider actually supports. - Quality-of-life: command palette (⌘/Ctrl+K) for everything (new chat, switch model, search, jump to conversation, run template); full keyboard shortcuts; undo for deletes (soft-delete + toast); autosave everywhere; offline-friendly UI shell (PWA); retry with backoff on transient provider errors; graceful, human error toasts (bad key names the provider, CORS-blocked explains the proxy/Router option, rate-limit shows retry).
- Theming extras: light default + dark toggle + a few accent choices; adjustable chat font size and message density (comfortable/compact); optional "focus mode" hiding the sidebar.
Core parity
- Multi-conversation local history (search, pin, rename, delete, groups) — all in IndexedDB/localStorage
- Streaming + non-streaming chat across all 12 providers / all Cloud models (browser fetch), model switch per conversation and per message
- Vision (image attach/paste) for capable models; text-file attach injected into messages
- System prompt per conversation + global default; per-conversation params (only those the provider supports)
- Keys + history in
localStorage/IndexedDB with optional passphrase lock; full export/import; clear-data controls; per-provider proxy override for CORS-blocked providers (point at a local Zyquo Router) - PWA installable; light theme default; fully responsive (usable on a phone browser)
PHASE 7 — VERIFICATION (MANDATORY)
The user will provide real API keys (same providers as Zyquo Cloud). You MUST:
- Provider matrix (browser-side): for every provider/model in the catalog, from an actual browser context, verify: non-streaming completion; streaming renders token-by-token; cancellation via Stop works; vision on vision-capable models; reasoning content on reasoning models; Perplexity citations. Record ✅/❌ per provider/model and the CORS verdict encountered (direct vs. needs-proxy). Fix everything fixable; for CORS-blocked providers, verify the proxy/Zyquo Router fallback path works and is clearly surfaced in the UI.
- Persistence: keys and full history survive reload and browser restart; export→clear→import restores exactly; schema migration works; large-history performance is smooth (virtualization if needed).
- Security/privacy sanity: confirm no key or prompt content is sent anywhere except the chosen provider (or user-set proxy) — inspect network traffic; confirm the CSP blocks unexpected origins; confirm the first-run localStorage notice is present; passphrase lock encrypts/decrypts correctly.
- Responsive/cross-browser: verify on Chrome, Safari, Firefox (desktop) and iOS Safari / Android Chrome (phone): layout, streaming, drawer nav, no overflow; light theme loads by default.
- Never commit or log any key; keys live only in the browser's localStorage during use.
PHASE 8 — BUILD & DEPLOYMENT
No notarization (it's a web app). Phase 8 is a proper production build + static deployment:
npm run build→ optimized static bundle (code-split, hashed assets, tree-shaken, minimal JS); zero type/lint errors; PWA assets generated; CSP finalized to the exact set of provider origins (+ a placeholder for the user's proxy origin, handled at runtime).- Deploy as static assets at
www.zyquo.cloud(HTTPS, apexzyquo.cloud→wwwredirect). If served under the Zyquo platform, use the same Node server onm2u64exposed through ngrok as the main site (bind thewww.zyquo.cloudcustom domain to the tunnel + DNS CNAME), OR any static host (Cloudflare Pages/Vercel/Netlify) as a documented alternative. Set security headers (CSP, HSTS, X-Content-Type-Options, Referrer-Policy) and long-cache for hashed assets. - Because it's 100% client-side, it also runs from
file://-style local hosting or a simple static server — document how a user can self-host it, which pairs naturally with running Zyquo Router locally for CORS-blocked providers. - Post-deploy: verify HTTPS, PWA install, all provider calls from the deployed origin (CSP must allow them), light-default, and mobile.
Engineering Standards
- TypeScript strict; ESLint + Prettier clean; zero build warnings; minimal, audited dependencies (each is key-theft surface)
- All
localStorage/IndexedDB access behindstorage/; all networking behindproviders/; components stay presentational - Provider layer faithfully ported from native Zyquo Cloud (all models); SSE via
fetch+ReadableStream+AbortController; robust human-readable errors (invalid key names the provider; CORS-blocked explains the proxy/Router fallback; rate-limit shows retry) - Design tokens only — no hardcoded colors/sizes; light theme default; responsive/mobile-first friendly
- Strict CSP; never transmit keys/history anywhere but the chosen provider (or user proxy); transparent first-run notice about localStorage
README.md(dev, self-host, "use with Zyquo Router") +docs/(PROVIDER-REUSE, CORS-MATRIX, PLAN)- Commit in logical, phase-prefixed increments; never commit keys/secrets
Definition of Done
- A React web app that reproduces Zyquo Cloud's chat experience in the browser with no auth, no accounts, no backend
- API keys stored in
localStorageand conversation history stored locally (IndexedDB/localStorage), surviving reloads/restarts, with export/import and clear-data — plus an optional passphrase lock and an honest first-run notice about local storage - Streaming + non-streaming chat across all 12 providers / all models from native Zyquo Cloud, called directly from the browser, with per-provider CORS reality documented and a proxy / local Zyquo Router fallback for blocked providers, verified with real keys (Phase 7 matrix)
- Full chat features: a rich searchable/priced Model Menu, per-message model override, branching/regenerate variants, edit & fork, multi-model compare, slash commands + prompt library, personas, Markdown + code + KaTeX + Mermaid, reasoning display, citations, vision, read-aloud / dictation, token/cost HUD + context bar with auto-trim, and a ⌘K command palette
- Deployed at
www.zyquo.cloud(HTTPS, apex→www); light theme loads by default; dark is a secondary toggle; the app is responsive and usable on phones; installable PWA - Strict CSP; keys/history never leave the device except as user-initiated provider requests
- The Zyquo mark/wordmark and Cloud accent applied consistently as crisp SVG
- Every code file starts with the mandatory Author/Mail header (verified by a repo-wide sweep)
docs/PLAN.mdshows every phase completed; PROVIDER-REUSE and CORS-MATRIX complete and traceable- Zyquo Cloud Web feels like the legendary, private, local-only browser edition of Zyquo Cloud