# Architecture

> How core, react, mcp, and the protocol package fit into one pipeline.

VibeCheck is a short, one-directional pipeline. Metrics are measured in the
browser, turned into issues, POSTed to a local server, and read back by your
coding agent. Four packages divide that work along a single seam: the browser
side and the agent side never share a runtime, only a wire contract.

## The pipeline

## The packages

| Package | Role | Runtime deps |
| --- | --- | --- |
| `@wcgw/vibe-check-core` | Collectors, detectors, `VibeCheckEngine`, `BeaconClient`. | Zero. |
| `@wcgw/vibe-check` | React overlay (`<VibeCheck />`, `<PerfToggle />`) + hooks. | React 18+ (peer). |
| `@wcgw/vibe-check-mcp` | Shared HTTP hub + stdio bridge exposing nine project-scoped tools. | `@modelcontextprotocol/sdk`, `zod`. |
| `@wcgw/vibe-check-protocol` | Snapshots, issues, project envelopes, dispatch results, and lease states. | Zero. Internal — bundled into the others. |

## The decoupling seam

The MCP package does **not** import core. The browser produces a `VibeSnapshot`,
serializes it to JSON, and POSTs it; the server parses and validates it back
into the same shape. Both sides depend on `@wcgw/vibe-check-protocol` for that
type — core imports it type-only (preserving its zero-runtime-deps promise),
while mcp also imports the `DETECTOR_NAMES` and `SEVERITIES` const arrays to
build its `zod` validation schema. Deriving both from one source makes drift
between browser and agent a compile error rather than a silent bug.

**Why the split matters**

  You can run any layer on its own: `core` headless with no UI, the React widget
  with no MCP server, or the MCP server with any beacon pointed at it. Nothing
  above requires the layer below to be present.

## What runs where

- **In the browser** — collectors measure the page, detectors analyze each
  snapshot into issues, the engine orchestrates them, and the beacon (when a
  `beaconUrl` is configured) ships snapshots out.
- **On your machine** — one hub holds isolated project stores, queues, and
  leases. Each agent client spawns a stdio bridge that talks to that hub. Only
  the hub binds the browser port.

## Keep reading

  - [Collectors](/docs/concepts/collectors.md): The six browser measurements and the Collector interface.
  - [Detectors & audits](/docs/concepts/detectors.md): How snapshots become issues.
  - [The Engine](/docs/concepts/engine.md): Orchestration, config, and the scripted engine.
  - [The Beacon](/docs/concepts/beacon.md): How snapshots reach the MCP server.
