01 / 14
AI-Powered UI Testing Platform

PhantomUI

Replace brittle CSS selectors with stable semantic attributes.
Tests that survive every refactor — forever.

Claude MCP Playwright < 5 KB SDK Zero Deps MIT License
<5KB
SDK Size
9
MCP Tools
3
Report Formats
0
Cloud Deps
github.com/ibrahim-abi/phantomui · @phantomui/sdk v0.1.4
PhantomUI v0.1.4
01 — The Problem
02 / 14

UI Tests Break.
Every. Single. Refactor.

CSS selectors tie tests to DOM position, not element meaning. The moment a developer reorganises markup — tests fail. Not because the feature broke. Because a div moved.

💥
30–50% of QA time — spent chasing selectors after routine refactors
🔁
Tests become maintenance burdens — not safety nets — teams stop trusting them
🚨
CI pipelines red on every design change — causing alert fatigue
❌ Fragile
div.container > form
  > div:nth-child(2)
    > input.form-control
✅ Stable
[data-ai-id="login-email"]
02 — The Solution
03 / 14

Describe What, Not Where

Add data-ai-* attributes that describe what an element is — not where it sits. They survive every refactor, forever.

🏷️
Semantic Identity
Elements are described by purpose — login-email, submit-btn — not DOM depth
♾️
Refactor-Proof
Move elements anywhere in the DOM — selectors stay stable and tests keep passing
🤖
AI-Readable JSON
SDK serialises your UI into structured JSON — Claude reads it and generates real tests
Auto-Discovery
Zero annotations? Auto-tagging finds inputs, buttons, and links on any page automatically
03 — Architecture
04 / 14

How PhantomUI Works

Three components. One seamless pipeline. Everything runs 100% locally — no cloud, no telemetry, no registration.

YOUR APP HTML + data-ai-* data-ai-id="login-email" @phantomui/sdk < 5KB · zero deps getSnapshot() → UiSnapshot JSON React · Vue · Angular · HTML JSON MCP SERVER @phantomui/server stdio MCP · HTTP :3100 9 MCP Tools Playwright Dashboard UI · Express ~/.phantomui/runs stdio · HTTP · Webhook MCP AI + EXECUTION Claude AI Anthropic · Ollama · OpenAI-compat generate_tests → TestScenario[] run_tests_parallel HTML · JSON · JUnit XML HTML JSON JUnit XML 100% LOCAL · NO CLOUD · NO TELEMETRY
04 — SDK
05 / 14

@phantomui/sdk — Install Once, Annotate Once

npm install @phantomui/sdk
npm install @phantomui/sdk < 5 KB gzipped Zero dependencies Production safe
ReactuseAiSnapshot()
Vue 3useAiSnapshot() + AiSdkPlugin
AngularAiSdkService
Plain HTML<script> tag
data-ai-* attributes
AttributeValues / Purpose
data-ai-idUnique stable key — snapshot primary ID
data-ai-roleinput · action · display · nav
data-ai-labelHuman label (falls back to textContent)
data-ai-action"submits login form"
data-ai-contextParent form / section name
data-ai-required"true" for required fields
data-ai-statedisabled · loading · active · empty
05 — getSnapshot()
06 / 14

One Call → Structured JSON Claude Can Read

Login form — annotated
getSnapshot() output

Every element becomes a structured descriptor with stable selector, role, label, state, and source. Claude reads this to generate precise tests.

const snap = window.__aiSdk.getSnapshot();

// Returns:
{
  url: "https://app.example/login",
  elements: [
    {
      id:       "login-email",
      role:     "input",
      label:    "Email Address",
      context:  "login-form",
      required: true,
      selector: "[data-ai-id='login-email']",
      source:   "manual"
    }
  ],
  meta: {
    manualCount: 4,
    autoCount: 2,
    sdkVersion: "0.1.4"
  }
}
source: "manual" source: "auto" warnings?: string[]
06 — Auto-Tagging
07 / 14

Zero Annotations? Auto-Discovery.

Auto-tagging on unannotated page

Auto-tagging discovers elements on any page — even with zero data-ai-* attributes. Auto-discovered elements are marked source:"auto".

input, textarea, selectinput
button, [type=submit]action
a[href]nav
h1 – h6display

Framework Adapters

React 16.8+ useAiSnapshot
const { snapshot, refresh, isReady }
  = useAiSnapshot({ autoTag: true });
Vue 3 composable + plugin
const { snapshot } = useAiSnapshot();
// OR: app.use(AiSdkPlugin)
Angular AiSdkService
constructor(private aiSdk: AiSdkService) {}
ngOnInit() { this.snap = this.aiSdk.getSnapshot(); }
07 — MCP Server
08 / 14

@phantomui/server — Two Transports, One Server

stdio transport — Claude Code & Claude Desktop connect via MCP protocol
HTTP :3100 — CI pipelines, webhooks, and the local dashboard
LLM Adapter — Anthropic · Ollama · OpenAI-compatible — auto-detected
Playwright Runner — Headless Chromium executes generated test scenarios
Result Store — Runs persisted to ~/.phantomui/runs as JSON
LLM Auto-Detection
ANTHROPIC_API_KEY? Claude · OPENAI_COMPATIBLE_BASE_URL? OpenAI · Ollama (fallback)
Claude Code Claude Desktop CI / Dashboard curl · webhook · browser stdio HTTP MCP Server 9 MCP Tools Runner Express LLM Adapter ~/.phantomui/runs TypeScript · Node.js Playwright Chromium Claude AI generate_tests Reports HTML · JSON · XML
08 — MCP Tools
09 / 14

