SPB Git

spb/zyquo-cloud-web Public MIT

Zyquo Cloud Web — every cloud model, one beautiful chat, entirely in your browser.

TypeScript 81.9% CSS 8.9% JavaScript 7.5% Shell 1.1% HTML 0.6%
9.9 KB

# Native Zyquo Cloud UX Reference (Phase 0.B study — feeds Phases 4 & 6)

Detailed study of the native macOS app's views (2026-07-31), used as the contract for the web UI. Web-specific departures are marked ⤷web.

# Layout

  • Root: sidebar (260, min 260 / max 360) + detail; window default 1240×800. ⤷web: sidebar collapses to a drawer under ~768px.
  • Sidebar (top→bottom): wordmark (CloudZGlyph 22 + "Zyquo Cloud" 14/medium); search field (surfaceSecondary@0.7, radius 6, ⌘F); full-width accent New Chat button (radius 6, ⌘N); conversation list (LazyVStack spacing 2, groups Pinned / Today / Yesterday / Previous 7 Days / Older, headers caption/ textTertiary); rows = title 13 + sub-line modelID · relative time caption, hover pin/trash, selected = accentSubtle, radius 6; context menu Pin / Add Tag / Remove Tag / Delete; tags capsule strip above footer; footer = gear (Settings) + usage caption X.XK tok · ~$Y.YY.
  • Chat header (52px, hairline below): model chip absolutely centered; left = editable title (13/medium, double-click rename); right = Compare, Export (⌘⇧E), Info popover (340 wide: tokens in/out, est. cost, editable system prompt 300×90).
  • Transcript: centered 760px column, 16px turn rhythm/padding; auto-scroll while pinned to bottom; floating "Jump to latest" pill (capsule, surface, hairline, soft shadow) when unpinned during streaming.
  • Bubbles: user right (accentSubtle fill, no border, ≥60px left spacer); assistant left with 26×26 circular provider avatar (accent glyph on accentSubtle) + surface bubble with 0.5px border; pad 12h/10v, radius 10; metadata row fades in on hover.
  • Input bar: floating card (pad 12, radius 14, surface, hairline, soft shadow, margins 12); optional 56px attachment strip; paperclip → auto-grow editor ("Message…", max 200px) → params button (popover) → 28×28 circular send (arrow up, accent; danger + stop icon while streaming), ⌘↩. Drag target: 1.5px dashed accent border. Images png/jpg/webp/gif; text files <512 KB. Thumbnails 56×56 radius 6 with remove badge.
  • Model chip: provider glyph 11 + name 12.5/medium + chevron 8, pad 8h/4v, radius 6, surfaceSecondary, press-scale; opens picker popover.

# Model picker (native popover 320×380)

Search field → "Favorites" section (query empty only) → per-provider sections, providers with keys first then alphabetical. Row: glyph · name 12.5 · capability icons 9pt (eye/brain/wrench) · context badge · star toggle (warning color). Rank: favorites → recommended → normal → legacy. No recents, no capability filters, click-only. ⤷web (Phase 4.2.1 spec goes beyond native): ⌘K palette sizing, fuzzy search, filter chips, Recents group, pricing per row, not-configured / needs-proxy states, aliases, compare picker, keyboard nav, virtualized list.

# Message rendering

  • Markdown blocks (spacing 12): headings ×1.55/1.35/1.2/1.05 semibold; blockquote = 3px accent left bar + textSecondary; task lists; ordered lists monospaced-digit in 20px slot; tables = zebra rows, header surfaceSecondary, hairline grid, radius 6; inline code mono size−1 on surfaceSecondary; links accent.
  • Code blocks: surfaceSecondary card radius 10; header = UPPERCASED language caption + hover-reveal copy (checkmark success 1.2s); body mono size−1, h-scroll. Syntax theme: keyword=accent, string=success, comment=textTertiary, number #B26A0B/#E0A458, type #2380C2/#62B7F0, function #6E4FD4/#A48CF2, property #2F6FBF/#7FB4E8, attribute=warning.
  • Reasoning: collapsed disclosure "Thinking…" (streaming) / "Thought process"; expanded = mono size−2, textSecondary, surfaceSecondary pad 8 radius 6.
  • Citations: capsule chips — 13px accent circle with white index + title/host caption; opens URL.
  • Streaming caret: 7×15 accent rounded rect blinking 1↔0.15 @0.55s.
  • Actions (hover, 10pt): copy, edit-&-resend (user), regenerate (assistant), quote-reply (> prefix into draft), delete. Edit mode = inline textarea + Cancel/Resend.
  • Error state: warning triangle + danger text on danger@8% radius 6.
  • Metadata: time HH:mm, {in}→{out} tok, ~$0.0000 when >0.

