/methodology

How the scan works

slop-detect scores a page against a fixed, weighted catalogue of the CSS and copy tells that Cursor, v0, Lovable, and Bolt converged on. It runs in real headless Chromium against the page's own computed styles. Same page in, same score out: no model, no randomness, auditable, reproducible, safe to gate CI on.

A fingerprint, not a verdict. Everyone uses AI now; the score measures how generic the result reads, nothing about the team behind it. The full positioning against ML detectors and Lighthouse lives at /compare; the live catalogue is at /api/patterns (definitions·2026.09).

01

The four axes

A page can be slop in more than one way. slop-detect scores four independent axes; the two slop axes want a low score, the system and AEO axes want a high one.

AxisWhat it measuresPolarity
design slopThe original CSS fingerprint: 27 weighted tells AI builders converged on — slop fonts, purple CTAs, gradient text, glassmorphism, bento grids.lower is better
copy slop9 text tells on the page's own prose: buzzword density, em-dash overload, the "not just X, it's Y" antithesis, filler openers.lower is better
system · DESIGN.mdDoes the page honor its own declared design system? Named, contestable drift against a DESIGN.md, never a verdict.higher is better
AEO · agent-readableCan AI engines fetch, read, and cite the page? 8 weighted checks against the live crawler registry.higher is better
02

Install

Nothing to set up for a one-off scan. npx fetches the CLI, opens the page in a real browser, and prints the score.

bash
# one-off scan, zero install
npx slop-detect https://your-site.com

# or install the CLI globally
npm i -g slop-detect
slop-detect https://your-site.com
03

The CLI

Score one or many URLs. The flags compose: axes, presets, the system axis, CI gating.

bash
slop-detect <url> [...urls]        # score one or many pages
  --copy              # also score the copy axis
  --axes all          # design + copy together
  --design-md auto    # check against <origin>/DESIGN.md
  --preset strict     # score a curated subset
  --remote            # scan via the API, no local browser
  --json              # machine-readable output
  --fail-on heavy     # exit non-zero to gate CI
tip--remote scans through the API and needs no local Playwright install, so it is the right default in CI and on air-gapped runners.
04

AEO · agent-readable

The AEO axis asks a different question: can AI engines actually fetch, read, and cite this page? A page can look perfectly human-made and still be invisible to ChatGPT, Claude, or Perplexity because it blocks their crawlers or serves JS soup. 8 weighted checks, total weight 100. The four required checks are the fundamentals; the rest are recommended bonuses. Higher is better: AI-Ready (≥80), Partial (≥50), Invisible (<50).

CheckWeightSeverity
Page is reachable (HTML 2xx)10required
AI crawlers are not blocked (GPTBot gets 2xx)25required
robots.txt does not Disallow AI crawlers20required
Page is indexable (no noindex)15required
Markdown twin served at <url>.md10recommended
HTML advertises the markdown twin (Link rel=alternate)8recommended
/llms.txt published at the site root7recommended
HTML sends Vary: Accept (content-negotiation aware)5recommended
eating our own cookingslop-detect serves a markdown twin for every page, publishes an llms.txt, and lets AI crawlers in. Run the axis on this very page: POST /api/aeo with { "url": "https://slop-detect.com/docs" }.
05

The system axis · DESIGN.md

