Architecture
This is the architecture reference. For a friendlier introduction, see How Mosayic Works.
Components
Section titled “Components”┌─────────────────────────────────┐│ Mosayic Dashboard (mosayue) ││ https://app.mosayic.io ││ Vue 3 + Vite SPA │└──────────────┬──────────────────┘ │ HTTPS │ Authorization: Bearer <supabase JWT> ▼┌─────────────────────────────────┐│ Mosayic Backend API ││ mosayic-api ││ FastAPI on Google Cloud Run │└────┬─────────────────┬──────────┘ │ WebSocket │ REST │ Bearer auth │ (CRUD on projects, │ │ variables, etc.) ▼ ▼┌──────────┐ ┌──────────────────┐│ VS Code │ │ Supabase ││ Extension│ │ (Mosayic's own) ││ (yours) │ │ │└──────────┘ └──────────────────┘Dashboard (mosayue)
Section titled “Dashboard (mosayue)”- Stack: Vue 3 (Composition API) + Vite + Tailwind CSS 4
- Routing: Vue Router 5, file-based
- Auth: Supabase JS SDK (Google OAuth via PKCE)
- HTTP client: native
fetchwith a thin wrapper that injects the Supabase JWT
The dashboard is a static SPA. It doesn’t run any backend code of its own — every operation either:
- Hits the Mosayic API directly (
POST /projects/.../scaffold,GET /commands/status, etc.) - Or kicks off a flow that the backend relays to your VS Code extension via WebSocket
Backend API (mosayic-api)
Section titled “Backend API (mosayic-api)”- Stack: FastAPI 0.119 + Python 3.10-3.12
- Server: Uvicorn on port 8080 (in container; published as 443 by Cloud Run)
- Database: Supabase Postgres, accessed via
supabasePython client (no SQLAlchemy — direct PostgREST queries) - Auth: validates Supabase JWTs via
supabase.auth.get_user(jwt=token) - WebSocket: one persistent connection per user, used to relay commands to and from the user’s VS Code extension
- External integrations: none (relays to the user’s CLIs via the extension; doesn’t talk to GitHub/GCP/Expo on the user’s behalf except through the extension running their CLIs)
Key endpoints:
| Path | Purpose |
|---|---|
GET /health | Health check (no auth) |
GET /auth/vscode/login | OAuth PKCE entrypoint for the extension |
GET /auth/vscode/callback | OAuth callback that redirects to vscode:// |
POST /auth/vscode/refresh | Token refresh |
WS /ws | Persistent socket for an authenticated extension |
GET /commands/status | Is the user’s extension connected? |
POST /commands/run | Run a one-shot command (sync) |
POST /commands/stream | Run a command, stream output as SSE |
POST /commands/terminal | Open a VS Code terminal and run a command |
POST /dev-server/start / stop / input | Manage long-running dev servers |
POST /projects/:id/scaffold | Background task that scaffolds a new project |
POST /projects/:id/github/create-repos | Create user’s repos via gh |
POST /projects/:id/secrets/... | Persist secrets via gcloud / gh |
POST /projects/:id/release/... | Pre-flight, create release, deploy API, sync EAS |
POST /projects/:id/supabase/setup | Start local Supabase via the CLI |
VS Code Extension (vscode-mosayic)
Section titled “VS Code Extension (vscode-mosayic)”- Stack: TypeScript on the VS Code extension API
- Activation:
onStartupFinished - Connection: single WebSocket to the backend, authenticated with the user’s Supabase JWT in the upgrade headers
- UI: a status bar item and the standard Output channel — no webviews, no custom panels
- Storage: tokens in VS Code
secretStorage(OS keychain)
Message types it handles from the backend:
| Type | Action |
|---|---|
command | Run shell command, stream output, return result |
terminal_command | Open a VS Code terminal and run a command |
start_dev_server | Open a managed pseudoterminal, run a long-running command, stream output |
stop_dev_server | Kill a managed pseudoterminal |
terminal_input | Forward keystrokes to a managed pseudoterminal |
dev_server_status | Report whether a managed session is alive |
pick_folder | Open a native folder picker |
open_folder | Open a folder as the workspace |
send_to_terminal | Send text to a named existing terminal |
ping | Reply with pong |
Data ownership
Section titled “Data ownership”| Data | Lives in | Mosayic accesses? |
|---|---|---|
| Your Google profile | Supabase Auth (Mosayic’s project) | Yes (read) |
| Project metadata (name, paths, URLs) | Supabase Postgres (Mosayic’s project) | Yes |
| Mobile / API source code | Your machine + your GitHub | No |
| Local Supabase data | Your machine (Docker volume) | No |
| Production Supabase data | Your hosted Supabase project | No |
| Secrets (Supabase service key, etc.) | Your Google Cloud Secret Manager | No (transits the relay; not persisted) |
| GitHub Actions secrets | Your GitHub repo | No |
| Production API code | Your Google Cloud Cloud Run | No |
| Your users’ data | Your hosted Supabase | No |
The blunt summary: Mosayic owns the project list and the Google Sign-In session. Everything else belongs to you, on your services.
Communication patterns
Section titled “Communication patterns”REST (dashboard ↔ backend)
Section titled “REST (dashboard ↔ backend)”Standard HTTP requests with Authorization: Bearer <token> and JSON bodies. 30-second timeout on the client.
Server-Sent Events (backend → dashboard)
Section titled “Server-Sent Events (backend → dashboard)”Used for streaming long-running command output to the dashboard. The dashboard’s fetch consumes the response as a stream and parses data: { ... }\n\n events.
WebSocket (extension ↔ backend)
Section titled “WebSocket (extension ↔ backend)”JSON messages over a persistent socket. Each message has a type and (for request/response pairs) a request_id. The backend tracks pending request IDs in an in-memory dict; when the response comes back, it resolves the matching asyncio.Future.
URI scheme (dashboard → extension, indirectly)
Section titled “URI scheme (dashboard → extension, indirectly)”The dashboard renders links like <a href="vscode://mosayic.vscode-mosayic/wake">. Clicking such a link causes VS Code to fire a URI handler in the extension, which can then trigger commands like reconnect or focus.
Deployment
Section titled “Deployment”| Component | Where |
|---|---|
| Dashboard | Static SPA hosted on (likely) Cloud Run/Vercel/similar at app.mosayic.io |
| Backend | Google Cloud Run (mosayic-api-service-...run.app) |
| Extension | Visual Studio Marketplace, distributed to users |
| Mosayic’s database | Supabase (separate from any user’s project) |
CI/CD lives in .github/workflows/ of the mosayic-api repo: gcp-deploy.yaml (Cloud Run), supabase-deploy-migrations.yaml, scheduled-backups.yaml.
Failure modes
Section titled “Failure modes”- Extension WebSocket drops — exponential backoff (1s, 2s, 5s, 10s, 30s) for up to 10 attempts. After that, manual reconnect.
- Backend restarts — all in-flight WebSocket sessions drop. Extensions reconnect within seconds.
- Two extensions per user — newer wins, older closed with code 4001. By design.
- Token expiry mid-session — extension auto-refreshes via
/auth/vscode/refreshbefore expiry. - Scaffold mid-flight — backend tracks scaffold state in-process. If the backend container restarts, the dashboard sees the scaffold as “stuck” — there’s no resumption today (this is on the roadmap).