vibecoded-design-tells: what Reddit flags as the AI website look, and a scanner that fails CI on it
Reddit-mined data ranking the visual tells of vibe-coded (AI-built) sites: 3.2M posts scanned across 47 subreddits, with scripts, raw data, and charts.
At a glance
- What is it?
- A Reddit-mined study of 3.2M posts ranks the visual tells of AI-built sites, and ships three Claude skills plus a scanner that greps a codebase and gates CI on its exit code. The data is reproducible with Python and matplotlib; the scanner is the part you can actually run.
- Who is it for?
- Adopt the scanner if you already run a CI lint step and want the AI-default look to fail a build rather than pass review, and read the comment-level ranking in comment_tell_counts.csv if you want to know which of your habits is loudest. Do not adopt it as a style guide: the repo says plainly that it does not impose a look, so a team looking for a house aesthetic will find nothing here, and the study is a proxy for vocal online opinion rather than a survey.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 86 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 18, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem: reviewers cannot name what makes a site read as AI-built
Ask a designer why a landing page feels generated and the answer is usually a shrug plus a gesture. The complaint is real but unenumerated, which makes it hard to act on and easy to dismiss. This repository turns the shrug into a ranked list. It scans public Reddit discussion from the Arctic Shift archive, tabulates which design features people actually name, and verifies each candidate tell against verbatim quotes with permalinks.
The audience is narrow and specific: engineers and designers shipping AI-assisted front ends who want to know which patterns get noticed, and anyone who wants a scanner rather than an opinion. The README states the flagship study ranked visual tells and that the same findings are packaged as a Claude skill. It is not a design system, and it does not tell you what to build instead.
How the corpus was built and why the comment ranking is the primary one
The pipeline is sequential and resumable, and every stage writes into the unslop-ai-ui/ folder. collect.py uses the aggregate endpoint for per-subreddit totals and matched-by-year counts. harvest.py takes a numeric argument (the README shows 3000) and pulls on-topic post text into corpus.jsonl. harvest_comments.py pulls comments from what the README calls 125 canonical threads into comments.jsonl. analyze.py tabulates post-level tells and draws the first five charts; analyze_comments.py does the comment-level tabulation; make_charts.py and make_charts2.py produce the honest comparison charts and the scale, funnel, concentration, co-occurrence, sentiment and thread charts.
The numbers as stated: 3,214,533 posts scanned across 47 AI and SaaS subreddits from 2020 to 2026, of which 46,971 are on-topic (1.46%), plus 3,033 comments harvested from 125 canonical threads. The design choice worth noting is that the comment-level ranking is treated as primary. The README's reasoning is that those threads are all on-topic, so the signal is not diluted by the 98.5% of scanned posts that merely mention AI. That is a defensible call, and it also means the headline percentages describe a small, self-selected group of people who chose to post in a complaint thread.
Detection is keyword-based. Tells are matched with a synonym lexicon in analyze.py, counted over a design-context subset of the corpus. The README is upfront that keyword matching can miss sarcasm or catch the wrong sense of a word, and that small subreddits are noisy. One candidate tell, mesh/blob/aurora backgrounds, was rejected outright as a keyword artifact after an adversarial verification pass, with 11 of 12 surviving. That rejection is the most informative line in the README: it tells you the authors checked, and it tells you the method's failure mode is exactly the kind of false positive you would expect from a lexicon.
Installing unslop-ui and running the scanner on a real codebase
The skill ships as a .skill archive. The README gives two install paths: unzip it into the Claude skills directory, or upload the file through the claude.ai skills UI. The command below is the local one, and after it runs you should see an unslop-ui directory under ~/.claude/skills/ containing SKILL.md and the scripts folder.
unzip skill/unslop-ui.skill -d ~/.claude/skills/The part that matters for a first real use is the standalone scanner, skill/scripts/devibe_scan.py. It greps a codebase, prints findings with a vibe score, and gates CI on its exit code. The README points at skill/README.md for how to install and run it, and does not reproduce the invocation in the top-level file, so check that file for the exact argument form before you wire it into a pipeline. The shape of the result is described: a list of findings and a score.
The study itself is reproducible without the skill, and this is the order the README specifies. The requirements file pins matplotlib and numpy only; everything else uses the standard library, and the README notes there is no API key and no auth.
pip install -r requirements.txt
cd unslop-ai-ui
python3 collect.py
python3 harvest.py 3000
python3 harvest_comments.py
python3 analyze.py
python3 analyze_comments.py
python3 make_charts.py
python3 make_charts2.pyIf you would rather not re-harvest, the committed corpus.jsonl.gz is a snapshot. The README says to gunzip it first, then run the analysis scripts against it. The comment-level ranking lands in comment_tell_counts.csv, and the verbatim evidence with permalinks is in comment_tell_examples.md.
What the ranking actually says, and where the memes fall
The headline finding is not a feature. It is recognizability. "They all look the same" and "screams AI / slop" each appear in roughly 13% of on-topic posts, which puts the meta-complaint above every individual tell. Among specific features, shadcn/Tailwind defaults and the AI-purple gradient lead the comment-level ranking. The README lists the other named cues the skill targets: gradient hero text, unprompted neon glow, emoji used as icons, and the centered hero plus three cards layout.
The counterintuitive result is at the bottom. Bento grids, glassmorphism and aurora gradients, the patterns most often circulated as the stereotype, sit near the bottom or were rejected during verification. If your mental model of the AI look came from a meme, the data disagrees with it. The README also flags a newer pattern the skill handles: a cream, serif and sage combination it calls the tasteful default, which it characterizes as trading one default for another. That is a sharper observation than the ranking itself, because it names the failure mode of the fix.
Growth is measured as share of posts, not raw counts, precisely because raw counts track subreddit growth. On that basis the README reports the conversation jumping roughly 150x from 2023 to 2024, and notes it barely existed before 2024.
Where this study is weak and where the scanner is the wrong tool
The README states the central caveat itself: this is a proxy for vocal, online opinion, so trust the relative ordering more than the exact percentages. That is the correct way to read it, and it also bounds what the rankings can support. A tell that recurs across many threads ranks above one that spiked in a single viral thread, which is a sensible rule, but it means a genuinely common pattern that nobody bothers to complain about will not appear at all. Absence from the list is not evidence of safety.
The scanner inherits the lexicon's limits. It greps for patterns, so it will flag a deliberate gradient the same way it flags a reflexive one, and it cannot see layout. The README describes the centered-hero-plus-three-cards arrangement as a tell, but a grep-based scanner reading source files is a poor instrument for judging composition; the skill's audit mode is where that judgement is supposed to live. Treat the exit code as a prompt to look, not as a verdict.
There is also a scope mismatch worth naming. The study is about perception, what readers say when they see a site. The scanner is about source. A pattern can be loud in the first and invisible in the second, or the reverse. The animated demo in demo/demo.html, where the README says one prompt becomes four distinct deliberate designs that all pass the scanner, is the authors' answer to that gap: passing means the tells are gone, not that the design is good.
Alternatives: a linter, a design system, or the raw data
If you want a build-time check, an ordinary linter or a stylelint rule set is the closer comparison. Those enforce rules you wrote, and they are deterministic in the sense that the rule text is the specification. devibe_scan.py enforces a catalog derived from Reddit complaints, which means the rule text changes when the study is re-run and the specification is a distribution rather than a decision. Choose the linter when you know what you want; choose this when you want to know what other people are noticing.
If you want a house look, a design system or a component library is the right tool, and this repository explicitly is not one. The README's framing is that the skill removes tells and forces a deliberate, project-specific choice instead of imposing a look. That is a real difference in approach, not a slogan: a design system answers "what should this be", and this answers "what does this currently read as".
If you want the evidence rather than the tool, the raw files are the alternative to the skill. corpus.jsonl.gz holds the 46,971 on-topic posts, comments.jsonl holds the 3,033 comments, and the field list is id, subreddit, created_utc, score, title or selftext, body, permalink. The README states no usernames were collected, which makes the dataset easier to publish and means you cannot follow a thread back to a person. DATA_AND_GRAPHS.md carries the full master table, the growth table and the chart index if you would rather re-derive the ranking than accept it.
Maintenance, licence and what an upgrade costs
The last push to the default branch was on 2026-06-24, and the repository is not archived. There are no retrieved releases, so there is no versioned artifact to pin and no changelog to read between commits. The dependency surface is small: requirements.txt pins matplotlib>=3.5 and numpy>=1.20, and the README states everything else uses the Python standard library (urllib, json, csv, re, gzip). That is the whole third-party cost.
Upgrading is cheap in the mechanical sense and awkward in the interpretive one. Re-running the harvest scripts against Arctic Shift produces a new corpus, and the rankings will move, because the underlying conversation moves. Any CI threshold you set from the current comment_tell_counts.csv is a threshold against a snapshot, not a constant. The committed corpus.jsonl.gz exists so you can reproduce the published numbers without re-harvesting, which is the right default for a pipeline check.
The LICENSE file is present at the repository root, but the repository metadata reports the licence as NOASSERTION, meaning no standard identifier was detected. Read LICENSE directly before you redistribute the data or vendor the scanner; the field list and the no-usernames note tell you the authors thought about publication, but that is a description of the dataset, not a grant of rights.
Editorial conclusion
Adopt the scanner if you already run a CI lint step and want the AI-default look to fail a build rather than pass review, and read the comment-level ranking in comment_tell_counts.csv if you want to know which of your habits is loudest. Do not adopt it as a style guide: the repo says plainly that it does not impose a look, so a team looking for a house aesthetic will find nothing here, and the study is a proxy for vocal online opinion rather than a survey. Verify first that your project is not one where the flagged patterns are deliberate (a product that genuinely uses shadcn defaults, a gradient that encodes state), then run devibe_scan.py and read its findings before wiring the exit code into a required check.
Frequently asked questions
What makes something look vibe-coded?
According to the study, the loudest signal is recognizability rather than any single feature: "they all look the same" and "screams AI / slop" each appear in about 13% of on-topic posts. Among specific features, shadcn/Tailwind defaults and the AI-purple gradient lead the comment-level ranking, while bento grids, glassmorphism and aurora gradients sit near the bottom or were rejected.
What do vibe-coded websites look like?
The README lists the cues the unslop-ui skill targets: the default shadcn/Tailwind look, AI-purple gradients, gradient hero text, unprompted neon glow, emoji used as icons, and the centered hero plus three cards layout. It also names a newer pattern, a cream plus serif plus sage combination it calls the tasteful default.
How do I install the unslop-ui skill?
The README gives two paths: unzip skill/unslop-ui.skill into ~/.claude/skills/, or upload skill/unslop-ui.skill through the claude.ai skills UI. The same archive layout applies to the unslop-text and unslop-code skills.
Does vibecoded-design-tells need an API key to reproduce the study?
No. The README states everything is reproducible with Python and the standard library plus matplotlib, with no API key and no auth, using the free Arctic Shift archive. requirements.txt pins only matplotlib and numpy.
Can the devibe_scan.py scanner fail a CI build?
Yes. The README says the standalone scanner greps a codebase, prints findings with a vibe score, and gates CI on its exit code. The exact invocation is documented in skill/README.md rather than the top-level README.
Community notes