TL;DR
You can inspect a page for signs of AI-assisted generation without uploading its HTML to a server. This tutorial walks through Vibe Code Detector, an open-source Chrome extension that runs weighted heuristics in the browser and reports a score with the detected factors.
The useful engineering idea is not the label. It is the separation between observable signals, a transparent scoring model, and a user interface that lets you inspect why a result happened.
The problem: a score is easy, an explainable score is harder
Browser extensions that inspect page structure face an awkward tradeoff. A simple rule can find a marker such as data-radix-*, a Lucide SVG, or a generator meta tag. But any one marker is weak evidence. Modern sites can use the same libraries for ordinary reasons, and a generated site may remove or change those markers.
Vibe Code Detector combines several signals instead of treating one match as proof. Its canonical factor list includes utility-class density, Shadcn or Radix markers, Lucide iconography, AI IDE markers, platform signatures, prompt-like comments, provider metadata, placeholder text, and other structural clues. Each factor has a weight, and the result exposes the individual detections.
That makes the extension useful as a forensic hint, not as an authorship detector. The distinction matters: the project documentation describes heuristic analysis, while the implementation can only observe the current document and its accessible markup.
Prerequisites
You need:
- Node.js 20 or a compatible current Node.js installation
- npm
- Google Chrome or another Chromium browser that supports Manifest V3
- A page you are allowed to inspect
The repository is released under the MIT License. The current main branch reports version 1.0.0 in both package.json and extension/manifest.json.
Build the extension from source
Clone the public repository and install its locked dependencies:
git clone https://github.com/paladini/vibe-code-detector.git
cd vibe-code-detector
npm ci
Build the extension and run the TypeScript check:
npm run lint
npm run build
The lint script runs tsc --noEmit. The Vite build writes the extension assets into extension/, including the popup page and bundled assets. The release workflow uses the same build command before packaging extension/ into a zip.
To load the result locally, open chrome://extensions, enable Developer mode, choose Load unpacked, and select the repository's extension/ directory. The manual installation path is also documented in the project README.
How the scanner works
The implementation keeps its factor definitions in src/lib/vibe-detector.ts. The same analysis function is used by the web preview and popup, while the content script contains an inlined copy because browser content scripts do not use the project's module imports directly.
The main path is straightforward:
- Read the active document's HTML and element structure.
- Count utility classes and compare the count with the number of elements.
- Check for known Shadcn, Radix, Lucide, IDE, and platform markers.
- Walk comment nodes for prompt-like or generated-by text.
- Add the weights of detected factors.
- Clamp the score to 100 and return the factor list.
For example, the utility-density rule counts whitespace-separated classes on elements and marks the factor when the average exceeds 4.5, or when the HTML includes the tw- prefix. The Shadcn and Radix rule requires at least three markers from a small list that includes bg-background, text-foreground, data-radix-, data-state=, rounded-xl, and border-input.
The result is intentionally inspectable. A caller receives a score plus factors shaped like this:
export interface VibeResult {
score: number;
factors: VibeFactor[];
}
This structure is more valuable than a bare boolean because it supports review. Someone examining a high score can ask which signals fired and whether those signals make sense for the page.
Verify the behavior without trusting the label
Use two pages with different characteristics. First, inspect a normal documentation or application page that uses a component library. Then inspect a page that clearly contains one or more generator markers. Compare the factor list, not just the final score.
The project has a practical constraint: extension/content.js must stay synchronized with src/lib/vibe-detector.ts. If you change a heuristic, update both paths and rebuild. Otherwise the preview and the loaded extension can disagree even though the TypeScript source looks correct.
You can also verify the packaged output by checking that the build produced extension/popup.html and the generated JavaScript and CSS assets. The repository's release workflow runs npm ci, npm run build, checks that the package and manifest versions match, then creates a zip and SHA-256 checksum.
Failure modes and security boundaries
A high score is not proof
Tailwind, Radix, Lucide, and motion libraries are popular outside AI-generated projects. Conversely, a site can be generated with an AI tool and remove the visible markers. Treat the score as a collection of clues. Do not use it as evidence of who wrote a page or as an automated moderation decision.
The scan is document-local
The core function receives a Document and reads its DOM, HTML, and comments. It does not establish provenance, inspect a private repository, or recover an author's workflow. Results can change after client-side rendering, navigation, or a site redesign.
Permissions still matter
The manifest requests activeTab and scripting, and its content script matches <all_urls>. Install the extension only from a source you trust, review permission changes, and inspect the code before loading an unpacked build. The repository recommends the Chrome Web Store listing for normal installation, while source loading is useful for development and review.
Dependency health is separate from scanner logic
In a fresh checkout on August 10, 2026, npm ci completed and reported 19 audit findings: 2 low, 7 moderate, 9 high, and 1 critical. That result is not proof that the extension is exploitable, but it is a reason to review the dependency tree before distributing a build. Run npm audit yourself and reassess the result as dependencies change.
FAQ
Does it detect whether a human or AI wrote a page?
No. It detects implementation and markup signals that may correlate with AI-assisted tools. The score is heuristic evidence about the page, not an authorship verdict.
Does the extension upload the page?
The documented analysis function operates on the active page's Document. Review the current repository and manifest before installing any version, especially if future releases add network features.
Can I add another AI tool signature?
Yes. Add a narrowly defined marker or factor to the canonical TypeScript implementation, mirror the change in extension/content.js, then run npm run lint and npm run build. A good contribution should include a reason the signal is useful and a note about false positives.
Takeaway
The strongest part of this project is its boundary: it turns a vague question about a web page into a visible list of weighted, testable signals. That does not make the conclusion certain. It makes the reasoning inspectable, which is the better property for a browser tool that deals with ambiguous evidence.
AI assistance disclosure: I used an AI assistant to help organize this tutorial and check the documented build path. The repository behavior, commands, permissions, and limitations were verified against the public source and a fresh local build.
What additional page signal would you test first, and how would you measure whether it adds useful evidence without increasing false positives?
Top comments (0)