# Stateproof > Precise frontend runtime state validation in a controlled browser. Intercept network requests at the browser layer without modifying application code. Forces loading, empty, error, and offline states to generate visual proof cards. ## Key Features - **Browser-Level Interception**: Intercepts requests inside a controlled Chromium instance via Playwright CDP. Zero MSW, zero proxies, zero app code alterations. - **Strict Deterministic States**: Test 4 key frontend states: - `loading`: Delay network responses (e.g. 500ms - 3000ms) to assert skeleton or spinner visibility. - `empty`: Fulfill with empty JSON array or fixture file (`[]`, `{ items: [] }`) to assert empty-state UI. - `error`: Fulfill with HTTP 4xx/5xx status codes to assert error alerts and retry controls. - `offline`: Simulate network disconnection (`internetdisconnected`) to assert offline banners. - **Model Context Protocol (MCP)**: Native bridge for Cursor, Claude Desktop, GitHub Copilot, and Antigravity agents. - **Zero Telemetry & Local-First**: Runs only on local loopback (`localhost`, `127.0.0.1`). Screenshots and reports write to local disk. --- ## Agent Setup & Prompting ### MCP Configuration Add to your AI agent's MCP settings (`.cursor/mcp.json` or `claude_desktop_config.json`): ```json { "mcpServers": { "stateproof": { "command": "npx", "args": ["-y", "@stateproof-dev/mcp-server"] } } } ``` ### Agent Prompt Cheatsheet To instruct an AI coding agent to configure Stateproof in a repo, provide this prompt: ```text Setup Stateproof in this repository: 1. Initialize config: npx @stateproof-dev/cli init --url http://localhost:5173 2. Inspect frontend components and write stateproof.scenarios.json covering: - loading (delay: 500ms -> visible: loading indicator selector) - empty (fixture or inline [] -> visible: empty state selector) - error (error: 500 -> visible: [error-message-selector, retry-button-selector]) - offline (mode: offline -> visible: offline-notice-selector) 3. Execute validation: npx @stateproof-dev/cli run 4. Export Markdown PR card: npx @stateproof-dev/cli export --format md ``` --- ## CLI Reference All commands run via `npx @stateproof-dev/cli`: - `npx @stateproof-dev/cli init [--url ] [--route ]`: Scaffold `stateproof.scenarios.json`, fixtures directory, and `.gitignore`. - `npx @stateproof-dev/cli --tui` (or `studio`): Launch interactive terminal UI for selecting and testing individual scenarios. - `npx @stateproof-dev/cli run [scenario-ids...]`: Run headless browser validation against the local application. - Flags: `--file `, `--url `, `--viewport `, `--reporter human|json`, `--allow-remote`, `--allow-third-party`. - `npx @stateproof-dev/cli list`: Validate and print defined scenarios and viewports without launching a browser. - `npx @stateproof-dev/cli export --format md|json`: Export Stateproof Card markdown or machine JSON from the latest run. --- ## Scenario File Schema (`stateproof.scenarios.json`) ```json { "$schema": "https://unpkg.com/@stateproof-dev/core@0.1.1/schema/v1.json", "name": "account-settings", "baseUrl": "http://localhost:5173", "route": "/settings", "viewports": [ { "name": "desktop", "width": 1440, "height": 1024 }, { "name": "mobile", "width": 390, "height": 844, "isMobile": true } ], "scenarios": [ { "id": "loading", "label": "Loading Skeleton State", "request": { "method": "GET", "urlPattern": "**/api/account" }, "response": { "mode": "delay", "milliseconds": 500 }, "expect": { "visible": "[data-state='loading']" } }, { "id": "empty", "label": "Empty State", "request": { "method": "GET", "urlPattern": "**/api/account" }, "response": { "mode": "fixture", "path": "fixtures/empty.json" }, "expect": { "visible": "[data-state='empty']" } }, { "id": "error", "label": "Server Error 500 State", "request": { "method": "GET", "urlPattern": "**/api/account" }, "response": { "mode": "error", "status": 500, "body": { "error": "Internal Server Error" } }, "expect": { "visible": ["[data-state='error']", "[data-testid='retry']"] } }, { "id": "offline", "label": "Offline Network Failure", "request": { "method": "GET", "urlPattern": "**/api/account" }, "response": { "mode": "offline" }, "expect": { "visible": "[data-state='offline']" } } ] } ``` --- ## Response Modes Reference 1. **`delay`**: Holds matched requests unresolved for `milliseconds` while waiting for the loading selector, then cancels gracefully. 2. **`fixture`**: Fulfills the request with a local file from `path` (e.g. `fixtures/empty.json`). 3. **`inline`**: Fulfills the request with inline JSON payload in `data`. 4. **`error`**: Returns HTTP `status` code (e.g. 500, 403, 404, 503) with optional JSON `body`. 5. **`offline`**: Aborts request with `internetdisconnected` network error. --- ## Exit Codes - `0`: All scenarios passed across all viewports. - `1`: One or more scenarios failed assertion or selector timeout. - `2`: Schema validation or syntax error in scenario configuration. - `3`: Target server unreachable or missing browser binary. - `4`: Internal execution error.