The CLI command `npx impeccable detect src/` was promoted in the
"New!" callout but it scans static source files — that's a separate
feature, not visual mode. Replaces it with a "Get the Chrome
extension" CTA which is the actual way users get visual mode in
their browser.
Also updates the lead text to drop the /critique-specific framing
and reframes the second feature blurb to mention all three usage
modes (Chrome extension, /critique embed, npx impeccable live).
The .detection-cmd class is restyled from a code-block-with-arrow
to a proper link/button with hover state, since it's now a CTA
rather than a shell prompt.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The .mobile-commands-layout was rendering at ~2400px wide on mobile,
blowing out the entire .language-section to 2457px and causing the
section-lead text, the periodic table area, and everything else to
overflow the viewport horizontally.
Root cause: grid and flex items default to min-width: auto, which
lets them expand to fit any intrinsically wide descendant. The mobile
commands layout contains a .split-container (the demo split-compare
component) whose intrinsic content is ~2400px wide. That width
propagated up the parent chain — through .mobile-commands-layout
→ .commands-gallery → .commands-subsection → .language-content grid
track — and stretched the entire section.
Fix: cascade min-width: 0 through every descendant of the section so
the constraint stops the propagation at every layer.
.language-section,
.language-section * {
min-width: 0;
}
Verified at 390×844 (mobile): bodyScroll matches viewport, zero
overflowing elements, the line-length detector finding on
.mobile-cmd-desc is gone. Verified at 1280×800 (desktop): periodic
table and magazine layout still render at full content width with
no regression.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous footer split into two tiers with four different
interactive styles (plain underlined links, accent inline links,
round icon buttons, and pill CTAs with arrows). The hierarchy was
inverted — the loudest elements (Blog and Newsletter pills) were
secondary author plugs, while the actual primary nav was buried
as quiet underlined text.
Collapse to a single horizontal row with three groups:
- Impeccable wordmark anchored left
- 6 nav links centered in the middle column (auto / 1fr / auto grid)
- "Created by Paul Bakaus" + X + LinkedIn icons anchored right
Removed:
- Blog and Newsletter pill buttons
- Two vertical dividers between author elements
- Horizontal divider between the two former tiers
- The 36×36 round social-button background fill on hover
- Persistent underlines on all footer links
Interactive styles consolidated from 4 down to 2: plain text links
(nav + author credit) and inline icon links (socials). Both use the
same color → accent hover transition.
Mobile breakpoint reworked to stack the three groups in a single
centered column at 900px and below.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Hero demo card no longer uses <h3> for its title, fixing the
h1 → h3 skip in the document outline. The "after" card now uses
<p class="impeccable-title"> matching the structure of the
corresponding "before" slop-card (which already used a <div>).
- Constrains .changelog-items and .faq-answer to max-width: 70ch so
long bullet points and FAQ paragraphs don't exceed comfortable
reading length (was hitting ~135 chars/line).
- Bumps the destructive-action warning text in the /clarify command
demo from #a16207 to #854d0e on #fef3c7, lifting the contrast from
4.4:1 (just below WCAG AA) to ~6.4:1.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Overused-font check now measures actual computed-style usage across
text-bearing DOM elements instead of scanning CSS rules. A font is
only flagged as "primary" when it's used by ≥15% of text elements,
so demo/example classes that exist in the stylesheet but apply to
one tiny element no longer trigger false positives. The detail
message also includes the actual usage percentage.
- Same approach for the single-font check.
- Skipped-heading detail now includes the heading text on both sides
of the skip (e.g. <h1> "Title" followed by <h3> "Subtitle"), making
the offending element trivial to locate.
- Removes the 26-character truncation in TYPE_LABELS that cut long
anti-pattern names mid-word in overlay labels.
- Selector generator now uses class names + tag names and stops
walking up the DOM as soon as the partial selector uniquely matches
the target. Filters out CSS-in-JS hashed class names. Replaces ugly
6-level :nth-child chains with readable selectors like
`code.detection-cmd` or `#section > div > .card`.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The old rule used a fixed 8px floor on minPad, which produced false
positives on small inline pills (like the homepage's .detection-cmd
at 6px vertical / 14px horizontal on 13px font) and false negatives
on large text (a 24px heading with 8px padding all around passed
the floor but is genuinely too tight for the text size).
The new rule uses two independent axis thresholds that scale with
font-size:
vertical: max(4px, fontSize × 0.3)
horizontal: max(8px, fontSize × 0.5)
The asymmetry reflects typographic reality: line-height already
provides built-in vertical breathing room (the line box is taller
than the cap height), so vertical padding can be tighter than
horizontal. Both thresholds scale with font-size — bigger text
demands proportionally more padding.
Behavior changes
- Small inline pills with line-height-aware padding now pass
(.detection-cmd: V 6 ≥ 4, H 14 ≥ 8). The homepage CSS is unchanged.
- Cramped large text now flags (24px heading with 8px padding fails
H 8 < 12). The old rule missed this entirely.
- All original 8px-floor flag cases still flag — 4px on 14px text
is still 4 < 4.2 vertical, 2px is still cramped, etc.
- Snippet now indicates which axis failed and the specific threshold
for the font-size: "6px vertical padding (need ≥4.8px for 16px text)"
instead of the old "6px padding (need >=8px)".
Fixture
- tests/fixtures/antipatterns/cramped-padding.html is a new
comprehensive side-by-side fixture with 8 flag cases and 12 pass
cases spanning small pills, cards, code blocks, interactive
elements, and big text. Replaces the prior 3-case version.
Test
- tests/detect-antipatterns-browser.test.mjs asserts exactly 8
cramped-padding findings with detailed comments listing each
expected case and which axis fails.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Renames "Page:" to "URL:" in both single and multi-finding copy formats
- Strips URL fragment so the page identifier isn't an in-page anchor
- Prefixes suggested skills with a slash (e.g. /arrange, /polish) so
they're recognizable as Impeccable slash commands
- In multi-finding output, rolls up all suggested skills into a single
deduplicated, frequency-sorted footer line instead of repeating the
same skill on every finding
- Drops "Please fix this" prescriptive footer in favor of a neutral
"Skills are suggestions, not required" note
- Compacts each multi-finding line to single-line format
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The quality detection rules (line-length, cramped-padding, tight-leading,
tiny-text, justified-text, all-caps-body, wide-tracking, skipped-heading)
were originally added as browser-only and wired only into the overlay
loop. The CLI's jsdom path silently skipped all of them.
Two of the eight rules genuinely need real browser layout
(line-length reads rect.width for chars-per-line; cramped-padding reads
rect.width/height to filter small badges). The other six only need
computed CSS values and pure DOM walks — they can run in jsdom too.
Refactor
- Extract a pure checkQuality(opts) from checkElementQualityDOM, taking
pre-resolved lineHeightPx and letterSpacingPx so each adapter handles
its own unit resolution.
- Add resolveFontSizePx(el, win) — walks the parent chain to compute
effective font-size in pixels, handling px / rem / em / % through
inheritance. Browsers do this automatically in getComputedStyle, but
jsdom returns "0.875rem" verbatim, which broke naive parseFloat math.
- Add resolveLengthPx(value, fontSizePx) — generic CSS length → px
helper used for line-height and letter-spacing in the Node adapter.
- Extract checkPageQualityFromDoc(doc) and add a Node call site so
skipped-heading fires from the CLI too.
- Add checkElementQuality(el, style, tag, window) Node adapter and wire
it into detectHtml's element loop.
Tests
- New tests/detect-antipatterns-browser.test.mjs — Puppeteer-backed
runner that spins up a temporary static server (port 8765, mirrors
the dev server's /fixtures/* and /js/* routes) and uses detectUrl()
to load fixtures in headless Chrome. Asserts the two browser-only
rules (cramped-padding, line-length) that need real layout.
- New tests/fixtures/antipatterns/cramped-padding.html — focused
side-by-side fixture for the cramped-padding rule. Pass column
includes a faithful replica of .detection-cmd from the homepage
(the disputed "small inline pill" case the user is deciding what
to do with). Test asserts 3 findings: 2 from the obvious flag
column + 1 from the disputed pill.
- New tests/fixtures/antipatterns/quality.html — merged side-by-side
replacement for the orphaned quality-should-flag/pass.html files.
Covers all 7 typography-quality rules. The 6 jsdom-compatible rules
are asserted in the jsdom test; line-length stays in the Puppeteer
test.
- Delete the orphaned quality-should-flag.html / quality-should-pass.html.
- Wire the new browser test into bun run test (~2.6s overhead).
Coverage win: the CLI now catches tight-leading, tiny-text,
justified-text, all-caps-body, wide-tracking, and skipped-heading on
real projects, where it previously missed all six.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each problem-space fixture is now a single file with two columns: left
for cases that should flag, right for cases that should not. Matches the
icon-tile-stack convention and makes browser-based visual review easier.
The pass column proves that no false positives leak from look-alike
patterns next to the real anti-patterns.
Merged (4 pairs → 4 files)
- color-should-{flag,pass}.html → color.html
- motion-should-{flag,pass}.html → motion.html
- glow-should-{flag,pass}.html → glow.html
- layout-should-{flag,pass}.html → layout.html
Left untouched
- should-{flag,pass}.html — used by the CLI smoke tests in
detect-antipatterns.test.js, which need a known-clean fixture for the
exit-code-0 path.
- typography-should-{flag,pass}.html — all three typography rules
(overused-font, single-font, flat-type-hierarchy) are page-level and
fundamentally can't share a page with their pass cases. Loading two
font stacks suppresses single-font; varied sizes suppress flat-type-
hierarchy. Documented in the test file.
Test calibration
- Hardcoded the jsdom finding counts (motion: 2 bounce + 2 layout-
transition; glow: 1 dark-glow). Real browser sees more because
jsdom doesn't fully apply class-based styles, but the pass-column
count is reliably 0. Browser-verified all 4 fixtures show expected
flag counts and zero pass-column false positives.
Fixture chrome fixes
- Sub-section labels (.col h3) now use #64748b instead of #94a3b8 so
the fixture's own UI doesn't trigger low-contrast. glow.html got a
CSS restructure into card-dark/card-light/card-medium variants so
every text/background pairing meets WCAG AA. layout.html's "card
with image" gradient changed from blue→purple to amber→rose so it
doesn't trip ai-color-palette.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removes the 26-character truncation in TYPE_LABELS that cut off long
anti-pattern names mid-word (e.g. "icon tile stacked above heading"
became "icon tile stacked above he"). The label is sized by content
via white-space: nowrap so it grows to fit, and multi-finding overlays
that exceed the outline width already fall back to the cycling UI.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A new icon-tile-stack detection (the canonical AI feature-card with a
small rounded-square icon container above a heading), backed by a
two-column TDD fixture, plus a single-source-of-truth design that ties
the engine to the impeccable skill so they can no longer drift silently.
Detection
- New icon-tile-stack rule (slop): heading's previousElementSibling is
a 32–128px rounded-square element with a non-transparent background
or border, contains an svg/icon-i child, and sits above (not next to)
the heading. Excludes round avatars, wide thumbnails, side-by-side
layouts, tiny icons, and hero images.
- Two-column fixture convention: a single icon-tile-stack.html with a
flag column (4 cases) and pass column (6 cases), with snippet-text
matching used by the fixture test.
Single source of truth
- Each ANTIPATTERNS entry can now declare skillSection + skillGuideline.
18 of 25 rules carry these fields; the build's new
validateAntipatternRules() in scripts/build.js fails if any declared
skillGuideline isn't found verbatim in the right SKILL.md section.
- scripts/build-extension.js now includes the description field in
extension/detector/antipatterns.json (it was previously dropped).
- The existing count validator was promoted from warn to error so
command count drift fails the build the same way detection drift does.
Impeccable skill DON'Ts
- Added 4 new top-level DON'Ts that target real default AI behavior:
single-font, flat-type-hierarchy, all-caps-body, line-length.
- Cut 7 new DON'Ts I had drafted (tight-leading, tiny-text, wide-tracking,
justified-text, low-contrast, cramped-padding, skipped-heading) because
they teach things every model already knows from CSS/a11y basics. The
detector still catches all of them.
Stale count cleanup
- 22 commands → 21 across 17 references in HTML, README, NOTICE, AGENTS,
plugin.json, marketplace.json (left over from the validate skill removal).
- Dropped the hand-coded "212 design guidelines" marketing copy on the
homepage, which never mapped to any real count.
Sub-agent
- New private .claude/agents/anti-patterns.md captures the full TDD
recipe, schema, plug-in points, jsdom constraints, and pre-commit
checklist so future sessions can add rules end-to-end without
re-investigating the wiring.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds the three /impeccable usage modes (freeform, teach, craft) to the
command demo, with a clearer multi-pane layout. Also tightens the
commands grid spacing on the site and refreshes the framework viz and
glass terminal styles for consistency.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updates the per-provider built skill files (.agents/, .claude/, .codex/,
.cursor/, .gemini/, .kiro/, .opencode/, .pi/, .rovodev/, .trae-cn/, .trae/)
to reflect the source removal of the /validate skill: deletes the
validate/SKILL.md output across all providers, drops /validate from the
command lists in audit and critique, and updates the impeccable craft
reference.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously checkColors bailed out whenever an ancestor used a gradient
background, since resolveBackground returned null. As a result, gray or
low-contrast text inside any gradient container was completely invisible
to both rules — e.g. the gray heading on bad-contrast.html.
Add a resolveGradientStops fallback that walks parents for gradient
stops and runs contrast against the worst-case stop, plus gray-on-color
when every stop is chromatic. parseGradientColors now also accepts hex
so jsdom fixtures with raw inline gradients work too. Extended the
color-should-flag fixture and tests to cover the gradient case.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Refactors the extension for on-demand injection (no static content_scripts
entry — content script and detector are loaded only when the user actively
opens the Impeccable panel, sidebar pane, or popup). Adds a new "Auto-scan"
preference (default: scan when the Impeccable panel opens, opt-in: scan
when DevTools opens) plus configurable line length (strict/lax) and
highlight blur on/off settings. Adds an Elements panel sidebar that shows
findings for the currently selected element.
Includes substantial overlay UX work: page-pixel-perfect spotlight mask
via clip-path, refined hover/dim states, instant transitions for snappier
feel, copy buttons for findings, hover-from-panel highlighting, and a
brand-aware exception list so the font check no longer flags Roboto on
Google's own properties.
Robustness fixes for the MV3 service worker lifecycle: heartbeat keepalive
plus auto-reconnecting ports across panel/sidebar/devtools so transient
SW restarts don't break the panel UI, and immediate teardown on DevTools
close (replacing an unreliable setTimeout-based defer that didn't survive
SW termination).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a Manifest V3 Chrome extension that injects the detector when
DevTools opens, with a dedicated panel for browsing findings, a toolbar
popup for quick scan/toggle, and per-rule settings synced via
chrome.storage. Categorizes anti-patterns into AI slop vs quality
issues with visual differentiation (sparkle prefix, panel grouping).
Overlay labels are polished with flush positioning, cycling for
multi-finding elements, and synchronized hover darkening.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove redundant "Commands in Action" heading, replace with subtle hint
- Fix double spacing between section lead and periodic table
- Tighten grid gaps for more cohesive layout
- Update GitHub star count from 13.3k to 16k
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace freelance "Work with me" with "Work with us" for Renaissance Geek
- Update contact email to paul@renaissance-geek.ai
- Simplify FAQ: everything is Apache 2.0
- Remove terminal license labels and tip button
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merges the impeccable-detect CLI repo (pbakaus/impeccable-cli@831a6cc)
into this repo. The BSL-1.1 license that motivated the split is gone;
everything is now Apache 2.0.
- Add bin/, src/, detection tests and fixtures from CLI repo
- Merge package.json: name → "impeccable", add bin/exports/files fields
- Internal refs now read from local src/ instead of node_modules/
- Update SPDX headers, NOTICE.md, CLAUDE.md, FAQ, npm README
- Add prepack/postpack scripts for CLI-focused README on npm
- Remove terminal license labels (no longer needed)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows "Apache 2.0" and "BSL-1.1 · Free for individuals and small teams"
right-aligned in the glass terminal title bars.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rename /craft skill to /shape and make it planning-only (no code output)
- Add /impeccable craft sub-command that calls /shape, loads references,
builds with visual iteration until delightful
- Replace all " -- " (em dash substitutes) with proper punctuation across
all skill files and index.html
- Move v1.6 changelog entry to "View older releases" section
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Simplify the licensing FAQ (no more CLI-calls-engine indirection).
Merge v2.0.0 and v2.0.6 changelog entries into one v2.0 release note
covering the full detection engine, CLI, framework support, and critique
overhaul.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The CLI and detection engine now live in pbakaus/impeccable-detect
(published as 'impeccable' on npm, BSL-1.1). This repo is purely
Apache 2.0: skills, prompts, website, and build system.
- Remove bin/ (CLI moved to CLI repo)
- Remove README.npm.md (moved to CLI repo)
- Remove @impeccable/detect dependency, add impeccable dependency
- Set package.json to private (no longer published to npm)
- Update all references from @impeccable/detect to impeccable
- Update CLAUDE.md, NOTICE.md, FAQ, and changelog
- Rebuild all provider skill distributions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Disclose that @impeccable/detect (BSL-1.1) is a transitive dependency
of this Apache 2.0 project, with a summary of the license terms.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace local detection engine dependency with @impeccable/detect (BSL-1.1
licensed, github:pbakaus/impeccable-detect). The main CLI now delegates
both `detect` and `live` commands to the external package.
Update critique skill to use `npx @impeccable/detect live` instead of
python3 http.server for serving the browser detection overlay.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add interactive confirmation when scanning directories with 50+ files,
warning about jsdom overhead for HTML files and suggesting --fast or
targeting a subdirectory. Auto-skipped in non-TTY (piped/CI) contexts.
Update CLAUDE.md and README.md to use node/npx instead of bun for the
detect CLI, since bun's jsdom is extremely slow and causes scans to hang.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tier 1: Add Vue/Svelte <style> block extraction and CSS-in-JS template literal
detection (styled-components, emotion) so anti-patterns inside framework-specific
syntax are caught. Enable multi-line context for CSS files so cross-line patterns
like gradient-text are detected.
Tier 2: Build a lightweight import graph when scanning directories. Findings are
annotated with importedBy context (e.g. "imported by App.tsx") in both human and
JSON output.
Tier 3: Detect framework config files (Next.js, Vite, SvelteKit, Nuxt, Astro,
Angular, Remix), probe the dev server port with HTTP fingerprinting to distinguish
the expected framework from unrelated services, and suggest URL-based scanning for
more accurate results.
Adds realistic Next.js project fixtures (Tailwind, CSS Modules, styled-components)
plus Vue, Svelte, JSX, and CSS-in-JS unit fixtures. 158 tests, 356 assertions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Switch staircase to grid at 1200px (was 1024px) to prevent tall
stairs from clipping at narrow desktop widths
- Add 2-col grid at 768px, compact horizontal cards at 520px
- Fix count crowding heading: use overflow hidden to gracefully
hide count when card is too narrow instead of wrapping or cramming
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each of the 7 dimension icons now has a continuous subtle animation
(breathing draws, pulsing circles, bobbing ball, blinking cursor,
toggle wobble) plus an enhanced hover effect. Responsive icon uses
transform-box: fill-box for a staggered desktop-to-mobile reflow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Build system now computes authoritative counts from source (22 commands,
24 detection rules) and warns about mismatches in HTML, README, plugin
configs. Generates public/js/generated/counts.js for frontend use.
Fixed 15 stale references across index.html, cheatsheet.html, README.md,
NOTICE.md, AGENTS.md, plugin.json, and marketplace.json. Changed all
"20 commands" to "22", "25 rules" to "24". Fixed v1.6.0 changelog date
(was March 24, after v2.0.0's March 20; now March 18).
Changelog entries are excluded from validation since historical counts
were correct at time of release.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reverts Codex's overly bureaucratic sub-agent delegation changes (permission
prompts, "not fully compliant" disclaimers) back to clear, practical language.
Uses RFC-style SHOULD for sub-agent delegation with named examples for both
Claude Code (Agent tool) and Codex (natural language spawning).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>