# Settings (native 720×520, 5 tabs)

  1. Providers & Keys — per-provider row: glyph, name + status dot (green verified / grey saved / spinner testing / red failed), sub-line Verified · 123 ms or error or masked key; 220px secure field (mono 11), Test (round-trips provider's cheapest model), trash. ⤷web adds: proxy base-URL field, localStorage honesty notice.
  2. Models — provider picker, Refresh from API (N live · M not in catalog), Add Custom (sheet: id, name, base URL, context, vision toggle); table: star, name + Featured/Legacy badges, mono id, capability badges, context, $in / $out.
  3. Appearance — theme System/Light/Dark; accents: Sky Indigo #4E6AF0/#6D84F5 (subtle #EBEFFD/#28304C), Graphite #5B6270/#8A93A6 (#EEF0F4/#2A2E3A), Teal #1D9A8F/#3BB5AA (#E6F6F4/#1F3A38), Amber #C77D1D/#DD9B45 (#FBF1E3/#3D3222), Rose #C94F7C/#DE7099 (#FAEAF1/#3D2733); chat font slider 12–18 step 0.5 with live preview card. ⤷web default = light (never dark-auto).
  4. Shortcuts — ⌘N new, ⌘K palette, ⌘F search, ⌘↩ send, ⌘⇧E export, ⌘, settings, ⌘. stop.
  5. Advanced — default system prompt (90px editor); data location note. ⤷web: Data tab (export/import/clear), passphrase lock, streaming toggle.

# Command palette (⌘K, sheet 560, results 380)

Sections: Models (max 8; empty query → recommended; switches current conversation's model) → Personas (max 6; applies system prompt + params + optional model) → Templates (max 10; inserts with {{input}} ← current draft). Row: accent symbol 13 + title 13 / subtitle caption. Native is click-only — ⤷web adds arrow/Enter keyboard nav.

# Compare (sheet ≥900×560)

2–4 equal columns, hairline separators; per-column: model chip, output-token caption, copy, regenerate, remove (>2 only); body = reasoning preview (mono size−2.5, max 6 lines) + markdown at size−0.5 + caret; footer prompt input broadcasts to all columns, each streaming independently; no system prompt, default params, not saved. ⤷web adds "promote answer into thread".

# Empty state

Centered slightly above middle: CloudZGlyph 88 → "Welcome to Zyquo Cloud" 20/semibold → "Your keys, every cloud model, one beautiful chat." (textSecondary) → model chip → 2×2 grid (max 460) of suggestion cards (surface, radius 10, hairline, pad 12): Explain something / Review my code / Summarize a document / Translate. Native has no first-run flow — ⤷web adds the honest localStorage welcome + quick key setup.

# Personas (8 built-ins)

Senior Code Reviewer, Technical Writer, Product Strategist, Research Assistant, Socratic Tutor, UX Critic, Data Analyst, Ruthless Editor — dense ~120-word system prompts, no fixed model (use default), default params. Ported verbatim in Phase 6 (features/personas.ts data).

# Prompt library (56 templates, 8 categories × 7)

Writing / Coding / Analysis / Translation & Language / Business / Learning / Creativity / Productivity; each body contains {{input}} exactly once (missing → input appended). Ported verbatim in Phase 6. Built-ins immutable; user templates appended after.

# ConversationStore behaviors to port

  • Conversations newest-first; search matches title or any message text; 5 sidebar groups.
  • Send: append user msg → placeholder assistant msg → build request from system prompt + messages (excluding placeholder and errored messages) → stream deltas; usage + estimatedCost applied at end. Per-message overrideModel also switches the conversation model.
  • Regenerate drops the trailing assistant turn (⤷web: keep as variant instead — native has no branching/variants; the web app adds variants per assistant message and branch-from-message).
  • Edit & resend rewrites the user message and truncates after it.
  • Auto-title: after first completed exchange (exactly 1 assistant msg, hasAutoTitle true): cheapest non-legacy non-reasoning model for the conversation's provider, non-streaming, maxTokens 24, prompt "Write a title of at most 5 words for this conversation. Reply with the title only, no quotes." + first user text (500 chars) + last assistant text (500 chars); trim quotes/whitespace, cap 60 chars; silent failure; manual rename disables auto-titling.
  • Params per conversation: temperature, topP, maxTokens, frequencyPenalty, presencePenalty, reasoningEffort, thinkingEnabled — nil = provider default, omitted from request; editor only shows rows the model supports, each slider gated by an enable checkbox.
  • Persistence: autosave on every mutation (streaming persisted at stream end, not per-token). ⤷web: IndexedDB, same document shape.

# Brand mark (CloudZGlyph → SVG)

Single-tint glyph, 1024 grid, tight box x 267–770 / y 257–766:

svg
<svg viewBox="0 0 503 509" xmlns="http://www.w3.org/2000/svg">
  <g transform="translate(-267,-257)" fill="none" stroke="currentColor">
    <path d="M320 310H704L320 700H556" stroke-width="106"
          stroke-linecap="round" stroke-linejoin="round"/>
    <rect x="653" y="585" width="104" height="168" rx="24"
          fill="currentColor" stroke="none"/>
  </g>
</svg>

Full app icon (~/Desktop/zyquo-cloud/assets/icon/zyquo-cloud.svg): Big Sur squircle (inset 100, 824 wide) with vertical gradient #6FA8FF → #4E6AF0@52% → #3A3F9E, top gloss, caret glow radial #BFD5FF @ (705,655,r200); Z drawn twice — plum #2A3490 contour at width 132 under near-white face gradient (#FFFFFF → #E9EFFC) at width 106; caret likewise (640,572,130×194,r34 plum under 653,585,104×168,r24 face). Reused for the PWA icon in Phase 5.

# Extras not ported

Quick Chat (⌥Space Spotlight panel) and the menu-bar extra are macOS-only; their role is covered by the web command palette.