Detect an AI-Generated Website in 30 Seconds: 21 Objective Signs (2026 Method)
Twenty-one verifiable signs, each scored 1 to 5, that separate a v0 or Lovable export from genuine custom work. Open DevTools, check the hex, count the cards, read the headers, and get a number between 0 and 75.
On this page
A site lands in the inbox. The freelance invoice cleared five figures. The agency deck said "bespoke design system" four times. The reader has thirty seconds before the meeting starts, and one uncomfortable question: did a human design this, or did v0 spit it out in eleven minutes?
This article is the answer. Twenty-one signs, each verifiable in seconds, scored on a severity scale, with a final calculator that produces a number between 0 and 75. Above 51, the site is what the industry now calls pure slop: generated by v0, Lovable, Bolt, Claude Artifacts, or ChatGPT canvas, then handed off as artisanal work. Below 16, a human designer made it. Between those bounds, a more careful reading is required.
The method is non-accusatory. AI-assisted work is fine. AI-dominant work passed off as human work is not. The point of this checklist is to give the reader (recruiter, agency client, founder, technical buyer) the vocabulary and the evidence to ask the right questions when a deliverable feels off.
TL;DR: The 30-second fast scan
Open the site. Answer five binary questions. Score one point per yes.
| # | Question | Yes / No |
|---|---|---|
| 1 | Does the primary color sit between #3b82f6 (Tailwind blue-500) and #8b5cf6 (Tailwind violet-500)? | □ |
| 2 | Is the body font Inter, with no fallback or variant tuning visible? | □ |
| 3 | Is there a hero with one H1, one paragraph, one filled CTA button, and one ghost CTA button: in that exact order? | □ |
| 4 | Is the pricing section three plans labeled approximately Starter / Pro / Enterprise, each in a rounded-2xl card with green checkmarks? | □ |
| 5 | Is the footer split into four columns titled approximately Product / Company / Resources / Legal? | □ |
Interpretation:
- 0-1: Probably human-led. The fast scan stops here.
- 2-3: AI-assisted or templated. Worth a closer look but not damning.
- 4-5: AI-dominant. Run the full 21-sign audit.
The fast scan catches most of what the full method catches. The rest (the technical fingerprints, the HTTP headers, the sitemap timestamps, the shadcn class soup) covers the edge cases where a careful human happens to use the same defaults as an AI model, or where an AI output has been lightly retouched.
Anyone who reads only this section already has more diagnostic capacity than most clients who hand over checks for so-called custom sites. The next sections explain the why, then walk through the twenty-one signs in detail. If you want the deeper background on why these five questions work, why every AI-generated website looks the same covers the training-distribution mechanics.
Why detecting AI slop is non-trivial
The detection problem in 2026 is not what it was in 2023. Back then, an AI-generated landing page had visible tells in the copy: stilted phrasing, hallucinated features, repeated transitions. Now the copy is mostly clean. Detection has shifted from text to structure.
AI-assisted versus 100 percent slop
A working definition is needed before any judgment.
AI-assisted describes a site where a designer or developer used an AI tool to draft sections, generate boilerplate, or accelerate iteration, and then made deliberate human choices: a non-default palette, a typography pairing, a layout that breaks the canonical grid, copy that sounds like a person wrote it. AI-assisted work is the dominant mode of frontend production in 2026 and is not a problem. The output reflects judgment.
Pure slop describes a site that came out of a generator, was lightly tweaked, and shipped as if a human had designed it from scratch. The output reflects defaults. Every choice (color, font, grid, copy) is the model's first guess. Stacked together, those first guesses produce a recognizable signature.
The distinction matters for two reasons. First, it determines whether a buyer was misled. Second, it determines whether the site has any chance of differentiation in a market where every competitor has access to the same generators.
AI code versus AI design
The detection landscape splits cleanly into two halves.
AI code (generated JavaScript, Python, or backend logic) can be detected with statistical tools that analyze token distributions, control-flow patterns, and stylistic regularities. They work because code has a measurable surface: identifiers, operators, structure. They produce a number. (The visual analog, reading the markup itself for tells, is covered in AI-generated code: 23 signs.)
AI design (the visual output of a generator) does not yield to statistical detection. There is no token distribution. There is a screenshot. The signal lives in human heuristics: the recognition that a particular palette, a particular grid, a particular microcopy choice has appeared on ten thousand other sites in the last quarter. A text classifier applied to a screenshot returns nothing useful. The detector must be a person who knows what to look at.
This is why the method below is built around perceptual signs, not algorithms. The reader becomes the classifier.
Why generic detectors fail on visuals
A reasonable question: why not train a classifier on screenshots of human versus AI sites?
Three reasons. First, the training set drifts: generators change their defaults with every model update. Second, the negative class (human-designed sites) includes everything from brutalist Berlin agency pages to corporate fintech dashboards; the variance swamps the signal. Third, and most important, the diagnostic is contextual. A rounded-2xl card grid is not slop on a Vercel template. It is slop on an invoice that claimed forty hours of bespoke design.
Detection is therefore a structured manual audit. The twenty-one signs are the structure. The thirty-second method is the protocol. The score is the output.
The 21-sign 30-second method
The method has three phases, each with a fixed time budget.
Phase 1: Visual scan (10 seconds): Look at the homepage above the fold. Note the palette, the font, the hero structure, the presence of an emoji-prefixed pill, the gradient direction.
Phase 2: Section walk (15 seconds): Scroll through the page once. Note the three-card grid, the social proof logos, the how-it-works steps, the pricing structure, the testimonial slider, the FAQ accordion, the footer columns.
Phase 3: Technical inspect (5 seconds, optional): Right-click, Inspect Element. Look at one button's class attribute. Look at the computed font-family. Look at the network tab for _next/static or shadcn-style class names.
The full audit takes thirty seconds for a trained eye. The scoring sheet is the twenty-one-sign table at the end.
The signs are not weighted equally. Some, like the canonical three-card grid or the stock purple-to-pink gradient, say a lot. Others, like the use of Lucide icons, are informative but not damning, since Lucide is genuinely popular among human designers. Each sign has a severity score from 1 to 5 and a signal strength. Both are editorial judgments: we have not run a study measuring how often each sign appears in generated versus hand-made sites, and we do not quote figures we cannot back.
What follows is the detailed catalog.
The 21 objective signs
Sign 1: Palette `#3b82f6` plus `#8b5cf6` (Tailwind blue-500 plus violet-500)
Severity: 4/5
One of the most recognizable visual signatures of an AI-generated site is the pairing of Tailwind's blue with its violet or purple: #3b82f6 (blue-500) with #8b5cf6 (violet-500) or #a855f7 (purple-500). They are stock values of the most common CSS framework on generated sites, and the model makers name the habit themselves: Anthropic's frontend prompt tells Claude to avoid "purple gradients on white backgrounds" (Claude Cookbook, 21 October 2025).
The narrative capture is consistent. A primary button rendered in bg-blue-500 with white text. A secondary accent (a badge, an icon background, a gradient stop) rendered in bg-violet-500 or bg-purple-500. A hover state that shifts to bg-blue-600 (#2563eb) and bg-violet-600 (#7c3aed). No saturation tuning, no chroma adjustment, no brand-specific deviation.
A human designer working on a serious project chooses a palette. The choice involves a spec, a moodboard, a check against the brand's existing assets, a verification under different lighting and accessibility conditions. The output is a hex value that almost never matches Tailwind's defaults exactly, because Tailwind's defaults were chosen for general utility, not for the specific brand on the desk. (For why blue-500 specifically became the tell, see the blue-purple gradient AI signature.)
A generator does not choose. It returns the most likely token sequence given the prompt "modern startup landing page." That sequence very often lands on blue plus violet or purple.
Verification method: Open DevTools. Click the primary button. In the Styles panel, look at the background-color property. If it reads rgb(59, 130, 246) (that is #3b82f6), flag the sign. If the secondary accent reads rgb(139, 92, 246) (that is #8b5cf6), flag again.
Signal strength: Strong next to the other color signs, weak on its own: plenty of human-designed sites like blue. Check it first because it takes five seconds.
A counterexample worth noting: some serious B2B brands genuinely use blue-500 because they want to communicate trust and the founder happens to like that exact shade. The check is necessary but not sufficient. It must combine with at least two other signs from the list to support a strong classification.
Sign 2: Default Inter font, no fallback tuning
Severity: 3/5
Inter is the default sans-serif of the modern frontend stack. It ships in Tailwind documentation, in Vercel templates, in shadcn/ui examples, and in every starter that v0 and Lovable produce. Its ubiquity is not a flaw; Inter is a well-engineered typeface designed by Rasmus Andersson with rigorous attention to legibility at small sizes.
The signal is not the use of Inter. The signal is the use of Inter without any companion typography choice: no display face for headlines, no monospace for code or labels, no italic alternate, no font-feature-settings tuning for tabular numerals. The site uses Inter for everything, in two or three weights, with default tracking, and stops there. (Geist, Vercel's house font, is the new variant of this tell: covered in Geist, the new Inter.)
A human designer, even one who chooses Inter, makes companion choices. A serif for body text. A geometric sans for the logotype. A grotesque for the H1. A monospace pair like JetBrains Mono or IBM Plex Mono for technical labels. The pairing communicates thought.
A generator returns Inter. Period.
Verification method: Open DevTools. Inspect any text element. In the Computed panel, look at font-family. If the resolved font is Inter, sans-serif or Inter, system-ui, ... and every text node (H1, body, button, caption) resolves to the same family with no variation, flag the sign.
A more specific check: look at the head of the document for <link> tags loading Google Fonts or next/font/google calls. If the only font requested is Inter, flag.
Signal strength: Moderate. Inter is popular with human designers too (the HTTP Archive's 2025 Web Almanac puts it on roughly 1.4 to 1.5% of all pages, and rising), so the sign is informative but should not stand alone.
Sign 3: Three-card grid with `rounded-2xl` and `shadow-md`
Severity: 5/5
This is the most diagnostic structural sign in the catalog. Almost every AI-generated landing page contains, somewhere between the hero and the footer, a section of exactly three cards arranged horizontally on desktop and stacked vertically on mobile. Each card has identical structure: an icon at the top, a heading, two or three lines of body copy, and optionally a small link. The card uses rounded-2xl for the corner radius, shadow-md for the elevation, and bg-white or bg-gray-50 for the surface.
The reason is structural. Generators are trained on the canonical landing-page anatomy: hero, three benefits, social proof, three steps, testimonials, pricing, FAQ, footer. The three-benefits section is almost never four, almost never two, never seven. It is three. Three is the median across the training corpus, and the median is what the model returns. (The conversion cost of this exact pattern is the subject of why 3 identical cards kill conversion.)
A human designer might use three cards. A human might also use a horizontal scroll, an asymmetric grid, a single hero feature with three sub-points, or a comparison table. The decision reflects content. The generator decision reflects the median.
The corner radius and shadow are equally diagnostic. Tailwind's rounded-2xl sets border-radius: 1rem, neither sharp enough to feel architectural nor soft enough to feel friendly. It is the safe middle. shadow-md is similarly the safe middle of Tailwind's shadow scale: visible but not heavy.
Verification method: Scroll to the section after the hero. Count the cards. If the count is exactly three, inspect any card. Search the class attribute for rounded-2xl and shadow-md (or shadow-lg, the close variant). If both are present and the grid is clearly three-by-one on desktop, flag.
A more granular check: look at the icons inside each card. If they are Lucide icons (cross-reference Sign 20), the diagnostic strengthens.
Signal strength: Strong in combination with Sign 1, moderate alone: the three-card pattern is also common in human-made templates and starter kits.
Sign 4: Hero with H1, paragraph, primary CTA, ghost CTA
Severity: 4/5
The canonical hero structure produced by v0, Lovable, and Bolt is identical to the point of being a fingerprint:
- An
<h1>with a two-line headline, often containing a colored span for emphasis on three or four words. - A
<p>immediately below, two or three sentences long, describing the value proposition in generic startup language. - A primary CTA button: filled, dominant brand color as background, white text, sometimes an arrow icon to the right.
- A secondary CTA button: ghost or outline style, no background fill, the brand color or gray as border, the same color as text, sometimes a play icon for "Watch demo."
The two buttons sit side by side on desktop, stacked on mobile, with consistent gap and equal height. The primary reads "Get started" or "Try it free." The secondary reads "Learn more," "Watch demo," or "Book a call." If you want the inverse (twenty-one hero compositions that escape this fingerprint), see hero section anti-slop.
A human designer has more degrees of freedom. The hero might be split into two columns with media on one side. It might have a single CTA. It might embed a form directly. It might lead with a video. The generator has one shape.
Verification method: Look at the hero region. Count the elements directly under the H1. If the sequence is paragraph, then two buttons in a flex row, with the first solid-filled and the second ghost-styled, flag.
A copy check (cross-reference Sign 13): if the buttons read "Get started" and "Learn more" (exactly those phrases), the diagnostic strengthens.
Signal strength: Moderate and contextual: the structure is genuinely effective, so many human-designed B2B sites use it too.
Sign 5: Tag pill above H1 with sparkle or rocket emoji
Severity: 4/5
A small rounded badge sits directly above the H1. It contains a sparkle emoji (✨), a rocket (🚀), or occasionally a fire (🔥), followed by text like "New: AI-powered insights" or "Now in beta" or "Just launched." The badge has a soft background (bg-purple-100 or bg-blue-50), a colored border or none, and a pill shape from rounded-full plus small horizontal padding.
The pattern originated in startup landing pages around 2021 and was systematized by Vercel, Stripe, and Linear marketing teams. Generators learned it as canonical. The result: nearly every AI-generated SaaS landing page now opens with a sparkle emoji.
The sign is diagnostic for two reasons. First, the emoji is almost always one of the three above (sparkle, rocket, fire) because those are the most frequent in the training distribution. Second, the microcopy follows a tight pattern: "New:" or "Now:" or "Introducing:" followed by a feature name in title case.
A human designer might use a similar badge but would more often write a specific sentence (a customer name, a release version, a date) rather than the generic "New: AI-powered X."
Verification method: Look at the area immediately above the H1. If a small pill-shaped element exists with an emoji and short text, inspect it. Note the emoji glyph. If it is sparkle, rocket, or fire, and the text follows the pattern "Word: phrase," flag.
Signal strength: Moderate. The pill is fairly specific and quick to spot, so it is worth checking early.
Sign 6: Gradient violet to pink, `bg-gradient-to-br from-purple-500 to-pink-500`
Severity: 5/5
The loudest signature in the catalog. A generated site frequently uses a violet-to-pink linear gradient as the dominant accent: as the background of a hero card, the fill of a CTA button, the background of a badge, or a decorative blob behind the headline. The exact Tailwind class is bg-gradient-to-br from-purple-500 to-pink-500, which in Tailwind v3 runs from #a855f7 to #ec4899 toward the bottom-right corner; the violet variant starts at #8b5cf6.
The model makers name it themselves: Anthropic's frontend prompt lists "purple gradients on white backgrounds" among the clichés Claude should avoid, and the HTTP Archive's 2025 Web Almanac calls it "the AI Purple Problem." Variants exist (from-violet-600 to-fuchsia-600, from-indigo-500 to-purple-500), but the family is unmistakable. The colors are bright, saturated, and identical across thousands of generated sites.
A human designer working on a serious brand does not pick this gradient. The reasons are practical: it clashes with most logos, it looks identical to every competitor, and it carries a strong "AI demo" association that signals lack of effort. A human who picks a gradient picks one that fits the brand: muted, custom, or genre-specific. (How to pick an accent color that is not Tailwind blue walks through the process a generator skips.)
Verification method: Look for the brightest gradient on the page. Inspect it. Read the background-image value in the Computed panel. If it contains linear-gradient with stops at or near #a855f7 or #8b5cf6 and #ec4899 (or close variants), flag.
A class-attribute check is faster: search the DOM for gradient-to-br, from-purple-500, to-pink-500, from-violet, to-fuchsia, or to-pink. Any of these in the same element flags the sign.
Signal strength: Strong. The stock stops are rarely what a brand designer would pick, and the model makers list the pattern as a cliché to avoid. One of the strongest single indicators in the catalog.
Sign 7: Three social-proof logos with "Trusted by"
Severity: 2/5
A horizontal strip below the hero contains three to five client or partner logos in grayscale, with a small label above reading "Trusted by leading teams" or "Used by companies like" or simply "Trusted by." The logos are evenly spaced, vertically centered, and rendered at low opacity. On mobile, they wrap into a two-row grid.
The pattern is genuinely effective and predates AI generators by a decade. Stripe popularized it. Every B2B template includes it. The generator learned it as part of the canonical anatomy and inserts it whether or not the product has any clients.
The diagnostic value is lower than other signs because the pattern is so widespread among legitimate human-designed sites. What raises suspicion is the specific phrasing ("Trusted by leading teams" or "Used by industry leaders") combined with placeholder logos that may not correspond to actual customers. On a generated site, the logos are often Vercel sample SVGs or stock placeholder marks that the buyer is expected to replace.
Verification method: Look for the "Trusted by" strip. Note the count of logos and the phrasing of the label. If the label is exactly "Trusted by" or "Trusted by leading teams" with no specific customer name, and the logos look generic or unfamiliar, flag.
Signal strength: Weak: a logo strip is a legitimate convention. Supportive, not decisive.
Sign 8: How it works, three steps with Lucide icons
Severity: 3/5
A section titled "How it works" or "Get started in three steps" contains exactly three numbered steps. Each has a Lucide icon (cross-reference Sign 20), a short heading, and one or two lines of body copy. The numbering is visible: a circled "1," "2," "3" or large numerals to the left of each step.
Three is canonical. Two feels insufficient. Four feels like work. Generators consistently produce three.
The Lucide icons are typically generic: a sparkle for "Sign up," a wrench or settings gear for "Configure," a rocket or check for "Launch." The choice follows the most-likely token in the training distribution.
Verification method: Scroll to the section after the benefits cards. If a "How it works" block exists with exactly three numbered steps and each contains an SVG icon, inspect one icon. If the SVG markup contains lucide- in the class attribute or matches Lucide's open-source markup pattern, flag.
Signal strength: Moderate.
Sign 9: Three pricing plans, Starter / Pro / Enterprise, `rounded-2xl`, green checks
Severity: 5/5
Pricing is the strongest section-level diagnostic in the catalog. A generated SaaS site has exactly three plans. The names are some permutation of: Starter, Basic, Free, Pro, Plus, Business, Enterprise, Custom. The middle plan is highlighted with a colored border, a "Most popular" badge, or a slight scale-up. Each card uses rounded-2xl and shadow-md. Below the price, a feature list uses green checkmark icons (typically Lucide's Check or CheckCircle) to the left of each line.
The structure is so canonical that it has become impossible to use it sincerely without looking generated. Even Stripe's official pricing page has moved away from it to differentiate. Yet generators continue to produce it because the training distribution heavily weights this exact layout. (Fifteen pricing-page layouts that escape it is the antidote.)
The diagnostic strength comes from the simultaneous presence of multiple sub-signs: three plans, the Starter/Pro/Enterprise naming, the rounded card shape, the green checks, the highlighted middle plan, and the standard "Get started" CTA on each. When all six are present, the probability of human design from scratch is below 8 percent.
Verification method: Scroll to the pricing section. Count the plans. Note the names. Inspect a card. If rounded-2xl is in the class attribute, if the feature list uses green checkmarks, if the middle plan has a "Most popular" or "Recommended" badge, and if the plan names match the canonical set, flag.
Signal strength: Strong: the exact three-tier layout with a raised middle card and green checks is one of the most stereotyped sections of a generated page.
Sign 10: Testimonial slider with round photos
Severity: 3/5
A section above the footer contains testimonials. Each has a quote, a name, a job title, a company, and a circular profile photo. The section is either a horizontal slider with arrow controls or a static three-column grid. The photos are headshots, sometimes real, sometimes stock, sometimes AI-generated faces.
The diagnostic specifics: the quotes are short (one to three sentences), end with a period, and rarely contain specific numbers or product details. The names are anglophone (a Sarah, a David, an Emma, a James). The job titles are generic ("CEO," "Head of Product," "Founder"). The companies, when present, are often invented.
A human-designed testimonial section more often has long quotes, specific use cases with numbers, real photos, and verifiable companies with linkable case studies.
Verification method: Scroll to the testimonial section. Read three quotes. If they are short, generic, and free of specific numbers, and if the photos are circular and possibly stock or AI-generated, flag.
A reverse image search on one photo can confirm AI generation; tools like FaceCheck or Google Lens can identify stock or generated faces.
Signal strength: Moderate to weak.
Sign 11: Plain accordion FAQ with chevron icon
Severity: 2/5
The FAQ uses a vanilla accordion: each question is a clickable row with a chevron icon on the right that rotates 90 or 180 degrees on expand. The container has rounded-lg borders, gray dividers between rows, and no visual hierarchy beyond bold question text. The number of questions is six to eight.
The component is the default shadcn <Accordion> with the default <AccordionTrigger>, <AccordionContent>, and Radix UI primitives underneath. The chevron is Lucide's ChevronDown.
The pattern is so common among template sites that the detection value is moderate. Many human-designed sites also use shadcn here, because the component is well-engineered and accessible. The signal is weakened accordingly.
Verification method: Scroll to the FAQ. Click a question. If the open behavior is a smooth rotate-and-expand with no other animation, and the markup uses Radix primitives (visible in DevTools as data-radix-accordion-trigger or data-state="open"), flag.
Signal strength: Weak: the accordion FAQ is a standard pattern. Informative only next to other signs.
Sign 12: Footer with four columns, Product / Company / Resources / Legal
Severity: 4/5
The footer is a structural fingerprint. A generated site has four columns, titled (in this order or close to it) Product, Company, Resources, Legal. Each contains three to six links. Below the columns, a horizontal row holds the logo, the copyright notice, and small social icons (X, GitHub, LinkedIn, Discord).
The diagnostic specifics: the columns are evenly spaced, the link text is short ("Pricing," "Blog," "About," "Privacy"), the logo matches the header, the copyright reads "© 2026 [Company]. All rights reserved."
A human designer might use a footer with two columns, a single horizontal row, a large brand statement, an embedded newsletter form, or no footer columns at all. The four-column layout is a generator default.
Verification method: Scroll to the footer. Count the columns. Note the titles. If the count is four and the titles match the canonical set (any subset of Product, Company, Resources, Legal, Solutions, Support, Developers), flag.
Signal strength: Moderate.
Sign 13: Microcopy "Get started," "Learn more," "Watch demo," "Try it free"
Severity: 4/5
The microcopy across all CTAs follows a tight pattern. The primary CTA reads "Get started," "Try it free," or "Start now." The secondary reads "Learn more," "Watch demo," or "Book a call." Section headings use "Everything you need to," "Built for," "Designed for," "The all-in-one platform for." Body copy uses "powered by AI," "in just a few clicks," "without writing a single line of code."
The vocabulary is so consistent across generators that it is a sign in its own right. Three or more canonical phrases on a single page is strong evidence of generated copy. Banned phrases: 40 words that mark copy as AI extends this list into prose.
A human copywriter has more verbal range. A human writes specific, branded, sometimes weird CTAs: "Plant your flag," "See it for yourself," "Take the tour." Specificity is the antidote to generation.
Verification method: Read the page. Count the canonical phrases: "Get started," "Learn more," "Watch demo," "Try it free," "Powered by AI," "in just a few clicks." If three or more appear, flag.
Signal strength: Moderate: three or more canonical phrases together say more than one.
Sign 14: Auto-generated OG image, often violet gradient with site name
Severity: 3/5
The Open Graph image is the preview that appears when the URL is shared on social platforms. A human-designed site has a custom OG image: a designed visual, a screenshot, a brand asset. A generator either omits it or auto-generates one.
The auto-generated OG image has a recognizable look: a violet or blue gradient background, the site name in large white sans-serif, sometimes a subtitle. The dimensions are 1200 by 630, the canonical Open Graph size. The image is typically served from /api/og or /_next/image?url=... if the site uses Next.js's @vercel/og library.
Verification method: View the page source. Look for <meta property="og:image". Open the URL in a new tab. If the image is a violet gradient with the site name in white text and no other content, flag.
A faster check: paste the page URL into Twitter, LinkedIn, or Slack. The preview that renders is the OG image. If it is the generic gradient-and-name pattern, flag.
Signal strength: Moderate.
Sign 15: No custom 404 page, Next.js or Vercel default
Severity: 3/5
Navigate to a URL that does not exist. Append /asdf-does-not-exist to the domain and load it. A human-designed site has a custom 404: a designed message, a search bar, a sitemap, a way to recover. A generator output usually has no custom 404. The page that loads is one of:
- The Next.js default 404: black background, "404 | This page could not be found." in small white text.
- The Vercel default 404: also minimal, with a Vercel logo.
- A bare 404 with the site's footer but no content.
The absence is not damning on its own: many small human-designed sites also skip it. But combined with other signs, it indicates a build that did not bother with edge cases, which is characteristic of generator output.
Verification method: In the address bar, append /random-string-12345 to the homepage URL. Press Enter. If the page is the Next.js default ("This page could not be found.") or the Vercel default, flag.
Signal strength: Weak: many hand-built sites never customize their 404 either.
Sign 16: No custom favicon, Vercel globe or emoji
Severity: 2/5
The favicon is the small icon in the browser tab. A human-designed site has a custom favicon: a logo mark, a brand glyph, sometimes an SVG that adapts to dark mode. A generator output has one of:
- The Vercel default favicon: a small dark globe.
- A Next.js default: a black square.
- A single emoji rendered as a favicon (an actual default behavior of some Next.js starters).
- No favicon at all, leading to a generic globe in most browsers.
The diagnostic value is low because favicons are easy to add and many human-designed sites also skip them. But combined with other signs, the absence is informative.
Verification method: Look at the browser tab. If the icon is a globe, a black square, or a single emoji glyph, flag.
Signal strength: Weak.
Sign 17: Fade-in-up animations everywhere, nothing else
Severity: 3/5
A generated site uses one animation primitive: fade-in-up. Every section enters the viewport with a 30-pixel translate-up combined with an opacity transition from 0 to 1 over 300 to 600 milliseconds. It is applied to the hero, the cards, the testimonials, the pricing, the FAQ: every section, identically. The library is typically Framer Motion; the trigger is whileInView with viewport={{ once: true }}. (Motion slop: the fade-in-up scroll animation dissects this one tell in full.)
A human designer who values motion uses different animations for different content. A staggered list. A horizontal slide. A parallax effect. A hover microinteraction. The variation reflects intent.
A generator returns one animation because variation is not a default. The result is a page that scrolls smoothly but mechanically: every section announces itself with the same gesture.
Verification method: Scroll through the page slowly. Watch each section as it enters. If every section uses the identical fade-and-translate-up entrance, with no other animation type visible, flag.
A code check: search the DOM or the bundled JavaScript for animate-fade-in-up, motion.div, whileInView, or Framer Motion patterns. One motion primitive applied uniformly is the signal.
Signal strength: Moderate.
Sign 18: shadcn/ui component naming in the DOM
Severity: 4/5
The single most reliable technical fingerprint of an AI-generated site in 2026 is unmodified shadcn/ui in the DOM. Open DevTools, look at any button. If the class attribute starts with inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all ... (current shadcn/ui, per its source) or, on older projects, inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors ..., that is the shadcn <Button> variant string, left as installed.
Then look at the data attributes. Current shadcn/ui components render a data-slot attribute naming the component (data-slot="card", data-slot="button"), and data-radix-* prefixes mean Radix UI primitives, the foundation shadcn is built on. The class soup on dialogs, dropdowns, and toasts confirms it.
shadcn is not exclusive to AI generators: many human developers use it because it is genuinely well-engineered. The signal is not shadcn; it is shadcn with no customization. A human who adopts shadcn tunes it. A generator returns it raw. The difference shows up in the source components/ui/button.tsx:
// Generator output: untouched CLI defaults
const buttonVariants = cva(
"inline-flex items-center justify-center ... bg-primary text-primary-foreground",
{ variants: { variant: { default: "...", ghost: "..." } } }
)
// Human-led: tokens and radii overridden, brand variants added
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-none font-display tracking-tight",
{ variants: { variant: { ink: "bg-ink text-paper hover:bg-ink/90", wire: "..." } } }
)The first is the default rounded-md, bg-primary, two stock variants. The second has bespoke radii, a display font, and brand-named variants: the fingerprint of a human who opened the file. (De-AI your Lovable/v0/Bolt site is the refactor that turns the first into the second.)
Verification method: Open DevTools. Inspect a button. If the class attribute contains the canonical shadcn variant string (the long utility-class run starting with inline-flex), flag. Also check for data-slot and data-radix-* attributes.
Signal strength: Strong but contextual: shadcn/ui is genuinely popular with human developers, so the tell is shadcn left exactly as installed.
Sign 19: `text-gray-500` and Tailwind defaults instead of named brand variables
Severity: 3/5
A human-built design system uses semantic, named CSS variables: --color-text-secondary, --color-surface-elevated, --color-accent-primary. The Tailwind config maps these to brand-specific values, and components reference the semantic name. The brand can rebrand later by changing one variable.
A generated site uses raw Tailwind defaults: text-gray-500, bg-white, border-gray-200, text-blue-600. There is no semantic layer. The classes refer directly to the Tailwind palette. If a rebrand is needed later, every file must be touched.
Verification method: Inspect any text element. If the text color is a raw Tailwind class like text-gray-500, text-gray-600, text-zinc-700, or text-slate-500 (and not a semantic class like text-secondary, text-muted, or text-content), flag.
A more thorough check: open the site's CSS in DevTools' Sources panel. Search for --color-, --brand-, or --surface-. If the file contains no semantic custom properties beyond what shadcn ships with, flag.
Signal strength: Moderate.
Sign 20: Lucide icons in nav and CTAs
Severity: 2/5
Lucide is the default icon library of the modern frontend stack. It ships with shadcn/ui, integrates trivially with Next.js, and its open-source license makes it the path of least resistance for any developer or generator producing an icon-heavy site.
The diagnostic specifics: every icon on the page is Lucide. The arrow next to a CTA is ArrowRight. The hamburger menu is Menu. The check in the pricing list is Check or CheckCircle. The chevron in the FAQ is ChevronDown. There is no custom icon set, no Phosphor, no Heroicons mixed in, no SVG illustrations specific to the brand.
Lucide use is not a strong signal in isolation. Many human-designed sites use it. The signal is the absence of any other icon source.
Verification method: Inspect a few icons. Look at the SVG markup. If every icon has the same authoring style (typically a 24x24 viewBox, stroke-based, class="lucide lucide-arrow-right"), flag.
Signal strength: Weak in isolation: Lucide is the default icon set of the React ecosystem, and shadcn/ui's own components import it.
Sign 21: Identical sitemap.xml `lastmod` dates across all pages
Severity: 3/5
A site with real activity has a sitemap where different pages have different lastmod dates: the blog index updated yesterday, the pricing page last month, the about page six months ago. The variance reflects actual editing.
A generated site has a sitemap where every page shares the same lastmod: the build date of the deployment. Every entry reads 2026-04-15T14:23:11.000Z or similar, identical to the second across homepage, pricing, blog, contact, and legal pages. This is the default behavior of Next.js's app/sitemap.ts when the build generates the sitemap at deploy time without per-page metadata.
The signal is not the use of build-time sitemaps. It is the absence of human curation: no manual lastmod overrides, no per-page edit timestamps, no exclusion of static legal pages from the rebuild.
Verification method: Append /sitemap.xml to the domain. Open it. Look at the <lastmod> values. If every page shares the same timestamp, flag.
A stronger check: compare the sitemap timestamp to the most recent blog post date or commit date. If the sitemap reads "today" but the most recent post is from 2025, the sitemap is auto-generated and the site has no real editorial activity.
Signal strength: Moderate.
Advanced technical indicators (DevTools required)
Beyond the twenty-one perceptual signs, a deeper inspection reveals technical fingerprints that are nearly impossible to fake without rebuilding the site. Each check takes under thirty seconds and produces a near-deterministic verdict. For a full walk-through of reading a site's CSS for tells, see audit any site for AI tells.
Bundle composition
// In DevTools console:
performance.getEntriesByType('resource')
.filter(r => r.name.includes('_next/static') || r.name.includes('.js'))
.map(r => r.name);A generated Next.js site loads a recognizable bundle:
next/font/googlechunks for Inter (sometimes split intoInter_Fallback.cssandInter.css).- Tailwind's compiled CSS in a single file at
_next/static/css/. - Radix UI primitives as separate chunks:
@radix-ui_react-dialog.js,@radix-ui_react-accordion.js,@radix-ui_react-dropdown-menu.js. - A
cn()utility from shadcn: typicallyclsxplustailwind-mergein the bundle.
The combination (Next.js, Tailwind, Inter via next/font, Radix primitives, shadcn cn()) is the modal stack of generators.
Component attributes
Current shadcn/ui components, which v0 uses by default, render a data-slot attribute on each component (shadcn/ui source). Counting them shows how much of the page is stock components:
// In DevTools console:
[...document.querySelectorAll('[data-slot]')].map(el => el.dataset.slot);A long list of card, button, badge and card-header means shadcn/ui components are in use. It does not prove a generator: plenty of developers use shadcn/ui by hand. It tells you where to look for untouched defaults.
HTTP headers signature
The deployment platform leaves headers diagnostic of the hosting choice, which correlates with the generator used.
| Header | Signature | What it tells you |
|---|---|---|
server: Vercel | Present | Hosted on Vercel, where v0 publishes |
x-vercel-id | Present | Vercel deployment (Vercel docs) |
x-vercel-cache | HIT/MISS/STALE/PRERENDER | Vercel's CDN cache status |
x-nf-request-id | Present | Netlify, one of Bolt's publishing targets |
cf-ray | Present | Served through Cloudflare |
Hosting narrows the candidates; it proves nothing on its own. A site on Vercel with the stock shadcn-and-Inter stack is consistent with v0, and equally consistent with a developer who chose the same stack by hand. Platform subdomains are more telling: *.lovable.app, *.bolt.host and *.replit.app are the default addresses of Lovable, Bolt Cloud and Replit.
# Command-line check:
curl -I https://example.com 2>&1 | grep -i "x-vercel\|server\|x-nf\|cf-ray"Sitemap timestamps
curl https://example.com/sitemap.xml | grep "<lastmod>"If every line has the same date and time, the sitemap is auto-generated at build time with no per-page tuning: a strong correlate of generator output.
Canonical link patterns
<link rel="canonical" href="https://example.com/" />A generated site often has the canonical URL matching the page URL exactly with no parameters. When canonical tags are present on every page and the site has no actual content variation, the SEO setup is the Next.js default.
The AI score calculator
The full audit produces a number between 0 and 75. Each sign is scored: present (severity points), absent (zero). The total maps to an interpretation band.
| # | Sign | Severity | Present? (Y=Sev, N=0) | Score |
|---|---|---|---|---|
| 1 | Tailwind blue-500 plus violet-500 palette | 4 | □ | __ |
| 2 | Default Inter font, no fallback | 3 | □ | __ |
| 3 | Three-card grid with rounded-2xl + shadow-md | 5 | □ | __ |
| 4 | Hero: H1 + p + 2 CTAs (filled + ghost) | 4 | □ | __ |
| 5 | Pill above H1 with sparkle/rocket emoji | 4 | □ | __ |
| 6 | Gradient violet-to-pink (purple-500 to pink-500) | 5 | □ | __ |
| 7 | Three social-proof logos with "Trusted by" | 2 | □ | __ |
| 8 | "How it works" three steps with Lucide icons | 3 | □ | __ |
| 9 | Three pricing plans (Starter/Pro/Enterprise), green checks | 5 | □ | __ |
| 10 | Testimonial slider with round photos | 3 | □ | __ |
| 11 | Plain accordion FAQ with chevron | 2 | □ | __ |
| 12 | Footer four columns (Product/Company/Resources/Legal) | 4 | □ | __ |
| 13 | Microcopy "Get started"/"Learn more"/"Watch demo" | 4 | □ | __ |
| 14 | Auto-generated OG image (gradient + site name) | 3 | □ | __ |
| 15 | No custom 404 page (Next.js or Vercel default) | 3 | □ | __ |
| 16 | No custom favicon (globe or emoji) | 2 | □ | __ |
| 17 | fade-in-up animations everywhere | 3 | □ | __ |
| 18 | shadcn/ui component naming in DOM | 4 | □ | __ |
| 19 | text-gray-500 / Tailwind defaults instead of named vars | 3 | □ | __ |
| 20 | Lucide icons in nav and CTAs | 2 | □ | __ |
| 21 | Identical sitemap.xml lastmod dates | 3 | □ | __ |
| TOTAL (out of 75) | __ |
Interpretation bands
| Score range | Verdict | Description |
|---|---|---|
| 0-15 | Human-designed | The site reflects deliberate choices. AI may have assisted in implementation, but the design vocabulary is human. |
| 16-30 | AI-assisted | Significant AI involvement with human direction. Acceptable for most contexts. The buyer should understand what they paid for. |
| 31-50 | AI-dominant | AI generated the foundation; minor human edits exist. Acceptable for internal tools, MVPs, and side projects. Misleading for premium freelance or agency deliverables. |
| 51-75 | Pure slop | Direct generator output with negligible human modification. The site has no differentiation from thousands of identical outputs. Buyer was misled if they paid for custom work. |
The bands are editorial thresholds, not statistically calibrated cut-offs: we have no study measuring their accuracy. Treat a score as a reason to ask questions and to look for more evidence, not as proof.
Five worked examples
The following five examples show how the calculator behaves on typical kinds of site. They are composites, built to illustrate the method, not audits of real sites or real clients; names, prices and details are invented.
Case A: "FlowSync". B2B SaaS for project management
A polished startup landing page, sold by a freelance designer as a "custom design system and bespoke implementation."
Audit results:
| # | Sign | Present | Points |
|---|---|---|---|
| 1 | Blue-500 + violet-500 | Yes | 4 |
| 3 | Three-card rounded-2xl grid | Yes | 5 |
| 4 | Canonical hero structure | Yes | 4 |
| 6 | Violet-to-pink gradient | Yes | 5 |
| 9 | Three pricing plans canonical | Yes | 5 |
| 12 | Four-column footer | Yes | 4 |
| 13 | Canonical microcopy | Yes | 4 |
| 18 | shadcn/ui in DOM | Yes | 4 |
| 19 | text-gray-500 throughout | Yes | 3 |
| 20 | Lucide icons exclusively | Yes | 2 |
| Other signs | (12 signs at zero) | No | 0 |
Total: 40/75, AI-dominant.
This is the profile of a v0 generation with cosmetic changes (a logo, two photos) shipped as custom work. A developer looking at the DOM would spot the shadcn class soup within a minute.
Case B: "Northcurrent". Boutique financial advisory
A small firm's brand site, built by a one-person agency and sold as "complete custom design including motion graphics."
Audit results:
| # | Sign | Present | Points |
|---|---|---|---|
| 2 | Inter exclusively | Yes | 3 |
| 17 | One animation primitive | Yes | 3 |
| 18 | shadcn/ui visible | Yes | 4 |
| 20 | Lucide icons | Yes | 2 |
| Other signs | (17 signs at zero) | No | 0 |
Total: 12/75, Human-designed.
Here the site uses Inter and shadcn, but the palette is custom (deep navy #0f1f3d and warm cream #f4ede1, not Tailwind defaults), the headlines use a chosen serif, the animation is not the default, and the layout breaks the canonical anatomy with a vertical hero. AI may have scaffolded it; the design on top is real.
Case C: "Helix Health". Healthtech MVP
A two-person startup's landing page, built in a weekend with Lovable and openly described as such.
Audit results:
| # | Sign | Present | Points |
|---|---|---|---|
| 1 | Blue-500 + violet-500 | Yes | 4 |
| 2 | Inter only | Yes | 3 |
| 3 | Three-card grid | Yes | 5 |
| 4 | Canonical hero | Yes | 4 |
| 5 | Sparkle pill | Yes | 4 |
| 6 | Violet-to-pink gradient | Yes | 5 |
| 7 | Trusted by logos | Yes | 2 |
| 8 | Three steps Lucide | Yes | 3 |
| 9 | Three pricing plans | Yes | 5 |
| 12 | Four-column footer | Yes | 4 |
| 13 | Canonical microcopy | Yes | 4 |
| 14 | Auto-OG image | Yes | 3 |
| 15 | Default 404 | Yes | 3 |
| 16 | No favicon | Yes | 2 |
| 17 | fade-in-up everywhere | Yes | 3 |
| 18 | shadcn raw | Yes | 4 |
| 19 | Tailwind defaults | Yes | 3 |
| 20 | Lucide everywhere | Yes | 2 |
| 21 | Identical sitemap dates | Yes | 3 |
Total: 66/75, Pure slop.
This is what a page left entirely on generator defaults looks like in the calculator. Nothing was misrepresented: the founders said what they used. The same score on a freelance deliverable sold as custom would be a serious problem.
Case D: "Atrium Studio". Boutique design agency portfolio
An established studio's portfolio site, selling premium engagements.
Audit results:
| # | Sign | Present | Points |
|---|---|---|---|
| 18 | shadcn visible (but heavily customized) | Partial | 0 |
| Other signs | (20 signs at zero) | No | 0 |
Total: 0/75, Human-designed.
The portfolio uses a chosen typographic pairing, a hand-built CSS grid (no Tailwind), bespoke SVG illustrations, an asymmetric layout, and long-form case studies. One shadcn component (a contact dialog) does not register because it has been customized throughout: colors, radii, motion, copy. The claim of bespoke work holds up.
Case E: "Quantum Brew". Coffee roaster e-commerce
A coffee roaster's shop, built by a freelance Shopify expert as a templated build with brand customization.
Audit results:
| # | Sign | Present | Points |
|---|---|---|---|
| 4 | Hero structure canonical | Yes | 4 |
| 7 | "As featured in" logos | Yes | 2 |
| 11 | Plain FAQ | Yes | 2 |
| 12 | Four-column footer | Yes | 4 |
| 13 | Some canonical microcopy | Yes | 4 |
| 16 | Generic favicon | Yes | 2 |
| 20 | Some Lucide icons | Yes | 2 |
| Other signs | (14 signs at zero) | No | 0 |
Total: 20/75, AI-assisted.
The site is templated (a Shopify theme), not generated, and the score shows how much templates and generators share on the surface. With the template disclosed and customization paid for, the score is consistent with the deliverable.
Generator-specific signatures
Each major AI generator leaves a distinct fingerprint. The following table refines the diagnostic from "AI-generated" to "AI-generated by tool X."
| Generator | Documented starting point | What to look for |
|---|---|---|
| v0 (Vercel) | A Next.js app with shadcn/ui and Tailwind CSS (v0 docs); publishes to Vercel | /_next/static/ paths, server: Vercel and x-vercel-id headers, shadcn data-slot attributes |
| Lovable | React and Tailwind; TanStack Start for apps created since 13 May 2026, React and Vite before (Lovable FAQ) | A *.lovable.app address; the "Edit with Lovable" badge on free-plan sites |
| Bolt.new | Any JavaScript framework, Node.js backend (Bolt help center) | A *.bolt.host address; the "Made in Bolt" badge on free-plan sites |
| Replit Agent | Depends on the project (Replit docs) | A *.replit.app address; the "Made with Replit" badge on free-plan apps |
Branding and default domains are the only signs that name the tool, and they disappear on paid plans or custom domains. Everything else in this catalog shows defaults, not a specific generator. Identifying the framework narrows the candidates: v0 always starts from Next.js, while Bolt and Replit can produce almost anything. For tool-by-tool depth, the honest reviews of v0, Lovable, and Bolt score each on exactly these tells.
# Detect framework from response headers and HTML:
curl -sI https://example.com | grep -i "x-powered-by\|server"
curl -s https://example.com | grep -E '(_next/|@vite/|astro-)'Flowchart: "Should the reader worry about the score?"
flowchart TD
A[Audit complete: score X/75] --> B{X ≤ 15?}
B -->|Yes| C[Human-designed.<br/>No concern.]
B -->|No| D{X ≤ 30?}
D -->|Yes| E{Was custom design<br/>explicitly promised?}
E -->|No| F[AI-assisted is fine.<br/>No concern.]
E -->|Yes| G[Ask freelance about process.<br/>Likely acceptable but verify.]
D -->|No| H{X ≤ 50?}
H -->|Yes| I{Internal tool, MVP,<br/>or side project?}
I -->|Yes| J[AI-dominant is fine<br/>for this context.]
I -->|No| K[Material concern.<br/>Renegotiate or document.]
H -->|No| L{Was the work<br/>premium-priced?}
L -->|No| M[Pure slop but<br/>buyer aware. OK.]
L -->|Yes| N[Pure slop sold as custom.<br/>Refund or rework.]The flowchart resolves whether a score should produce action. The score alone is insufficient; the context (what was promised, what was paid, what the use case is) determines whether action is warranted.
When generator output is acceptable
The method should not be wielded as a weapon against legitimate uses of AI tools. There are contexts where generator output is the right choice and a high score is irrelevant.
Internal tools. A two-person startup needs an internal dashboard to triage support tickets. Lovable produces a working interface in two hours. The interface is generic, the palette is the default, the score is 60. None of this matters. The tool is internal, the audience is three people, the cost saved is two weeks of frontend work. AI-dominant is the right choice.
MVPs and prototypes. A founder needs a landing page to capture interest before committing to a full build. v0 generates it. The page is generic, the score is 55. None of this matters. The page exists to validate demand. If it succeeds, the next version will be custom.
Side projects and personal sites. A developer builds a weekend portfolio with Bolt. The score is 48. None of this matters. The audience is employers who care about the developer's actual work, not the design frame.
Hackathon submissions. A team has 48 hours to build a project. They use Claude Artifacts to scaffold. The frontend scores 70. The judges evaluate the idea and the implementation, not visual differentiation.
The pattern is consistent: when the audience is small, the cost of bespoke design exceeds the marginal value, and the buyer is the same person as the producer, generator output is correct.
When it is not acceptable
The method becomes load-bearing in three contexts.
Public freelance work claiming custom design. A freelance designer charges $15,000 for a "complete custom design system" and delivers a v0 output with a logo swapped. The buyer paid for differentiation and received a generic deliverable shared with thousands of competitors. The score is 60. The misrepresentation is material.
Premium agency deliverables. A client contracts an agency for $40,000 over three months for a "bespoke brand site." The agency uses Lovable internally, ships in three weeks, and bills the full retainer. The score is 55. The agency has captured value that does not match the work. The contract is breached.
Corporate sites at scale. A Fortune 500 company commissions a $200,000 marketing site rebuild. The vendor delivers a site that scores 50. The company will be on the same visual frame as every other corporation that bought the same vendor. The differentiation premium has not been delivered.
In all three, the audit is not about whether AI was used. It is about whether the buyer knew. If the contract specified custom design and the deliverable scores in the AI-dominant or pure-slop band, the contract is not being honored.
How to confront a freelance or agency
The audit produces a number. The number does not produce an action. What follows is a practical guide for the conversation after a high score.
Tone
The conversation is not accusatory. The reader does not know, with certainty, that AI was used. The audit produces a probability. The conversation is about evidence and process.
The wrong opening: "You used AI to generate this. I want a refund." This is brittle: the freelance can plausibly deny, the buyer cannot prove, the relationship deteriorates.
The right opening: "I would like to understand the process behind this deliverable. Can you walk me through how the design system was developed?" This is non-confrontational and produces information. A freelance who built the site genuinely can describe iteration, reference choices, alternatives considered. A freelance who shipped a generator output cannot.
Specific questions
These produce diagnostic information:
- "Can you share the moodboard and inspiration references that informed the palette?"
- "What alternative typography pairings did you consider before landing on Inter?"
- "How was the spacing system developed? Baseline grid or modular scale?"
- "Can you show the design files in Figma or whatever tool was used?"
- "Were there any A/B variants of the hero section explored?"
- "How was the pricing card layout chosen over alternatives like a comparison table?"
- "Can you walk me through the source repository and explain the components you built?"
A genuine designer answers in detail and with specific reasoning. A generator user struggles at the third question or later. The asymmetry is informative.
Contractual clauses
For future engagements, the following additions reduce the risk of slop delivered as custom work:
AI disclosure clause: "Vendor agrees to disclose any AI-generated outputs used in the deliverable, including but not limited to outputs from v0, Lovable, Bolt, Cursor, Replit, Claude, and similar tools. AI-generated outputs may be used as part of the development process but must be substantially modified before delivery."
Originality clause: "Vendor warrants that the design system, including but not limited to color palette, typography, layout grid, and component styles, is original work developed for the project and not direct output from any third-party tool or template."
Process documentation clause: "Vendor agrees to deliver, alongside the final code, a process document including design exploration files (Figma, Sketch, or equivalent), a list of design decisions and their rationale, and a record of iteration on at least three major sections of the site."
Audit right clause: "Buyer reserves the right to commission an independent audit of the deliverable to verify the level of customization. If the audit reveals that the deliverable is substantially direct generator output, Vendor agrees to either rework the deliverable to meet originality standards or refund a proportional share of the engagement fee."
These clauses are not adversarial. They formalize what most buyers assume is implicit. Their presence changes incentives on the vendor side: there is no upside to passing off a generator output, since the audit clause exposes it.
Complementary tools
The 21-sign method is one input. A complete diagnostic combines it with adjacent tools, each addressing a different surface.
Sailop: A free web scan that checks a live page's markup and stylesheets for eight common signatures (blue-family utilities, the blue-to-purple gradient, Inter or Geist as the page font, a three-equal-column grid, fade-up motion, frosted glass, stock button copy, soft-shadow cards) and returns a fix kit. It covers fewer signs than this manual method and none of the context; it is quick and repeatable. A command-line version for repositories is not published yet. (Where each AI tool's defaults come from compares the tools.)
GPTZero: A statistical text classifier. Useful for the copy on a page (blog posts, marketing pages) but blind to visual generation. A site can score zero on GPTZero and 70 on the visual audit. The two answer different questions.
Wappalyzer: A browser extension that identifies the stack: framework, hosting, analytics, fonts, libraries. It does not detect AI generation directly, but it surfaces the canonical stack (Next.js + Tailwind + Vercel + shadcn) that strongly correlates with generator output. A useful pre-filter.
Lighthouse: Google's performance and SEO auditor. Useful for technical health but not for slop. A generated site can score 100 on Lighthouse (Vercel and Next.js are well-optimized by default) and still be pure slop. Performance does not equal differentiation.
Manual DevTools inspection: The deepest signal. A trained eye in DevTools for sixty seconds extracts more than any automated tool. The 21-sign method is the structured guide for that inspection.
The recommended workflow for a serious audit:
- Run the 21-sign manual scan first (30 seconds).
- If the score is in the gray zone (16-50), run the free web scan for a second, mechanical read.
- Use Wappalyzer to confirm the stack (~5 seconds).
- If text-on-page slop is suspected, run GPTZero on the longest blocks of copy.
- Lighthouse only as a sanity check on technical health, not as a slop signal.
Method limits
The 21-sign method produces probabilities, not certainties. The reader must understand the failure modes.
False positives: Human work that looks generated
A skilled developer who uses the canonical stack (Next.js, Tailwind, Inter, shadcn, Lucide) and works from a popular template can produce a site that scores in the AI-assisted or even AI-dominant band. The defaults of the modern frontend stack align with generator outputs because both draw from the same corpus.
A specific failure mode: a junior developer who builds genuinely from scratch but starts from a starter kit that includes Inter, shadcn, and the canonical hero. The work scores high not because AI was used but because the starting point was generator-aligned.
The mitigation is to weight the contextual signs. A high score on a high-priced custom freelance contract is concerning. A high score on a junior developer's hobby project is not.
False negatives: Generator output that looks custom
A sophisticated user can take a v0 output and customize it deeply: swap the palette, add a custom font, restructure the layout, write specific copy. The result scores low because the surface signals have been replaced. The underlying scaffolding is still AI-generated, but the audit cannot detect it.
The mitigation is that, at the level of customization required to defeat the audit, the user has effectively done the work the buyer paid for. The line between AI-assisted and human-led is genuinely fuzzy at this point. The audit captures cases where the customization layer is missing: the majority of cases.
Drift over time
Generator defaults change with every model and platform update. Specific signs (the violet-to-pink gradient, the sparkle pill) may evolve as generators are tuned to be less obviously canonical; Lovable, for one, now asks about palette, typography and layout before it builds. The method must be updated regularly.
The framework (palette, typography, structural anatomy, microcopy, technical signature) is durable. The specific instantiation of each sign is not. Treat the catalog as a snapshot of the 2026 state and consult updated versions as the field evolves.
Probability not certainty
A score of 65 does not prove AI generation. It states that the deliverable shares twenty visual and structural features with the modal output of current generators. That is strong evidence in a Bayesian sense but not courtroom-grade proof. In a dispute, treat the score as one input alongside other evidence (commit history, design files, vendor testimony) rather than as a verdict.
For internal use (a buyer deciding whether to contest an invoice, a recruiter screening agency portfolios, a founder evaluating a hire), the score is sufficient. For legal disputes or public accusations, support it with additional evidence.
A 15-minute audit protocol for recruiters and agency clients
For recruiters evaluating designer portfolios, agency clients reviewing pitch decks, and procurement teams vetting vendors, the following protocol produces a defensible audit in fifteen minutes.
Minutes 0 to 2: Visual scan
Open the candidate's primary portfolio site. Run the 5-question fast scan. Note the count of yes answers.
If 4-5 yes, the candidate's own portfolio is in the AI-dominant or pure-slop band. This is informative regardless of what the candidate does for clients: their personal site reflects their default taste.
Minutes 2 to 5: Full 21-sign audit
Apply the full method to the portfolio site. Compute the score. Document each sign.
If the portfolio scores below 16, the candidate has demonstrated capacity for human-led design. Proceed.
If it scores above 30, the candidate's default is generator output. Not disqualifying (many successful designers use AI tools heavily), but it must be understood explicitly.
Minutes 5 to 10: Sample case audit
Pick the case study most relevant to the role. Open the linked client site. Apply the 21-sign audit to it.
Compare the case-study score to the portfolio score:
- Case-study score significantly lower: the candidate produces more custom work for clients than for themselves. Common pattern; positive signal.
- Similar: the candidate ships generator-aligned work consistently. Acceptable for some roles, not others.
- Significantly higher: rare. The candidate may have inflated the portfolio's customization for marketing.
Minutes 10 to 13: Process verification
In the candidate's case study, look for:
- Design file links (Figma, Sketch) that can be opened.
- Process screenshots showing iteration.
- Specific design decisions explained in writing.
- Specific results metrics (conversion, performance, engagement).
All four indicates a designer who does the work. The absence of all four, combined with a high score, indicates a designer who passes off generator output.
Minutes 13 to 15: Documentation
Record the audit on a single page:
Candidate: [Name]
Portfolio URL: [URL]
Portfolio score: __/75
Portfolio band: [Human / AI-assisted / AI-dominant / Pure slop]
Case study reviewed: [Case URL]
Case study score: __/75
Case study band: [Human / AI-assisted / AI-dominant / Pure slop]
Process evidence:
[ ] Design files linked
[ ] Iteration shown
[ ] Decisions explained
[ ] Results documented
Recommendation: [Proceed / Discuss process / Decline]
Notes: [Free text]The protocol produces a defensible record. If the candidate is hired and the work later disappoints, the audit is a baseline. If rejected, the rejection is documented with specific evidence rather than vibes.
The same protocol adapts to agency vetting, with the case study replaced by a recent agency client deliverable. The agency playbook for AI-built client sites covers the vendor side of the same conversation.
FAQ
Could a freelance have used AI for half the work and human design for half?
Yes, and this is by far the most common pattern in 2026. The audit handles it naturally: a half-AI half-human deliverable scores in the 20-35 band, which the table classifies as AI-assisted. Acceptable for most contracts. The audit only raises a concern when the score is high (51+) or when the contract specifically promised custom work.
A useful framing: AI assistance is a tool, like Figma or VS Code. The buyer does not object to Figma, even though Figma "did" some of the work. The buyer objects when the deliverable is generic, regardless of which tools produced it. The audit measures genericness, which is the actual concern.
If the site is pretty but generic, is that bad?
It depends on what was promised. A pretty generic site for $2,000 against a brief that said "make it look professional" is fine. A pretty generic site for $30,000 against a brief that said "differentiate us from competitors with a bespoke visual identity" is not.
The audit measures genericness directly. The brief determines whether genericness is acceptable.
How can the reader be 100 percent sure AI was used?
The reader cannot, with the audit alone. The audit produces probability. For certainty:
- Ask the freelance directly. Most admit AI use when asked, especially under contractual disclosure obligations.
- Examine the commit history. If the first commit contains thousands of lines from a
v0_initial_exportor similar source, the origin is clear. - Check the deployment artifacts. Some generators leave identifying artifacts that are difficult to remove.
- Compare against known generator outputs. Some sites are nearly identical to public v0 demos; the comparison is the proof.
Certainty is rarely necessary. The audit is sufficient for most decision contexts.
Is using shadcn/ui a sign of AI?
Not in itself. shadcn is a popular, well-engineered library used by many human developers. The signal is the use of shadcn without customization: default radii, default colors, default class names visible in the DOM. (Why shadcn became a design monoculture explains how a good library became a tell.)
A useful test: open the source. If components/ui/ contains files copied directly from shadcn's CLI and never touched, the use is uncustomized. If the files have been edited to override colors, structure, or behavior, the use is customized. The latter is human-led; the former is generator-aligned.
Does this method work for sites built before AI generators existed?
Yes, with a caveat. Sites built before 2023, when generators became viable, mostly score low because they predate the convergence on canonical defaults. A 2019 startup site that uses Inter and a three-card grid scores high on those individual signs but low on the technical signs (no Next.js, no shadcn, no Vercel headers). The combined score is typically 0-20.
The audit is most reliable for sites built between 2023 and now. For older sites, the verdict is "almost certainly human" by default.
How accurate is the audit on landing pages versus full apps?
The method was developed primarily on landing pages. It generalizes well to marketing sites, brochure sites, and product landing pages. It generalizes poorly to:
- Full SaaS dashboards: the design vocabulary is different (data tables, settings, complex navigation). The 21 signs do not directly apply.
- E-commerce stores: Shopify, WooCommerce, and similar have their own conventions. The audit confuses platform defaults with AI generation.
- Editorial sites: blogs and content-heavy sites have a different anatomy.
- Web apps with authentication: the public landing page is auditable; the authenticated experience is not.
For these, an adapted version is needed. The principle (measure convergence on generator defaults) holds; the specific signs change.
What if the site is genuinely beautiful but checks several boxes?
A site can be beautiful and generic at once. Genericness is about differentiation, not aesthetics. A polished three-card grid with a violet gradient hero is beautiful, in the same way a polished default IKEA bookshelf is beautiful. It also looks like ten thousand other bookshelves.
The audit measures the second property (the resemblance to defaults), not the first. A high score and a beautiful site both being true is a coherent observation. The relevant question is whether the buyer paid for differentiation or for execution.
Can the audit be gamed?
Yes. A vendor who knows the audit can deliberately remove the highest-severity signs while keeping the underlying generator scaffolding. Replace blue-500 with #3a82f6 (one digit off, visually identical). Replace Inter with Manrope. Restructure the hero with two paragraphs instead of one. The score drops; the site is still substantially generator output.
This is the central limit: it measures surface alignment with current defaults. A vendor who decouples the surface from the scaffolding can pass the audit while shipping AI-dominant work.
The mitigation is that, at the level of effort required to defeat the audit, the vendor has done a meaningful portion of the design work. The buyer is no worse off.
Do high scores correlate with bad SEO performance?
Loosely, yes. A high-scoring site has features that correlate with weak SEO:
- Auto-generated OG images underperform custom ones in click-through.
- Identical sitemap timestamps signal lack of editorial activity to crawlers.
- Generic copy underperforms specific copy in long-tail search.
- Fade-in-up animations on every section can cause Cumulative Layout Shift penalties.
The correlation is not causation. Some high-scoring sites rank well because they target uncompetitive terms or have off-page authority. Some low-scoring sites rank poorly because the content is thin. The audit is not an SEO predictor; it overlaps with SEO concerns coincidentally. Google's helpful-content update versus AI slop covers where the two genuinely intersect.
How does Sailop relate to this manual method?
Sailop's free web scan automates a subset of it: eight of the most mechanical signs, checked in a live page's markup and stylesheets, with a fix kit. The manual method covers more signs and, above all, the context (what was promised, what was paid) that no scanner sees.
The two are complementary. The manual method takes thirty seconds for a trained eye and is sufficient for most decisions. The scan gives a repeatable second read, useful when you audit many sites or want to show a vendor exactly which defaults are on the page. A repository scanner is planned but not published.
What is the difference between AI-assisted and AI-dominant?
AI-assisted means a human directed the design and AI helped implement it. The human chose the palette, typography, layout, and copy. AI generated boilerplate, scaffolded components, and accelerated iteration.
AI-dominant means AI produced the design and a human modified it lightly. The AI chose the palette (defaults), the typography (Inter), the layout (canonical anatomy), the copy (canonical microcopy). The human swapped a logo and edited two headlines.
The score band reflects the distinction. 16-30 is AI-assisted. 31-50 is AI-dominant. The labels map to different contractual expectations.
Is it possible for a generator to produce truly custom work?
Not with current technology. Generators are statistical systems that return high-likelihood outputs for given prompts. The high-likelihood output is, by definition, the modal output. The modal output is the generic one. Asking a generator for "custom" produces the average idea of custom, which is itself generic.
A human can use a generator as a starting point and customize aggressively. The result is custom, but the generator did not produce it; the human did. The generator was a fast scaffolding tool. This is AI-assisted work, not AI-generated custom work. (The future of AI-assisted design is constraints, not templates argues where this is heading.)
How often should the method be updated?
Quarterly. Generator defaults change with model updates and platform releases. Specific signs (the exact gradient, the exact emoji, the exact pricing layout) drift on a three-month timescale. The framework is stable; the catalog of signs is not.
Consult the most recent version of this catalog when running an audit. A sign that was diagnostic in Q2 2025 may be obsolete in Q1 2026, replaced by one that captures the new default.
What if the score is borderline (around 30)?
Borderline scores require the contextual flowchart. A score of 30 on a $40,000 corporate site is concerning. A score of 30 on a $2,000 landing page is fine. A score of 30 on a freelance designer's own portfolio is informative but not damning.
For borderline scores, the most useful next step is the process conversation: ask the vendor to explain how the design was developed. The conversation typically resolves the case in five to ten minutes.
Is this method anti-AI?
No. It is anti-misrepresentation. AI tools are productivity multipliers and the field has benefited from them. The method exists because the gap between what some vendors deliver and what buyers expect has widened with generator availability. The audit is a corrective for asymmetric information, not a critique of AI.
In contexts where AI use is disclosed and accepted (Helix Health in Case C), the audit serves a documentation function rather than a corrective one. The high score is a fact, not a complaint.
Glossary
AI-assisted: A site where a human directed the design and used AI tools to accelerate implementation. Typically scores 16-30. Acceptable in most contexts.
AI-dominant: A site where AI produced the foundational design and a human made minor modifications. Typically scores 31-50. Acceptable for internal tools, MVPs, and side projects; questionable for premium custom work.
Pure slop: A site that is direct generator output with negligible human modification. Typically scores 51+. Acceptable when disclosed; problematic when sold as custom work.
Bolt.new: An AI tool from StackBlitz that generates full-stack applications. Tends to favor Astro and Vite. Leaves StackBlitz container artifacts in the bundle.
Claude Artifacts: Anthropic's interactive output mode in claude.ai, often used to produce single-file React applications served inline.
ChatGPT canvas: OpenAI's interactive output surface in the ChatGPT product. Produces similar single-file outputs to Claude Artifacts.
Generator: A tool that converts a natural-language prompt into a working website or component. Includes v0, Lovable, Bolt, Replit Agent, Claude Artifacts, ChatGPT canvas.
Inter: A neo-grotesque sans-serif designed by Rasmus Andersson. The default font of Tailwind documentation, shadcn examples, and most generator outputs.
Lovable: An AI tool that generates full-stack applications with a Supabase backend by default. Prefers React with Vite.
Lucide: An open-source icon library, the default icon set of shadcn/ui and the most common icon source in generator outputs.
OG image: The Open Graph image, rendered when a URL is shared on social platforms. The 1200x630 dimension is canonical.
Radix UI: A library of low-level, accessible component primitives. The foundation shadcn/ui builds on.
Replit Agent: Replit's AI coding assistant. Sites typically deploy to replit.app subdomains unless a custom domain is configured.
shadcn/ui: A copy-paste component library built on Tailwind and Radix UI. Distributed via a CLI that copies source files into the consuming project, allowing local modification.
Slop: A pejorative for generic, low-effort, AI-generated content shipped as if it were custom work. Originated in image generation and spread to other domains. (What is AI slop: 7 dimensions of generic design maps the full taxonomy.)
Tailwind CSS: A utility-first CSS framework. Its default palette includes blue-500 (#3b82f6), violet-500 (#8b5cf6) and purple-500 (#a855f7), stock colors that generated pages often use as-is.
v0 (v0.dev, now v0.app): Vercel's AI app builder. Every chat starts from a Next.js app with Tailwind and shadcn/ui.
Vercel: A hosting platform tightly integrated with Next.js. Sites deployed to Vercel return headers such as server: Vercel and x-vercel-id.
Hosting platform header signatures
The HTTP response headers of a deployed site reveal the hosting platform, which correlates with the most likely generator origin. The following table catalogs the canonical headers per host, with the generators that most commonly deploy to each.
| Hosting platform | Distinctive headers | Default for generator |
|---|---|---|
| Vercel | server: Vercel, x-vercel-id, x-vercel-cache (Vercel docs) | v0 publishes here by default |
| Netlify | x-nf-request-id, server: Netlify | One of Bolt's publishing targets; many hand-built sites |
| Cloudflare | cf-ray, cf-cache-status, server: cloudflare | Anything served through Cloudflare |
| Replit | A replit.app address unless a custom domain is connected | Replit Agent's default |
| Lovable | A lovable.app address unless a custom domain is connected | Lovable's default |
| Bolt Cloud | A bolt.host address unless a custom domain is connected | Bolt's default |
| GitHub Pages | server: GitHub.com, x-github-request-id, x-served-by | Mostly human deployments |
| AWS Amplify | x-amz-cf-id, x-amz-cf-pop, x-cache: Hit from cloudfront | Mostly human deployments |
| Render | x-render-origin-server, rndr-id | Mixed |
| Fly.io | fly-request-id, server: Fly/... | Mostly human, custom backends |
A pattern: Vercel headers combined with shadcn class soup in the DOM and Inter or Geist as the only font are consistent with v0, and also with a developer who chose the same stack by hand. Treat it as a strong lead, not a verdict.
# Standard header inspection workflow:
curl -sI https://example.com | head -30
# Filter for hosting signatures:
curl -sI https://example.com 2>&1 | grep -iE "vercel|netlify|cloudflare|replit|render|fly"
# Check for cache state (indicates ISR):
curl -sI https://example.com | grep -i "x-vercel-cache\|cf-cache-status"The header signature is not the verdict. It narrows the candidate pool. A site on Vercel can be hand-built. A site on AWS can be generator output manually deployed. The header is one of twenty-plus inputs.
DevTools snippet library
The following snippets, runnable in the browser DevTools Console (F12, then Console tab), automate parts of the audit. Each returns a result that maps to a specific sign.
Snippet 1: Detect blue-purple palette
// Extract all unique computed colors on the page
const colors = new Set();
document.querySelectorAll('*').forEach(el => {
const style = getComputedStyle(el);
colors.add(style.color);
colors.add(style.backgroundColor);
colors.add(style.borderColor);
});
const targets = ['rgb(59, 130, 246)', 'rgb(139, 92, 246)', 'rgb(236, 72, 153)'];
const found = targets.filter(t => [...colors].some(c => c === t));
console.log('AI-signature colors detected:', found);
// If both blue-500 and violet-500 show up, flag Sign 1Snippet 2: Verify Inter font dominance
// Count font-family usage across the document
const fontCounts = {};
document.querySelectorAll('*').forEach(el => {
const ff = getComputedStyle(el).fontFamily;
fontCounts[ff] = (fontCounts[ff] || 0) + 1;
});
const sorted = Object.entries(fontCounts).sort((a, b) => b[1] - a[1]);
console.table(sorted.slice(0, 5));
// One family (Inter or Geist) on nearly every node = Sign 2Snippet 3: Detect three-card grid
// Search for any container with exactly three direct children using rounded-2xl
const candidates = [...document.querySelectorAll('div, section')]
.filter(el => el.children.length === 3)
.filter(el => {
const childClasses = [...el.children].map(c => c.className || '');
return childClasses.every(c => c.includes('rounded-2xl') || c.includes('rounded-xl'));
});
console.log('Three-card rounded grid candidates:', candidates.length);
candidates.forEach(c => console.log(c));Snippet 4: Detect canonical hero structure
// Look for an h1 immediately followed by p, then exactly two button-like elements
const h1 = document.querySelector('h1');
if (h1) {
let next = h1.nextElementSibling;
const sequence = [];
while (next && sequence.length < 5) {
sequence.push(next.tagName);
next = next.nextElementSibling;
}
console.log('Post-H1 sequence:', sequence);
// Canonical AI hero: ['P', 'DIV'] where DIV contains 2 buttons, or ['P', 'BUTTON', 'BUTTON']
}Snippet 5: Detect emoji pill above H1
const h1 = document.querySelector('h1');
if (h1) {
let prev = h1.previousElementSibling;
if (prev) {
const text = prev.innerText || '';
const emojiPattern = /[✨\u{1F680}\u{1F525}]/u;
if (emojiPattern.test(text)) {
console.log('Emoji pill detected:', text);
}
}
}Snippet 6: Detect violet-to-pink gradient
// Find any element with a gradient containing canonical AI stops
const gradients = [];
document.querySelectorAll('*').forEach(el => {
const bg = getComputedStyle(el).backgroundImage;
if (bg.includes('gradient') && (bg.includes('139, 92, 246') || bg.includes('236, 72, 153'))) {
gradients.push({ el, bg });
}
});
console.log('Violet-to-pink gradients found:', gradients.length);Snippet 7: Detect shadcn class signature
// shadcn buttons have a distinctive long class soup
const shadcnSignature = /inline-flex items-center justify-center.*ring-offset-background/;
const matches = [...document.querySelectorAll('button, a')].filter(el =>
shadcnSignature.test(el.className)
);
console.log('Shadcn-pattern buttons:', matches.length);Snippet 8: Detect Radix UI primitives
// Radix attaches data-radix-* attributes
const radixAttrs = ['data-radix-collection-item', 'data-radix-popper-content-wrapper', 'data-state'];
const counts = {};
radixAttrs.forEach(attr => {
counts[attr] = document.querySelectorAll(`[${attr}]`).length;
});
console.table(counts);Snippet 9: Detect Lucide icons
// Lucide SVGs have a recognizable class pattern
const lucideIcons = document.querySelectorAll('svg[class*="lucide"]');
console.log('Lucide icons on page:', lucideIcons.length);
const totalSvgs = document.querySelectorAll('svg').length;
console.log('Total SVGs:', totalSvgs);
console.log('Lucide ratio:', (lucideIcons.length / totalSvgs * 100).toFixed(1) + '%');
// Nearly all SVGs from Lucide = Sign 20Snippet 10: Check for Next.js framework
// Next.js leaves identifiers in the global scope and DOM
const isNext = !!(window.__NEXT_DATA__ || document.getElementById('__next'));
console.log('Next.js detected:', isNext);
if (isNext) {
console.log('Next.js build ID:', window.__NEXT_DATA__?.buildId);
}Snippet 11: Inspect sitemap timestamps
// Fetch and analyze sitemap.xml from the same origin
fetch('/sitemap.xml')
.then(r => r.text())
.then(xml => {
const matches = xml.match(/<lastmod>([^<]+)<\/lastmod>/g) || [];
const dates = matches.map(m => m.replace(/<\/?lastmod>/g, ''));
const unique = new Set(dates);
console.log('Total <lastmod> entries:', dates.length);
console.log('Unique timestamps:', unique.size);
if (dates.length > 5 && unique.size === 1) {
console.log('All timestamps identical:', [...unique][0]);
}
});Snippet 12: Detect default 404
// Try a guaranteed-404 path
fetch('/random-path-that-cannot-exist-' + Math.random().toString(36).slice(2))
.then(r => r.text())
.then(html => {
const isNextDefault = html.includes('This page could not be found') || html.includes('404 | This page');
const isVercelDefault = html.includes('NOT_FOUND') && html.includes('Vercel');
console.log('Next.js default 404:', isNextDefault);
console.log('Vercel default 404:', isVercelDefault);
});These snippets run in any modern browser without installation. Paste them sequentially into the Console and accumulate evidence in under two minutes.
Score severity adjustments by context
The raw score is the starting point. Context modifies the interpretation. The following adjustments refine the verdict.
Adjustment 1: Industry baseline
Some industries have higher legitimate use of canonical patterns than others. A B2B SaaS company is more likely to use the canonical pricing card and three-benefit grid because that anatomy is genuinely effective for that audience. A boutique agency, a creative studio, or an editorial brand has stronger expectations of differentiation.
| Industry | Score adjustment | Rationale |
|---|---|---|
| B2B SaaS, mid-market | -10 from raw | Canonical anatomy genuinely effective; less expectation of bespoke |
| Creative agency or studio | +10 to raw | Differentiation is the product; high score is more concerning |
| Boutique consultancy | +5 to raw | Premium positioning expected |
| Indie hacker / solo founder MVP | -15 from raw | Speed is the priority; AI use expected |
| Enterprise / Fortune 500 | +10 to raw | Procurement expects custom work |
| Open-source project landing | -10 from raw | Functional concerns dominate |
| E-commerce shop | -5 from raw | Platform conventions inflate score |
| Personal portfolio | depends | If creative role: +10. If technical role: -5. |
| Nonprofit | -5 from raw | Budget constraints justify generic builds |
| Editorial / media | +5 to raw | Voice and identity are core |
A B2B SaaS site scoring 40 raw is, after adjustment, scoring 30: borderline acceptable. A creative agency scoring 40 raw is, after adjustment, scoring 50: concerning.
Adjustment 2: Promised level of customization
The contract or pitch sets expectations. Compare the score to what was promised.
| Promise level | Acceptable score ceiling |
|---|---|
| "Quick landing page" or "MVP" | 60 |
| "Professional design" | 40 |
| "Custom design system" | 25 |
| "Bespoke brand identity" | 15 |
| "From-scratch fully custom" | 10 |
A score above the ceiling means the deliverable does not match the promise. The conversation with the vendor should focus on closing the gap, either by reworking to lower the score or by renegotiating the price to match the actual customization level.
Adjustment 3: Time and budget invested
A site with a scoped budget of $1,500 cannot reasonably achieve the lowest score band. The cost of escaping the canonical defaults (typography research, custom palette, bespoke illustrations, motion design) is itself a labor cost. Scores must be weighed against budget.
Budget vs. acceptable score:
$0 - 1,500 60 ceiling (template territory)
$1,500 - 5,000 45 ceiling (template-plus territory)
$5,000 - 15,000 30 ceiling (custom-light territory)
$15,000 - 50,000 20 ceiling (custom territory)
$50,000+ 10 ceiling (bespoke territory)A $30,000 deliverable scoring 50 is a price-quality mismatch. A $1,000 deliverable scoring 50 is fine: generic was what the budget bought.
Audit walk-through example
A fully worked example of the 21-sign audit applied in real time to a hypothetical site: "QuoteEngine.io," a fictional B2B SaaS for proposal automation. The freelance vendor charged $18,000 with a brief that read "modern, custom, professional design system."
Phase 1: Visual scan (10 seconds)
The reader opens the homepage. Above the fold:
- A pill above the H1 reading "✨ New: AI-powered proposal scoring"
- An H1: "The proposal platform built for modern teams"
- A paragraph: "QuoteEngine helps sales teams send winning proposals in minutes, not hours. Powered by AI."
- Two buttons: "Get started free" (filled blue) and "Watch demo" (ghost gray)
- A horizontal strip of four grayscale logos under "Trusted by leading teams"
Initial flags: 1 (palette likely), 4 (canonical hero), 5 (sparkle pill), 7 (trusted by), 13 (canonical microcopy).
Phase 2: Section walk (15 seconds)
Scrolling reveals:
- Three benefit cards with icons, headings, and short descriptions, each in a
rounded-2xlcontainer with shadow - A "How it works" section with three numbered steps and Lucide icons
- A pricing section with three plans (Starter $19, Pro $49, Enterprise "Contact us") in
rounded-2xlcards with green checkmarks - A testimonial slider with three round headshots and short quotes
- An accordion FAQ with eight questions, chevron icons, default styling
- A footer with four columns: Product, Company, Resources, Legal
Additional flags: 3 (three-card grid), 8 (how it works), 9 (three pricing plans), 10 (testimonial slider), 11 (plain FAQ), 12 (four-column footer).
Phase 3: Technical inspect (5 seconds)
The reader presses F12. The primary CTA button's class attribute reads:
inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 bg-blue-500 text-white hover:bg-blue-600 h-10 px-4 py-2The canonical shadcn button variant with a Tailwind blue-500 background.
Body text font-family reads "Inter, sans-serif": Inter only. The hero background blob's background-image is linear-gradient(135deg, rgb(139, 92, 246), rgb(236, 72, 153)). The first request returns server: Vercel and an x-vercel-id header. Appending /sitemap.xml shows every entry sharing the same <lastmod>.
Additional flags: 1 (confirmed blue-500), 2 (Inter only), 6 (canonical gradient), 18 (shadcn class soup), 19 (Tailwind defaults), 21 (identical sitemap dates).
Score computation
| # | Sign | Severity | Flagged | Score |
|---|---|---|---|---|
| 1 | Blue-500 + violet-500 | 4 | Yes | 4 |
| 2 | Inter only | 3 | Yes | 3 |
| 3 | Three-card grid | 5 | Yes | 5 |
| 4 | Canonical hero | 4 | Yes | 4 |
| 5 | Sparkle pill | 4 | Yes | 4 |
| 6 | Violet-to-pink gradient | 5 | Yes | 5 |
| 7 | Trusted by | 2 | Yes | 2 |
| 8 | How it works (Lucide) | 3 | Yes | 3 |
| 9 | Three pricing plans | 5 | Yes | 5 |
| 10 | Testimonial slider | 3 | Yes | 3 |
| 11 | Plain FAQ | 2 | Yes | 2 |
| 12 | Four-column footer | 4 | Yes | 4 |
| 13 | Canonical microcopy | 4 | Yes | 4 |
| 14 | Auto OG image | 3 | (not checked) | 0 |
| 15 | Default 404 | 3 | (not checked) | 0 |
| 16 | No favicon | 2 | (not checked) | 0 |
| 17 | fade-in-up only | 3 | Yes | 3 |
| 18 | shadcn class soup | 4 | Yes | 4 |
| 19 | text-gray-500 | 3 | Yes | 3 |
| 20 | Lucide everywhere | 2 | Yes | 2 |
| 21 | Identical sitemap | 3 | Yes | 3 |
| TOTAL | 63/75 |
Adjustments: B2B SaaS industry (-10). Promised "custom design system" (ceiling 25). Budget $18,000 (ceiling 30).
Adjusted score: 53. Verdict band remains Pure slop. Promise gap: 53 vs. 25 ceiling = 28 points over. Budget gap: 53 vs. 30 ceiling = 23 points over.
Outcome
The buyer's options:
- Accept the deliverable as-is, acknowledge the marketing site is generic, and discount the fee accordingly.
- Request a rework focused on lowering the score: custom palette, custom typography, restructured hero, custom illustrations, removal of the canonical pricing structure. The rework should target a score below 25.
- Cancel the engagement, retain the working site for interim use, and engage a different vendor for the brand rebuild.
The audit does not choose option 1, 2, or 3. It quantifies the gap between deliverable and expectation and provides the vocabulary to negotiate.
Multi-page audit considerations
The method above audits a single page: typically the homepage. Some sites vary across pages, where the homepage is generic but interior pages show real customization, or vice versa. A multi-page audit captures the variance.
Page selection for audit
For a multi-page site, the recommended sample:
- Homepage (always audit)
- Pricing page (separate audit if it exists)
- About page (separate audit)
- One blog post or content page (separate audit)
- Contact or signup page (separate audit)
Compute the score for each independently. The five scores combine into a profile.
Variance interpretation
The variance across pages is itself a signal.
| Variance pattern | Interpretation |
|---|---|
| All pages score similarly (within ±5) | Consistent build; either all custom or all generated |
| Homepage low, interior pages high | Hand-tuned homepage with generated interior; common with limited budget |
| Homepage high, interior pages low | Generated homepage with curated content pages; rare but exists |
| Wildly inconsistent (variance > 30) | Multiple authors or mixed AI/human work |
| One page dramatically higher | Recently added section, possibly post-launch generator output |
A site where every page scores 60+ is fully generated with no human curation. A site where the homepage scores 10 and the pricing page scores 60 is a hand-built marketing front with a generated pricing extension: a common pattern when a startup adds pricing late and uses a generator for the addition.
Per-route signal
For Next.js sites, the per-route bundle can reveal which pages have custom code. Using DevTools' Network tab, navigate between pages and watch for:
- A new
_next/static/chunks/pages/[route].jsrequest: a code-split page with potentially custom logic. - The same chunk reused: the page is part of the static export with shared component reuse.
A site where every route reuses identical chunks is more likely generated than a site with diverse per-route bundles.
Detection at scale: auditing many sites
Some readers (recruiters, agency procurement teams, talent directors) face the problem of auditing dozens of candidate sites. The manual 30-second method does not scale to one hundred sites in one sitting. The following workflow handles volume.
Phase A: Triage with automation
Run the 30-second fast scan on each site, or run each URL through an automated checker such as Sailop's free web scan, one page at a time (there is no batch mode). Record a first score for each.
Phase B: Filter to the gray zone
The batch produces three groups:
- Clearly human (score 0-15)
- Gray zone (score 16-50)
- Clearly slop (score 51-75)
Group 1 passes without further audit. Group 3 either fails or warrants a manual conversation about disclosure. Group 2 (the gray zone) receives the manual 30-second audit.
How many land in each group depends entirely on your candidates; expect the gray zone to be the largest.
Phase C: Manual gray-zone audit
Each group 2 candidate receives a manual 30-second pass producing:
- Confirmation of the automated score (or correction up/down)
- A qualitative note on dominant signs
- A binary recommendation: proceed, decline, or request process documentation
At 30 seconds per gray-zone candidate, even fifty of them take under half an hour.
Phase D: Deep dive on top candidates
The short list of strong candidates (typically 5-15 names) receives the full 15-minute protocol from the recruiter section. For 10 candidates at 15 minutes each, the deep dive takes 2.5 hours.
Total time budget
For one hundred candidate sites, at the timings this method assumes:
- Phase A (fast scan, 30 seconds each): under an hour
- Phase B (filtering): a few minutes
- Phase C (gray zone, 30 seconds each): depends on how many land there
- Phase D (top candidates, 15 minutes each): about two and a half hours for ten
That is half a day, against roughly 25 hours for a full 15-minute protocol on every site.
The economic logic of slop
Why does pure slop exist? The audit produces evidence; it does not produce a theory. A brief economic framing explains the prevalence. (The AI slop economy develops this argument across the whole market.)
Vendor incentives
A freelance designer or small agency faces a sharp tradeoff. Custom design takes time. Time is the binding constraint on revenue. A typical custom landing page from an experienced designer takes 40-80 hours over 4-8 weeks. A generated landing page takes 2-4 hours over 1-2 days.
If both are billed at $15,000, the hourly rate of the generated work is approximately $5,000/hour while the custom work is approximately $250/hour. The vendor's incentive to ship slop while charging custom rates is enormous.
The constraint is detection. If buyers detect slop, the vendor loses repeat business and reputation. The audit shifts the detection probability upward, which shifts the equilibrium back toward honest pricing.
Buyer vulnerability
The typical buyer is not a designer and cannot, before learning the audit, distinguish a generic landing page from a custom one. The visual quality of generator output is high enough that, to an untrained eye, it looks competent and professional.
Buyers compensate by relying on referrals, portfolios, and testimonials. None is robust against vendor misrepresentation. A vendor with a strong portfolio (perhaps borrowed, perhaps from a few legitimate engagements) can ship slop on subsequent contracts without easy detection.
The audit is the buyer's response to this asymmetry. It transfers some diagnostic capacity from the trained designer to the lay buyer.
Market consequences
If audit adoption increases, three market effects follow:
- Honest pricing equilibrium: Vendors who use AI tools are forced to price accordingly. The $15,000 generated landing page becomes a $3,000 generated landing page, the difference reflecting transparency rather than effort.
- Premium for differentiation: Vendors who do genuinely custom work can command a higher premium because the audit verifies their claim. The $15,000 custom landing page becomes a $25,000 custom landing page that buyers can confidently distinguish from generated work.
- Generator commoditization: Generators become positioned as buyer-facing tools. A buyer who knows they need a generic site uses v0 directly for $20/month instead of paying a vendor to use v0 on their behalf. The intermediation premium collapses.
The end state is a market where buyers either pay for tools (generators, templates) or pay for differentiation (custom designers). The middle (generic work passed off as custom) disappears under audit pressure.
Edge case: hybrid sites
A pattern that confounds the simple score: the hybrid site. A vendor uses a generator for the marketing pages (homepage, pricing, about) and writes custom code for the product or app section. The marketing pages score high; the product section scores low.
The hybrid pattern is increasingly common because:
- The marketing pages have less variance per industry; a generator output is "good enough" for most B2B marketing.
- The product or app needs domain-specific logic that generators cannot produce.
- The vendor's effort is concentrated where it matters technically, not visually.
For audit purposes, the hybrid pattern requires distinguishing the contractual scope. If the buyer paid for "the website" and the marketing pages are slop, the score reflects the deliverable. If the buyer paid for "the product" and the marketing pages are an afterthought, the marketing score may not be the relevant signal.
The audit should explicitly note when a hybrid pattern is detected:
Audit summary:
- Marketing pages: score 58 (Pure slop band)
- Product/app pages: score 14 (Human-designed band)
- Hybrid pattern confirmed
- Contractual scope: [buyer to determine]
- Recommendation: clarify whether the contract covered the marketing surfaceThe hybrid pattern is not necessarily bad faith. It can be an honest division of effort the buyer was not warned about. The audit makes the division visible.
Edge case: the deliberate generic
A small but genuine class of sites scores high because the designer deliberately chose to look generic. The intent might be:
- Communicating "we are like every other modern startup" as a positioning choice.
- Reducing visual friction with users accustomed to canonical patterns.
- Saving design effort to allocate elsewhere (product, customer success, content).
- Conforming to a corporate parent's brand guidelines that resemble modern startup defaults.
In these cases, the high score is accurate, but the interpretation differs. The site is generic, yes, but the buyer who wanted generic got what they paid for.
The audit cannot distinguish deliberate generic from accidental generic. The conversation with the vendor reveals the difference. Asking "was the canonical SaaS visual language a deliberate choice?" produces the answer. A deliberate choice was articulated in writing during the engagement; an accidental choice was not discussed.
For deliberate generic, the audit serves documentation: the buyer should at least know they bought generic. Expectation alignment matters more than the score.
Edge case: rebrands and refreshes
When auditing a recently rebranded site, the score may be temporarily inflated. A rebrand often involves:
- A new visual identity created by humans (low score signal)
- Implementation by developers using current frameworks (high score signal)
- A mix of new content and legacy content (variance)
The post-rebrand site may score in the 30s, not because it is AI-generated, but because the implementation layer is canonical even when the design layer is custom.
The mitigation is to audit the design system separately from the implementation:
- Look at the brand book, if available. Was a custom palette specified? Custom typography? Custom illustration style?
- Compare the brand book to the deployed site. Does the deployment match?
- If the brand book specifies custom and the deployment is canonical, the implementation team may have shortcut the brand work.
The score is then weighted: brand work is what the buyer paid the brand agency for; implementation may have been delegated to a different team. A high score on a rebranded site can indicate execution debt rather than design debt.
The role of templates
A significant fraction of gray-zone sites are not AI-generated but template-based. Templates from ThemeForest, Tailwind UI, Cruip, Stripe Press, and similar marketplaces produce sites that share most of the canonical signs. The audit cannot distinguish a template from generator output. (Why templates need a score argues the case directly.)
This is intentional. From the buyer's perspective, the relevant question is not "did AI make this?" but "is this generic?" A template-based site is generic by construction; a generator-based site is generic by emergence. The outcome for the buyer is similar.
That said, some buyers care about the distinction. To probe template versus generator origin:
- Reverse-image-search the OG image. If it appears on multiple unrelated sites, a template is shared.
- Inspect the source for template-specific identifiers. Tailwind UI components have predictable class compositions. Cruip templates have characteristic file structures.
- Ask the vendor directly. Most admit template use when asked, since templates are an accepted commercial reality.
Templates are not a problem unless misrepresented. A buyer who knew they were getting a template gets what they paid for. A buyer told "completely custom" who got a Tailwind UI template is in the same misrepresentation territory as one who got generator output.
Method calibration over time
The 21 signs reflect the state of generator defaults in early 2026. The catalog should be re-validated quarterly. The following protocol describes the calibration process for readers who maintain their own audit framework.
Step 1: Generate fresh samples
Each quarter, generate ten new sites from each major tool (v0, Lovable, Bolt, Replit Agent, Claude Artifacts, ChatGPT canvas) using a standard prompt: "Build a modern landing page for a B2B SaaS startup that helps sales teams write better proposals."
The standard prompt provides a consistent baseline. Variations in defaults across quarters reflect generator updates rather than prompt variation.
Step 2: Tabulate sign frequency
For each sign, count the frequency of presence across the fresh samples. A sign that was diagnostic in Q1 (present in 80 percent of samples) but is now present in only 30 percent has lost diagnostic value and should be downweighted or replaced.
Step 3: Identify new defaults
Examine the fresh samples for patterns not in the existing catalog. New defaults emerge as generators update. Examples of recently emerged signs:
- Glassmorphism cards with
backdrop-blur-md(see glassmorphism as an AI tell) - Bento-grid hero layouts replacing the three-card section (the bento grid is the new hero)
zinc-950dark-mode hero backgrounds as a new default (zinc-950 dark hero)
New signs are added to the catalog with a starting severity matching their observed diagnostic value.
Step 4: Recalibrate severity scores
For each sign, recompute the diagnostic accuracy: precision (probability AI given sign present) and recall (probability sign present given AI). The severity score combines these into a single number scaled 1 to 5.
A sign with high precision but low recall is a strong but rare signal: high severity, low frequency. A sign with high recall but low precision is a common but weak signal: moderate severity, high frequency. The severity scale absorbs this tradeoff.
Step 5: Re-test against human samples
To prevent drift toward over-detection, the recalibrated method must be re-tested against a control sample of known human-designed sites. False positive rate should remain below 15 percent for signs above severity 3, and below 30 percent for signs at severity 2 or below.
The full calibration cycle takes roughly four hours of focused work per quarter. The output is a versioned catalog (v1.0, v1.1, v1.2, etc.) with documented changes.
Cross-reference with content slop detection
The audit above focuses on visual and structural slop. A complementary diagnostic targets content slop: the actual words on the page. The two are related but distinct.
Content slop signs include:
- Long paragraphs of generic startup language with no specific examples
- Repeated transitions like "Furthermore," "Moreover," "Additionally," "In conclusion"
- The phrase "in today's fast-paced world" or variants
- Lists of three benefits, each with a generic adjective ("Powerful," "Seamless," "Intuitive")
- Bullet points that all begin with verbs in the same tense
- A blog post grid where every post has a similar abstract image and a one-line summary that explains nothing
The content audit correlates moderately with the visual audit. A site that scores high on visual signs typically also has generic copy, since both originated from the same generator pass. But the correlation is not perfect: some teams use a generator for visuals and write copy by hand, or vice versa.
For a complete audit, compute both scores and report them separately. A site might be 60 visual / 20 content (visual generator, hand-written copy) or 20 visual / 60 content (custom design, generic copy). The combined report is more informative than either alone.
A practical workflow:
- Run the 21-sign visual audit (this article) for the visual score.
- Run GPTZero or equivalent on the longest text blocks for the content score.
- Combine into a unified verdict.
A site scoring high on both is fully generated. A site scoring high on one and low on the other is partially generated, and the audit can identify which part.
From intuition to evidence
The audit formalizes what experienced developers already do informally. It moves the diagnostic from intuition ("this looks generated") to evidence ("here are 14 of 21 signs present"). The shift matters for public conversations because it changes the burden: a vendor cannot dismiss "this looks generated" but must address "here are the 14 specific features that match generator defaults."
Limitations of the comparative approach
The 21-sign method is comparative: it measures the deliverable's resemblance to known generator outputs. The approach has structural limitations.
Limitation 1: New generators
When a new generator launches with substantially different defaults, the catalog does not capture it until the next calibration cycle. A site generated by a tool released last week, with different defaults, may score zero on the catalog while being entirely AI-generated.
The mitigation is the meta-signal: any site that looks too consistent (every section in the same style, every spacing identical, every choice the obvious default) is suspect even if the specific defaults are unfamiliar. A trained eye captures this even when the catalog does not.
Limitation 2: Adversarial customization
A vendor who knows the audit can deliberately add noise. Replace blue-500 with #3b83f7 (one digit off, visually identical, but no longer matching the audit's exact hex). Use a custom font similar to Inter. Restructure the hero with three buttons instead of two. The score drops; the underlying generator scaffolding remains.
The mitigation is to score the structural patterns at a higher level of abstraction. The presence of a hero with a CTA pair (regardless of count) is a structural sign. The use of a single sans-serif throughout (regardless of whether it is Inter exactly) is a structural sign. The audit can be reformulated to capture these higher-level patterns, at the cost of higher false-positive rates.
Limitation 3: Convergence with human design
The defaults that generators produce are not random. They are the modal patterns of human-designed sites in the training corpus. As humans converge on these patterns (because they are effective), the audit's discrimination capacity decreases. The catalog cannot distinguish a generator from a human who chooses generator-aligned defaults.
The mitigation is to focus on signs humans rarely produce: the technical fingerprints (shadcn class soup unmodified, identical sitemap timestamps, default 404s). These are less converged because they reflect platform laziness rather than design choice.
Limitation 4: Single point in time
The audit captures the site at one moment. A site that was generated, then thoroughly customized over six months, may now score low. A site that was hand-built but recently extended with a generated section may now score high. The audit does not see the trajectory.
The mitigation is to ask about history. Vendors who hand-built typically have commit history, design files, and process documentation. The audit produces the score; the supporting evidence produces the trajectory.
Cross-tool comparison: what each generator gets right
A balanced view requires noting where each major generator differs from the modal output. The differences are diagnostic in their own right, and they illustrate that "AI-generated" is not monolithic.
v0 (Vercel)
Documented: every chat starts from a Next.js app with shadcn/ui and Tailwind CSS; v0's docs warn it "may struggle" with customized shadcn components; Design Systems 2.0 lets a team start from its own components and tokens instead.
Tells: shadcn/ui components left as installed, Vercel hosting headers, a default typeface.
Departures from canonical: with a design system or a specific prompt (named fonts, hex values, a layout), the defaults move.
Lovable
Documented: one fixed stack (TanStack Start with React and Tailwind for new apps), a built-in backend (Lovable Cloud) or Supabase, hosting on lovable.app.
Tells: the "Edit with Lovable" badge on free-plan sites, a lovable.app address, design defaults when its design questions were skipped.
Departures from canonical: Lovable asks about palette, typography and layout before it builds when a prompt leaves them open; answered properly, the output moves away from the defaults.
Bolt.new
Documented: any JavaScript framework that runs on the frontend, Node.js for the backend, running in WebContainers; publishing to Bolt Cloud (bolt.host) or Netlify.
Tells: the "Made in Bolt" badge on free-plan sites, a bolt.host address.
Departures from canonical: because the framework varies, the DOM signature varies too; the visual defaults are what stay constant.
Replit Agent
Documented: a full workspace with databases, secrets and several deployment types; Agent 4 (March 2026) holds several apps in one project.
Tells: a replit.app address unless a custom domain is configured, the "Made with Replit" badge on free-plan apps.
Departures from canonical: Replit sites are more often functional apps than marketing pages, so the 21-sign catalog (focused on marketing pages) applies less directly.
Chat assistants (Claude, ChatGPT)
Pages drafted in a chat assistant and pasted into a project carry whatever the model reached for. The model makers document the tendency: Anthropic's frontend prompt exists because Claude "tends toward generic, conservative designs" without guidance, and OpenAI's GPT-5 guide recommends Tailwind, shadcn/ui, Lucide and Inter or Geist for new frontends. Expect the same visual defaults as the builders, in a simpler structure.
Three-month-out predictions
The 2026 generator landscape will not stabilize. Predictions for the period through the end of 2026:
Convergence on a few stacks: Generators will keep favoring React with Tailwind and component kits; Lovable already moved all new apps to one stack, TanStack Start, in May 2026. Detection of the stack becomes simpler; detection of the tool does not.
Counter-convergence on customization: Sophisticated users will increasingly add a customization layer to generator output. The middle tier of audit scores (30-50) will inflate; pure slop (51+) will become rarer because the worst offenders learn to add basic customization.
Audit tooling proliferation: automated checks for generator defaults will become ordinary procurement tooling for agencies and recruiters.
Vendor transparency requirements: Industry norms will shift toward mandatory AI disclosure in client work. Contracts will routinely include AI-use clauses. The current ambiguity will be replaced by explicit terms.
Generator-side countermeasures: Builders will keep adding ways to move off their own defaults (Lovable's design questions and v0's design systems are early examples). The canonical signature will fragment.
Detection lag and recalibration: As generators vary their defaults, the catalog will require monthly rather than quarterly updates. Diagnostic capacity will compress to a smaller set of structural signs (hero anatomy, pricing structure, footer pattern) that change more slowly than surface details.
The trajectory is mutual escalation: better detection, better adversarial customization, better detection again. The equilibrium is not no-AI; it is transparent-AI, where buyers know what they are paying for and vendors price accordingly.
Concluding observations
The 21-sign method is a tool. Like any tool, its value depends on how it is used.
Used well, it gives a buyer the vocabulary to ask the right questions, the evidence to support a renegotiation, and the framework to evaluate vendors objectively. It transfers diagnostic capacity from a small group of experienced designers to anyone who reads this article.
Used poorly, it becomes a weapon. A buyer who treats the score as a verdict, refuses to consider context, and weaponizes the 21 signs against legitimate AI-assisted work undermines the productivity gains AI tools provide to the entire field.
The intended use is the former. The article documents twenty-one observable features. It assigns severity weights. It produces a score. The score is a starting point for a conversation, not a substitute for one. (If the diagnosis lands on your own site, how to build a unique landing page without looking AI-generated is the way out.)
For the recruiter screening agency portfolios, the audit is preparation for the vetting call. For the buyer evaluating a deliverable, it is preparation for the project review. For the founder considering vendors, it is preparation for the contract negotiation.
In all three, the audit closes the information asymmetry between buyer and vendor. That closure has value regardless of the eventual decision. A buyer who decides to accept generator output at generator pricing is fine. A buyer who decides to demand custom work and pays accordingly is fine. The buyer who is unaware of the distinction is the one the audit serves.
The method has limits. It produces probabilities, not certainties. It measures alignment with current defaults, which drift over time. It can be defeated by sophisticated customization. None of these invalidate the audit. They define its scope.
What the audit does, reliably, is shift the burden of evidence. Before the audit, the buyer faced a black box: a deliverable that may or may not have been custom work. After the audit, the buyer has a number, a per-sign breakdown, and a vocabulary for the conversation that follows. The number is not a verdict, but it is a starting point.
For thirty seconds of inspection, that starting point is enough.
Revision note
Updated on 18 October 2026. Removed: per-sign "detection gain" percentages and false-positive rates, a claimed calibration on "one hundred random freelance portfolio sites and one hundred random AI-generated demos" with accuracy figures, a distribution chart of "100 audited freelance sites," a chart of detectability by year, "documented" public cases, and tool signatures we could not verify (data-v0-* attributes, an x-vercel-deployment-id header, a Bolt config file and SDK, a "Built with Lovable" footer link, Lovable using Mantine). None of it was backed by data we hold. Signal strengths are now labeled as editorial judgments, the five case studies are labeled as composites, the hosting and generator tables follow the vendors' documentation, the shadcn/ui signs follow its current source, and the Sailop section describes the free web scan that exists today. #8b5cf6 is Tailwind's violet-500, not purple-500; the text now says so.
Scan a live page
Eight AI defaults, the evidence for each, and a fix kit. Free, no account.