cocottetech/@platform/codebase/@features/ai-copilot/docs/G-web-surfaces.brief.md
natalie 1b719e1fd7 chore(bootstrap): initial V4 commit
Clean successor to V3 (forge: lilith/atlilith). Seeded from local Mac
working tree at ~/Code/@projects/@cocottetech/. node_modules and build
artifacts excluded via .gitignore.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 08:11:41 -07:00

3.9 KiB

G — Web secondary surfaces

Goal

Web FEs (React 19 + Vite, hosted on vps-0) for visual / bulk / replay work that's wrong-shaped for a phone chat. Same auth, same tokens, same component conceptual model as iOS — but desktop-first.

Designer skim

  • Headline UX: Desktop is the inspection/power-user surface; iOS is daily-driver. Every web action is also reachable by asking ai-copilot on phone. Same auth + tokens + components conceptually.
  • Surfaces (4): G1 content-portal (calendar, asset lib, persona) · G2 engagement-portal (CRM prospect table, funnel telemetry) · G3 agent-actions log viewer · G4 ai.cocotte.maison web companion.
  • Pair-with: cross-device-handoff.flow.md.
  • Blocking Qs: OPEN-DECISIONS.md → G-Q1 companion parity-vs-divergent.

Constraints

  • React 19 + Vite; design tokens shared with iOS via brief F.
  • Hosted on vps-0; consumed by Quinn at her laptop. Mobile web works but isn't the target.
  • Auth via the same SSO that CocotteAI uses.
  • Every action exposed in web is also reachable by asking ai-copilot in iOS — web is the inspection / power user surface, not the primary.

Surfaces

G1 — content-portal (content.cocotte.maison)

  • Calendar grid: month view, drag-to-reschedule, multi-select for batch approval. Same content_plans data as iOS calendar drawer (brief B1).
  • Asset library: large grid, batch tag editing, drag-upload, presigned URL flow to MinIO. Mirrors iOS asset drawer (B2).
  • Persona editor: keyboard-driven JSON-facet editor with side-by-side preview. Mirrors B5.

G2 — engagement-portal (engagement.cocotte.maison)

  • Prospect list (CRM-style): sortable table — surface, funnel stage, last contact, value-to-date.
  • Prospect detail page: full cross-surface message history, all drafted-but-unsent replies, value timeline.
  • Funnel telemetry charts: per-surface, aggregate, time-series. Data source: TimescaleDB hot tier on vps-0.

G3 — agent-actions log viewer

  • Reverse-chronological table of every specialist decision. Filter by specialist_id, action_type, stakes, outcome.
  • Tap row → full outcome_json viewer with diff highlighting (when target_kind has a before/after state).
  • Replay mode: scrub timeline by date range, see "what would the cache state look like at T?"

G4 — ai.cocotte.maison (web companion)

  • Lightweight web version of CocotteAI's chat surface, used when Quinn is on a laptop and doesn't want to switch to the phone.
  • Same chat + approval-card UX as iOS (brief A); rendered with React equivalents of the SwiftUI components.

Constraints per-surface

  • Auth-gated; no public reads.
  • Reads from prod platform.api on black via HTTPS (single API plane — no dev API).
  • Public anonymous reads (e.g. brand sites) live elsewhere (cocotte.maison Cocotte umbrella, sansonnet.maison, tour brand sites at adulttherapytour.com / futawaifutour.com, talent site transquinnftw.com); these portals are operator-only.

States to design (per surface)

  • Idle / empty / loaded / error / offline / forbidden (auth expired).

In-the-wild copy

G3 · agent-actions log filter chip (plain — power-user surface):

specialist: content-onlyfans · last 24h · auto-only · 47 rows

G2 · prospect CRM table empty filter (working):

Nothing in this slice yet. Loosen a filter or check the funnel chart.

G4 · web-companion offline notice (plain):

Lost connection. Re-sync when you're back.

Out of scope

  • Marketing pages (separate cocottetech.com design).
  • Admin / billing (platform-admin surface — different brief).

Open questions

  • Single SPA per portal vs one mega-SPA with internal routing?
  • Should web companion (G4) maintain UI/UX parity with iOS, or is desktop allowed to diverge in IA (e.g. side-panel with persistent drawer)?
  • Cache invalidation in the browser: do we listen on Redis pub/sub via SSE on vps-0, or poll?