9 Tools. One Prompt.

Claude orchestrates the full pipeline by chaining tools automatically. You never write test code.

01
get_ui_snapshot
Navigate to URL, inject SDK, return full UiSnapshot via Playwright
02
list_elements
Filter snapshot by role (input/action/nav) or source (manual/auto)
03
generate_tests
AI generates TestScenario[] from snapshot + optional natural-language hints
04
run_test
Execute a single scenario step-by-step with Playwright
05
run_tests_parallel
Up to 10 concurrent browsers with network mocking & session injection
06
get_results
Full step-by-step result with timing and errors for any run ID
07
retry_failed
Re-run only failed steps with optional per-step overrides
08
save_report
Export HTML · JSON · JUnit XML to any file path
09
diff_snapshots
Compare two snapshots — returns added, removed, changed element arrays
09 — Workflow
10 / 14

End-to-End in One Prompt

You type in Claude:
"Test the login form at localhost:3000. Include an invalid credentials scenario. Save an HTML report to ./reports/login.html"
1
get_ui_snapshot — Playwright opens page, SDK scans, returns 6 elements
2
generate_tests — Claude creates 3 scenarios: happy path, wrong password, empty fields
3
run_tests_parallel — 3 Chromium instances run concurrently — fully isolated
4
get_results — Step-by-step pass/fail with timing for each scenario
5
save_report — Self-contained HTML report at ./reports/login.html
3 / 3 passed · 100% element coverage · < 8s total
Claude running the test pipeline
get_ui_snapshot → UiSnapshot JSON
generate_tests → TestScenario[]
run_tests_parallel → TestResult[]
save_report → HTML · JUnit · JSON
10 — Dashboard
11 / 14

Local Dashboard at localhost:3100

Home — enter any URL
After capture — element cards
Elements grid — role filters
One-click report export

A full dark-mode UI served at GET /. No cloud. No account. Start with one command.

node dist/index.js --port 3100
📸 Snapshot any URL — Playwright navigates headlessly
🏷️ Element grid — filter by role badge (input/action/nav)
📋 Run history — all test runs with pass/fail and duration
📊 One-click reports — HTML, JSON, JUnit directly from UI
REST API (same server)
GET/healthliveness probe
POST/snapshotcapture page
POST/runrun scenario
GET/runslist all runs
POST/reportgenerate HTML/XML
11 — CI/CD
12 / 14

Plug Into Any Pipeline

3 report formats — HTML · JSON · JUnit XML
🌐
HTML
Self-contained report with element coverage and inline data
📋
JUnit XML
GitHub Actions · Jenkins · GitLab CI · CircleCI test panels
{ }
JSON
Machine-readable for custom pipelines and integrations

The reusable composite GitHub Action runs PhantomUI in any workflow — takes a URL and an API key, publishes JUnit results.

# .github/workflows/ui-tests.yml
- uses: ./.github/actions/run-tests
  with:
    url: https://staging.example.com
    format: junit
    anthropic-api-key:
      ${{ secrets.ANTHROPIC_API_KEY }}
    hints: "test auth flow + dashboard"

# Automatically:
# ✓ Installs Playwright + Chromium
# ✓ Runs all test scenarios
# ✓ Publishes JUnit test panel
# ✓ Uploads HTML as artifact
# ✓ Fails build on test failure
GitHub Actions Jenkins GitLab CI CircleCI Webhook
12 — Getting Started
13 / 14

Up & Running in 5 Minutes

1
Tag your HTML
2
Install the SDK
npm install @phantomui/sdk
3
Connect MCP to Claude
claude mcp add --transport stdio phantomui \
  node /path/to/server/dist/index.js
4
Ask Claude to test your UI
"Test the login form at localhost:3000
 and save an HTML report"
Environment Variables
ANTHROPIC_API_KEYRequired for Claude
LLM_PROVIDERanthropic · ollama · openai-compatible
AI_MODELOverride model (e.g. claude-opus-4-6)
RESULT_STORE_PATHDefault: ~/.phantomui/runs
HEADLESSfalse = show browser window
WEBHOOK_URLPOST results after every run
Claude Desktop Config
{
  "mcpServers": {
    "phantomui": {
      "command": "node",
      "args": ["/path/to/server/dist/index.js"]
    }
  }
}
Or: dashboard at localhost:3100
13 — Summary
14 / 14

Build Once.
Test Semantically.
Never Chase a Broken Selector Again.

PhantomUI v0.1.4
<5KB
SDK Size
9
MCP Tools
3
Adapters
3
LLM Providers
0
Cloud Deps
Star on GitHub
github.com/ibrahim-abi/phantomui
📦
Install the SDK
npm install @phantomui/sdk
🚀
Run the Server
node dist/index.js --port 3100
"Ask Claude: Test the login form at localhost:3000"
get_ui_snapshot generate_tests run_tests_parallel save_report
Open Source · MIT License · Muhammad Ibrahim · March 2026