@wcgw/vibe-check-core
v0.3.0
Published
Framework-agnostic performance monitoring engine with AI/vibe-coding issue detection
Maintainers
Readme
@wcgw/vibe-check-core
Framework-agnostic browser performance monitoring engine with AI/vibe-coding issue detection. Zero runtime dependencies.
Installation
npm install @wcgw/vibe-check-coreUsage
import { VibeCheckEngine } from '@wcgw/vibe-check-core'
const engine = new VibeCheckEngine()
engine.start()
// Get a performance snapshot
const snapshot = engine.getSnapshot()
console.log(snapshot.frameRate.fps)
console.log(snapshot.issues)
// Subscribe to snapshot updates
const unsubscribe = engine.onSnapshot((snapshot) => {
if (snapshot.issues.length > 0) {
console.warn('Performance issues detected:', snapshot.issues)
}
})
// Clean up
engine.stop()
unsubscribe()Configuration
const engine = new VibeCheckEngine({
// Send snapshots to an MCP server
beaconUrl: 'http://127.0.0.1:4200',
projectId: 'my-project',
})Collectors
Collectors measure browser metrics continuously:
- Frame Rate -- FPS, frame times, dropped frames via
requestAnimationFrame - Long Frames -- Long Animation Frames (LoAF) API with script attribution
- Web Vitals -- LCP, CLS, INP via PerformanceObserver
- Memory -- JS heap size via
performance.memory - Resources -- Resource loading performance and sizes
- Console -- Tracks console.log/warn/error volume
Detectors
Detectors analyze snapshots and flag issues.
All 13 detectors are enabled by default; toggle any of them via config.detectors.
| Detector | What it catches | Threshold |
|----------|-----------------|-----------|
| dom-bloat | Excessive DOM nodes and deep nesting | ≥ 800 nodes (warning), ≥ 1,500 (error) |
| duplicate-requests | The same URL + method fetched repeatedly | 2+ identical requests within 2s |
| console-spam | High-volume console output | > 20 calls per 10s window |
| memory-leak | Steadily growing JS heap without GC recovery | > 10% growth over 30s (warning), > 25% (error) |
| layout-thrashing | Clusters of layout shifts without user input | ≥ 3 shifts within 500ms |
| unoptimized-images | Missing dimensions/lazy/alt, oversized, or distorted images | natural > 2× rendered; aspect mismatch > 0.15 |
| large-images | Oversized image transfers | ≥ 500KB (warning), ≥ 1,024KB (error) |
| long-task-attribution | Scripts causing long animation frames (LoAF) | ≥ 3 long frames attributed to one source |
| resource-bloat | Oversized JS/CSS/font/image resources | ≥ 100KB (prod) / 500KB (dev) |
| web-essentials | Missing document essentials (favicon, viewport, lang, charset) | 4 document checks |
| heavy-library | Known heavy libraries and their pitfalls | 16 library signatures |
| seo | Discoverability / search-visibility problems | 20 checks (title ≤ 60, description ≤ 160 chars, …) |
| aeo | AI answer-engine / agent readiness | 9 checks |
Audit checks
The seo, aeo, and web-essentials detectors each emit one issue per failed check.
Search visibility (seo) — 20 checks
title-missing— Missing page titletitle-too-long— Page title is too longtitle-default— Page title is a framework defaultmeta-description-missing— Missing meta descriptionmeta-description-too-long— Meta description is too longog-image-missing— Missing social preview image (og:image)og-title-missing— Missing og:titleog-description-missing— Missing og:descriptioncanonical-missing— Missing canonical linkh1-missing— No headingh1-multiple— Multiple headingsimage-alt-missing— Images missing alt textslug-unfriendly— Unfriendly URL slugnoindex— Page is set to "noindex"title-too-short— Page title is very shortog-url-missing— Missing og:urltwitter-card-missing— Missing Twitter/X cardgeneric-link-text— Vague link textsitemap-missing— Missing or invalid sitemap.xmlrobots-missing— Missing robots.txt
AI answer-engine readiness (aeo) — 9 checks
structured-data-missing— No structured data (JSON-LD)structured-data-invalid— Structured data is invalidno-main-landmark— No landmarkno-author-metadata— No author or date signalsllms-txt-missing— No llms.txtcontent-requires-js— Content only renders with JavaScriptmarkdown-negotiation-missing— No markdown content negotiationai-crawlers-blocked— robots.txt blocks AI crawlersmcp-discovery-missing— No agent interface (MCP) advertised
Document essentials (web-essentials) — 4 checks
favicon— Missing faviconviewport— Missing viewport meta taglang— Missing lang attribute oncharset— Missing charset declaration
Headless usage (any framework)
core has zero runtime dependencies and no React coupling — use it from any (or no)
framework. The React widget in @wcgw/vibe-check is one consumer of the
engine below.
import { VibeCheckEngine } from '@wcgw/vibe-check-core'
const engine = new VibeCheckEngine({
beaconUrl: 'http://127.0.0.1:4200',
projectId: 'my-project',
})
engine.onSnapshot((s) => {
console.log(s.frameRate.fps, s.issues.length)
})
engine.start()For deterministic demos, createScriptedEngine(scenario) implements the same public
surface (start/stop/getSnapshot/onSnapshot/…) but replays a canned timeline
of snapshots + issues instead of reading live collectors.
API
VibeCheckEngine
start()— begin monitoringstop()— stop monitoring and clean upisRunning(): boolean— whether the engine is currently runninggetSnapshot(): VibeSnapshot— current performance snapshotgetIssues(): readonly VibeIssue[]— current issues from all enabled detectorsclearIssues(): void— clear the issues buffer on every detectoronSnapshot(cb): () => void— subscribe to snapshot updates (fires every 500ms). Returns an unsubscribe function.
Types
All types are exported: VibeSnapshot, VibeIssue, FrameRateStats, LongFrameStats, WebVitalsStats, HeapMemory, ResourceStats, ConsoleStats, VibeCheckConfig, Collector, Detector, DetectorName, Severity, etc. See src/types.ts for the full surface.
License
MIT