The absolute slop score asks "does this look AI-generated?" The system axis asks the durable question: does the page honor its own declared design system? Point it at a DESIGN.md (Google Labs' open spec: colors, typography, radii) and it reports drift: fonts in use that aren't declared, CTA or surface colors off the palette, radii off the scale. A bespoke site checked against its own system scores Aligned, never "slop". Every drift item is a named, contestable signal.

bash
slop-detect https://your-site.com --design-md auto

  ◳ system   Drifting   62/100   (DESIGN.md)
  drift  Inter is in use but is not declared in the system
  drift  the CTA fill is off the declared palette
  drift  a 16px card radius is off the declared 4 / 8 / 12 scale
06

Web & REST API

One curl away. POST a URL, read back the grade, score, verdict, and definitions version.

bash
# score a page on the design + copy axes
curl -s -X POST https://slop-detect.com/api/scan \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://your-site.com","axes":["design","copy"]}' | jq

endpoints

Public REST endpoints
EndpointWhat it returns
POST /api/scanScore a URL on the design (and optional copy) axis. Add "designMd": true for the system axis, "preset" for a subset.
POST /api/aeoScore whether AI engines can fetch, read, and cite a page. Higher is better.
GET /api/patternsThe live pattern catalogue: id, label, category, weight, and the definitions version.
POST /api/fix-promptAssemble a paste-ready prompt that de-slops a page, scoped to its heaviest tells.
GET /?mode=agentA machine-readable capability document (capabilities, endpoints, auth, discovery) in one fetch.

Auth. No key needed for normal use. GET endpoints are public; POST is per-IP rate-limited (scan 6/min from the web, 3/min server-to-server). Pass X-API-Key or Authorization: Bearer for higher, per-key limits: free 10/min, pro 60/min, unlimited. Foreign browser origins are rejected without a key; the CLI and MCP are not.

07

Continuity & directory

Detection is free and stateless. The optional continuity layer remembers a domain, re-scans it daily, and emails you when it regresses to slop or drifts off its DESIGN.md between redesigns. list: true also opts the domain into the public, crawlable directory with a real backlink.

Continuity and directory endpoints
EndpointWhat it returns
POST /api/watchRegister a daily re-scan with regression + DESIGN.md-drift email alerts (double opt-in).
GET /api/watch/confirmConfirm the emailed opt-in link and switch alerts on.
GET /api/sitesThe public, owner-gated directory dataset of listed domains.
GET /api/statsAggregate scan stats: total scans, median score, share carrying slop.
POST /api/dashboard/linkEmail a single-use magic sign-in link for the multi-domain dashboard.
08

Programmatic · the core engine

@slop-detect/core is the pure, runtime-agnostic engine: it runs in Node, a Cloudflare Worker, or the browser, and knows nothing about fetching a page. You open the page, run each pattern's detect() in-page, then hand the triggered results to the scorer.

javascript
import { scorePatterns, PATTERNS, DEFINITIONS_VERSION } from '@slop-detect/core';

// core is pure: YOU open the page (Playwright/Puppeteer) and run each
// pattern's detect() in-page, then hand the triggered results to the scorer.
const summary = scorePatterns(results);
console.log(summary.score, summary.grade, summary.tier);
console.log(PATTERNS.length, DEFINITIONS_VERSION); // 27 2026.09
09

Presets & agents

Not every audience cares about the same tells. A preset scores a curated subset or weighting without forking the ruleset. Pass --preset on the CLI or { "preset": "strict" } to the API.

PresetScores
fullAll patterns at their default weights. The canonical score.
strictOnly the highest-signal smoking guns (weight ≥ 5). Fewer false positives — good as a hard CI gate.
marketingBrand-surface tells a marketer can act on: fonts, colours, gradients, hero treatment. Skips structural/code-level signals.
minimalThe three most-cited dead-giveaways only: slop fonts, VibeCode purple, gradient text.

MCP · self-audit before shipping

slop-detect-mcp is a Model Context Protocol server that lets an agent scan a page before it ships and pull the fix prompt back into the loop. Four tools: scan_page, check_aeo, check_design_system, fix_prompt.

json
{
  "mcpServers": {
    "slop-detect": { "command": "npx", "args": ["-y", "slop-detect-mcp"] }
  }
}
10

CI gate · GitHub Action

The action scans a deploy-preview URL, posts a sticky PR comment with the grade and triggered patterns, and fails the check when slop creeps above your threshold. fail-under takes a number (fail if the score exceeds it) or a letter grade. Leave it empty for report-only mode.

yaml
- uses: ravidsrk/slop-detect/packages/[email protected]
  with:
    url: ${{ steps.preview.outputs.url }}   # your deploy-preview URL
    fail-under: 'B'                       # fail if the grade drops below B
11

Tiers & grades

The 0-100 score is the source of truth; the tier and letter grade are derived from it. Lower is cleaner. The grade bands are read from the engine, so they cannot disagree with the scorer.

Clean
score 0-9
  • A+0-2
  • A3-5
  • A-6-9

A point of view. The slop fingerprint is absent.

Mild
score 10-27
  • B+10-14
  • B15-19
  • B-20-23
  • C24-27

Good bones, a few template tells creeping in.

Heavy
score 28+
  • D+28-33
  • D34-39
  • F40-100

Wears the AI starter kit head to toe.

Empty is better than fake. Show the product, don't decorate around it.

Scan a page and read its fingerprint in about eight seconds.