The old /skills was one long scrollable list. Replace it with a proper
app-shell layout: sticky left sidebar with every skill grouped by
category, main column on the right with an orientation piece (intro
+ 'how to pick one' callout + category sections with chip lists).
- scripts/build-sub-pages.js
- renderSkillsSidebar(): the sticky left rail used across the /skills
section. Takes an optional currentSkillId so we can mark the active
skill with aria-current when detail pages adopt the same shell in a
later commit
- renderSkillsOverviewMain(): the right column. Editorial header,
'how to pick one' callout that inlines 5 hot-link skill references,
then one block per category (title, count, description, chip row
of all skills in that category)
- wrapInDocsLayout(): tiny helper that pastes the sidebar and main
into a .skills-layout grid
- public/css/sub-pages.css
- Copy .skip-link a11y styles over from main.css so the 'Skip to
content' link is properly hidden until keyboard focus (was showing
unstyled at the top-left of every generated page)
- Add .skills-layout grid shell (260px sidebar + flex main column,
max-width 1400px, clamp-based horizontal padding)
- Add sticky .skills-sidebar with its own scroll-y overflow and a
thin scrollbar; group titles + mono link list; aria-current styling
with a 2px left accent bar
- Add .skills-overview-howto callout, category sections with chip
rows, and mobile collapse (sidebar becomes an inline block above
the main column at <=920px)
- Introduce --site-header-height and --skills-sidebar-width tokens
No detail page layout changes in this commit — those still use the
single-column .skill-detail shell.
Ships the first new sub-page section. Every user-invocable skill now has
its own page at /skills/{id}, with the canonical SKILL.md body rendered
via marked. The index at /skills lists all 21 skills grouped by category.
Editorial wrappers are opt-in: if content/site/skills/{id}.md exists, it
renders above the canonical body (with a "The skill itself" divider).
All 21 pages currently ship with the auto-rendered body only; hand-written
wrappers land in the next few commits.
- scripts/lib/sub-pages-data.js: builds the data model. Reuses
readSourceFiles() from lib/utils.js for skill content; parses the
ANTIPATTERNS array out of src/detect-antipatterns.mjs; reads optional
editorial wrappers from content/site/skills/*.md; validates that every
user-invocable skill has a category entry (build fails loudly if not).
- scripts/build-sub-pages.js: orchestrator. Writes generated HTML into
public/skills/*.html (gitignored). Called from both scripts/build.js
(before buildStaticSite) and server/index.js (at module load) so dev
and prod share the same generation code path.
- scripts/lib/render-page.js: new assetDepth parameter so generated
pages one level deep under public/ use relative paths (../favicon.svg,
../css/sub-pages.css) that Bun's HTML loader can resolve on disk.
- scripts/build.js: pass generated files into Bun.build entrypoints;
post-process to flatten build/public/* → build/* (Bun preserves the
public/ prefix when entrypoints span multiple depths).
- server/index.js: generateSubPages() runs at module load; new routes
/skills, /skills/:id, /anti-patterns, /tutorials, /tutorials/:slug
serve the pre-generated files via Bun.file().
- public/css/sub-pages.css: adds sub-page layout shell, skills index
grouped-list styling, skill detail header/meta chips/divider, collapsed
<details> reference sections, and a .prose block for rendered markdown
with editorial typography, code blocks, and inline code.
Verified: bun run build produces 26 HTML files (4 hand-authored + 22
generated), all flat under build/. Dev server returns 200 on /skills,
/skills/polish, /skills/impeccable, /skills/critique. Tests pass.
Every hand-authored HTML page now carries the same sticky top nav:
Home / Skills / Anti-Patterns / Tutorials / Gallery / GitHub. The three
future sections (skills, anti-patterns, tutorials) will land behind
these links in subsequent commits.
- Add <header class="site-header"> with a <!-- site-header v1 --> marker
to index, cheatsheet, gallery, privacy
- Each page links public/css/sub-pages.css so it picks up the shared
header styling (sticky, backdrop blur, accent-underlined current item)
- Gallery: drop the inline .site-header/.header-brand/.header-nav
definitions that predate the shared component (class names conflicted)
- Cheatsheet: restructure the page title into .cheatsheet-page-header
so it doesn't collide with the new <header class="site-header">; move
the page container max-width/padding off <body> onto .cheatsheet-page-header,
main, and footer so the shared sticky header spans the full viewport
- Privacy: full styling refresh using sub-pages.css tokens + a small
inline block for the page body typography
- Add a validateSiteHeader step to scripts/build.js that fails the build
if any of the four pages drops the marker
- Add /privacy route to server/index.js so extensionless URLs work
All four built pages pass the marker check; dev server serves all four
with 200 and the shared header.
Groundwork for new /skills, /anti-patterns, /tutorials sections.
No user-visible changes yet — this is pure plumbing.
- Split main.css into tokens.css (design tokens + reset, ~100 lines) and
main.css (everything else, imports tokens.css). Lets sub-pages import
only tokens without pulling in the landing-page component CSS.
- Add marked as a dependency.
- Add scripts/lib/render-markdown.js: marked wrapper with a custom link
resolver (skill slugs, reference/*.md anchors, external rel=noopener),
stable heading slugger, and terminal-style code blocks.
- Add scripts/lib/render-page.js: page shell wrapper that injects the
shared site header partial with aria-current marking.
- Add content/site/partials/header.html: shared site header with nav
(Home / Skills / Anti-Patterns / Tutorials / Gallery / GitHub).
- Add public/css/sub-pages.css: shared styles for generated pages, with
.site-header styling (sticky, backdrop blur, accent-underlined active
nav item) and mobile collapse.
Build still produces the same 104 KB landing-page CSS chunk; tests pass.
Tailwind was wired into the build but the project didn't actually use it:
no @tailwind/@theme/@apply directives in source CSS, no utility classes
in any HTML or JS, no tailwindcss dependency in package.json, and no
HTML page linked to the compiled styles.css output.
Bun's HTML loader already handles main.css's @import chain transparently
in both `bun run dev` and `bun run build`. Removing the Tailwind step:
- Deletes buildTailwindCSS() from scripts/build.js (and the now-unused
execSync import)
- Removes public/css/styles.css (dead compiled output that nothing read)
- Updates CLAUDE.md to drop the "must rebuild Tailwind after CSS edits"
instruction
Verified: `bun run build` produces the same 104 KB CSS chunk linked from
index.html via Bun's HTML loader. No more rebuild step after CSS edits.
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>
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>
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>
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>
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>
Major skill consolidation for v2.0:
- Rename source/skills/frontend-design/ to source/skills/impeccable/
with user-invocable: true and argument-hint: "[teach]"
- Fold teach-impeccable body into impeccable as "Teach Mode" section,
activated via /impeccable teach
- Create deprecation shims:
- frontend-design: redirects to /impeccable
- teach-impeccable: redirects to /impeccable teach
- Update all 16 skill cross-references from {{command_prefix}}frontend-design
to {{command_prefix}}impeccable and {{command_prefix}}teach-impeccable to
{{command_prefix}}impeccable teach
- Update CLI sentinel detection to use 'impeccable' (with teach-impeccable
as legacy fallback)
- Update build system readPatterns() path and EXCLUDED_FROM_SUGGESTIONS
- Update all public files (data.js, cheatsheet, index, viz, demos)
- Update all documentation (README, NOTICE, AGENTS, plugin.json)
- Update all test expectations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rename bin/impeccable.mjs to bin/impeccable (npm rejects .mjs in bin)
- Shebang: #!/usr/bin/env node (works without Bun)
- Add README.npm.md with CLI-focused docs, swapped in during publish
- Build browser script to source/ dir so URL scanning works in npm pkg
- Include browser script in files field
- Move website-only deps (archiver, motion, playwright) to devDependencies
- jsdom as dependency, puppeteer as optionalDependency
- Bump version to 2.0.1 across package.json, plugin.json, marketplace.json
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merges 54 commits from main including factory-based build system, Trae support,
improved skill descriptions, and security hardening. Consolidates the critique
skill to combine v2.0's sub-agent architecture and automated anti-pattern
detection with main's Nielsen heuristics scoring, cognitive load assessment,
persona-based testing, and structured follow-up workflow. Fixes browser detector
build to create target directory after skill sync.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merge main (factory refactor) and adapt Trae to use the config-driven
transformer system instead of a standalone trae.js file. Two provider
entries (trae-cn, trae) replace the custom dual-directory logic.
Also adds placeholderProvider support to the factory for providers that
share placeholder configs but need separate output directories.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Resolve conflict from codex.js (deleted in our branch, modified on main
for command_prefix). The command_prefix feature from main is preserved
in factory.js via PROVIDER_PLACEHOLDERS lookup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Research each harness's official documentation to verify and correct
provider frontmatter configs. Remove Codex/Gemini body transforms that
targeted their commands systems, not skills.
- Add compatibility + metadata to Cursor and Agents (Copilot)
- Add allowed-tools to Pi
- Remove Codex $ARGNAME and Gemini {{args}} body transforms
- Add HARNESSES.md as source of truth for harness capabilities
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes#67: argument-hint values starting with [ were parsed as YAML flow
sequences. Replace structured args arrays in source files with pre-formatted
argument-hint strings, and quote values starting with [ or { in
generateYamlFrontmatter().
Also consolidates 8 nearly-identical transformer files into a single
config-driven createTransformer() factory. Adding a new provider now
requires only a config object in providers.js instead of a full file.
- Replace args source frontmatter with argument-hint strings
- Add YAML quoting for values starting with [ or {
- Add quote stripping to parseFrontmatter() for round-trip support
- Create factory.js + providers.js, delete 8 individual transformers
- Replace 16 explicit build.js calls with a loop over PROVIDERS
- Consolidate 8 test files into 2 (factory + providers)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The build system hardcoded `/` as the command prefix for every provider,
but Codex CLI uses `$`. Added command_prefix to PROVIDER_PLACEHOLDERS
so replacePlaceholders and prefixSkillReferences use the right one.
Now `$normalize` shows up in Codex output instead of `/normalize`.
Previously only .claude/skills/ was synced from dist after build. Now
all 8 provider directories are synced (.claude, .cursor, .gemini, .codex,
.agents, .kiro, .opencode, .pi) so each provider's output can be tested
directly in this repo.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PR #50 fixed the output SKILL.md files but the source files, build
scripts, tests, docs, and server code still used the wrong spelling.
Claude Code expects `user-invocable` (with c) for slash command
autocomplete to work.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add {{scripts_path}} build placeholder that resolves per-provider
(${CLAUDE_PLUGIN_ROOT}/scripts for Claude Code, relative paths for others)
- Restructure critique into sub-agent architecture: LLM review and
detector run independently to avoid bias, results synthesized at end
- Browser overlay is now a visual aid for the user only -- agent reads
findings from console via [impeccable] prefix instead of scrolling
- Add scroll-to-top instruction before overlay injection
- Add allowed-tools frontmatter for detector bash commands
- Fix YAML parser to handle simple string arrays (not just - name: objects)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Output skills to both .trae-cn/ and .trae/ directories
- Update README with installation instructions for both versions
- Update DEVELOP.md with dual-variant documentation
- Add trae.js transformer with full metadata support (same as Claude Code)
- Update build.js to include Trae in provider transformations
- Update README.md with Trae installation instructions
- Update DEVELOP.md with Trae transformer documentation
Trae uses ~/.trae-cn/builtin_skills/ for skills installation.
Combine detect-antipatterns-core.mjs, detect-antipatterns.mjs, and
detect-antipatterns-browser-wrapper.js into a single universal file
that auto-detects browser vs Node via IS_BROWSER. Shared constants,
color utilities, and pure detection logic exist once instead of
being duplicated across files.
Build script simplified to strip @browser-strip-start/end markers,
set IS_BROWSER=true, and wrap in IIFE.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The skill sync wipes .claude/skills/ and re-copies from dist, deleting
the generated browser script. Moved build-browser-detector.js to run
AFTER the sync. Dev server's /js/* route now falls through to
.claude/skills/critique/scripts/ for built artifacts. All fixture HTML
references use /js/detect-antipatterns-browser.js (clean URL).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The generated browser detector now lives alongside the CLI script in
.claude/skills/critique/scripts/ — clearly a build artifact, not a
hand-maintained source file in public/js/.
- build-browser-detector.js outputs to .claude/ instead of public/js/
- Dev server serves .claude/skills/* for local testing
- All fixture and antipattern-example HTML files updated to new path
- Puppeteer detectUrl reads browser script from same directory
- Browser parity test server updated to serve from .claude/
- Deleted public/js/detect-antipatterns-browser.js
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DRY refactor:
- detect-antipatterns-core.mjs (297 lines): shared constants (SAFE_TAGS,
OVERUSED_FONTS, GENERIC_FONTS, ANTIPATTERNS), color utilities (parseRgb,
relativeLuminance, contrastRatio, hasChroma, getHue, colorToHex,
isNeutralColor), and pure detection functions (checkBorders, checkColors,
isCardLikeFromProps).
- CLI (889 lines, was 1212): imports from core, keeps jsdom-specific
resolveBackground, page-level analyzers, regex fallback, and CLI logic.
- Browser wrapper (335 lines): template with browser-specific DOM adapters,
highlighting, scan loop. Core is injected at build time.
- build-browser-detector.js: reads core, strips exports, injects into
wrapper, writes to public/js/detect-antipatterns-browser.js (generated).
- Build step added to scripts/build.js (runs before Bun bundling).
Source of truth for detection logic is now the core module. Browser script
is generated — do not edit public/js/detect-antipatterns-browser.js directly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Anti-pattern detector script (source/skills/critique/scripts/detect-antipatterns.mjs):
CLI tool that scans files/dirs for UI anti-patterns via regex. Detects side-tab
accent borders and border-accent-on-rounded patterns across Tailwind, CSS, JSX.
Context-aware: skips safe elements (blockquotes, nav, inputs, code), neutral
colors, and adjusts thresholds based on border-radius co-occurrence.
- Browser visualizer (public/js/detect-antipatterns-browser.js):
Drop-in script that highlights anti-patterns directly in the browser with
labeled overlays. Two modes: "static" (regex, matches CLI) and "computed"
(getComputedStyle, catches CSS cascade). Scans both inline styles and
<style> blocks.
- Gallery of Shame (public/gallery.html):
Standalone page showcasing 11 AI anti-pattern examples with thumbnails
and links. Anti-pattern example pages updated from 1080x1080 Twitter
format to responsive layouts, labels removed, screenshots retaken at 16:10.
- Critique skill updated to run detector before manual review.
- Build system: skills now support scripts/ directories alongside reference/.
All 8 provider transformers refactored to use shared.js (DRY).
- 58 new tests covering detection logic, fixtures, CLI integration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add first-class Pi (pi.dev) provider with transformer, tests, and build integration
- Fix CODEOWNERS username (@paulbakaus → @pbakaus)
- Add missing providers to issue/PR templates (Copilot, Kiro, OpenCode, Pi)
- Add Pi and OpenCode logos to homepage hero and install sections
- Move /onboard from "system" to "enhancement" category
- Update README and DEVELOP.md with all supported providers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Created opencode transformer in scripts/lib/transformers/opencode.js
- Added opencode placeholders to scripts/lib/utils.js
- Integrated opencode into build.js and universal assembly
- Updated README.md and scripts/lib/transformers/index.js with OpenCode support
Fix bug in Kiro transformer where commandNames was incorrectly passed
to replacePlaceholders for reference files. Add dedicated test suites
for Agents and Kiro transformers, and add unit tests for
replacePlaceholders and prefixSkillReferences utilities. (107 → 164 tests)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cloudflare Pages build environment doesn't have the zip CLI tool,
causing zip bundle creation to fail silently. Switched to the archiver
npm package for cross-platform zip generation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Without _routes.json, the SPA fallback was serving index.html instead of
invoking the download Functions, causing zip downloads to return HTML.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace Vercel serverless functions with Cloudflare Pages static
rewrites and lightweight download functions. Pre-generate all API
JSON data at build time for zero-invocation static serving. Also
fix stale simplify→distill rename in framework-viz periodic table.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Kiro transformer and build integration (.kiro/skills/ structure)
- Add Kiro to validation allowlists, API handlers, and homepage badge
- Replace legacy getFilePath in Vercel API with unified skills directory structure
- Remove individual provider ZIP creation (only universal ZIPs needed)
- Simplify bundle API allowlist to universal/universal-prefixed only
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Filter teach-impeccable from {{available_commands}} (setup skill, not a fix)
- Soften wording: "prefer" our commands but also allow other installed skills
the LLM is sure exist, preventing false negatives while still preventing
hallucinated commands
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>