@booklib/core 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/booklib-standards.mdc +40 -0
- package/.gemini/context.md +372 -0
- package/AGENTS.md +166 -0
- package/CHANGELOG.md +226 -0
- package/CLAUDE.md +81 -0
- package/CODE_OF_CONDUCT.md +31 -0
- package/CONTRIBUTING.md +304 -0
- package/LICENSE +21 -0
- package/PLAN.md +28 -0
- package/README.ja.md +198 -0
- package/README.ko.md +198 -0
- package/README.md +503 -0
- package/README.pt-BR.md +198 -0
- package/README.uk.md +241 -0
- package/README.zh-CN.md +198 -0
- package/SECURITY.md +9 -0
- package/agents/architecture-reviewer.md +136 -0
- package/agents/booklib-reviewer.md +90 -0
- package/agents/data-reviewer.md +107 -0
- package/agents/jvm-reviewer.md +146 -0
- package/agents/python-reviewer.md +128 -0
- package/agents/rust-reviewer.md +115 -0
- package/agents/ts-reviewer.md +110 -0
- package/agents/ui-reviewer.md +117 -0
- package/assets/logo.svg +36 -0
- package/bin/booklib-mcp.js +304 -0
- package/bin/booklib.js +1705 -0
- package/bin/skills.cjs +1292 -0
- package/booklib-router.mdc +36 -0
- package/booklib.config.json +19 -0
- package/commands/animation-at-work.md +10 -0
- package/commands/clean-code-reviewer.md +10 -0
- package/commands/data-intensive-patterns.md +10 -0
- package/commands/data-pipelines.md +10 -0
- package/commands/design-patterns.md +10 -0
- package/commands/domain-driven-design.md +10 -0
- package/commands/effective-java.md +10 -0
- package/commands/effective-kotlin.md +10 -0
- package/commands/effective-python.md +10 -0
- package/commands/effective-typescript.md +10 -0
- package/commands/kotlin-in-action.md +10 -0
- package/commands/lean-startup.md +10 -0
- package/commands/microservices-patterns.md +10 -0
- package/commands/programming-with-rust.md +10 -0
- package/commands/refactoring-ui.md +10 -0
- package/commands/rust-in-action.md +10 -0
- package/commands/skill-router.md +10 -0
- package/commands/spring-boot-in-action.md +10 -0
- package/commands/storytelling-with-data.md +10 -0
- package/commands/system-design-interview.md +10 -0
- package/commands/using-asyncio-python.md +10 -0
- package/commands/web-scraping-python.md +10 -0
- package/community/registry.json +1616 -0
- package/hooks/hooks.json +23 -0
- package/hooks/posttooluse-capture.mjs +67 -0
- package/hooks/suggest.js +153 -0
- package/lib/agent-behaviors.js +40 -0
- package/lib/agent-detector.js +96 -0
- package/lib/config-loader.js +39 -0
- package/lib/conflict-resolver.js +148 -0
- package/lib/context-builder.js +574 -0
- package/lib/discovery-engine.js +298 -0
- package/lib/doctor/hook-installer.js +83 -0
- package/lib/doctor/usage-tracker.js +87 -0
- package/lib/engine/ai-features.js +253 -0
- package/lib/engine/auditor.js +103 -0
- package/lib/engine/bm25-index.js +178 -0
- package/lib/engine/capture.js +120 -0
- package/lib/engine/corrections.js +198 -0
- package/lib/engine/doctor.js +195 -0
- package/lib/engine/graph-injector.js +137 -0
- package/lib/engine/graph.js +161 -0
- package/lib/engine/handoff.js +405 -0
- package/lib/engine/indexer.js +242 -0
- package/lib/engine/parser.js +53 -0
- package/lib/engine/query-expander.js +42 -0
- package/lib/engine/reranker.js +40 -0
- package/lib/engine/rrf.js +59 -0
- package/lib/engine/scanner.js +151 -0
- package/lib/engine/searcher.js +139 -0
- package/lib/engine/session-coordinator.js +306 -0
- package/lib/engine/session-manager.js +429 -0
- package/lib/engine/synthesizer.js +70 -0
- package/lib/installer.js +70 -0
- package/lib/instinct-block.js +33 -0
- package/lib/mcp-config-writer.js +88 -0
- package/lib/paths.js +57 -0
- package/lib/profiles/design.md +19 -0
- package/lib/profiles/general.md +16 -0
- package/lib/profiles/research-analysis.md +22 -0
- package/lib/profiles/software-development.md +23 -0
- package/lib/profiles/writing-content.md +19 -0
- package/lib/project-initializer.js +916 -0
- package/lib/registry/skills.js +102 -0
- package/lib/registry-searcher.js +99 -0
- package/lib/rules/rules-manager.js +169 -0
- package/lib/skill-fetcher.js +333 -0
- package/lib/well-known-builder.js +70 -0
- package/lib/wizard/index.js +404 -0
- package/lib/wizard/integration-detector.js +41 -0
- package/lib/wizard/project-detector.js +100 -0
- package/lib/wizard/prompt.js +156 -0
- package/lib/wizard/registry-embeddings.js +107 -0
- package/lib/wizard/skill-recommender.js +69 -0
- package/llms-full.txt +254 -0
- package/llms.txt +70 -0
- package/package.json +45 -0
- package/research-reports/2026-04-01-current-architecture.md +160 -0
- package/research-reports/IDEAS.md +93 -0
- package/rules/common/clean-code.md +42 -0
- package/rules/java/effective-java.md +42 -0
- package/rules/kotlin/effective-kotlin.md +37 -0
- package/rules/python/effective-python.md +38 -0
- package/rules/rust/rust.md +37 -0
- package/rules/typescript/effective-typescript.md +42 -0
- package/scripts/gen-llms-full.mjs +36 -0
- package/scripts/gen-og.mjs +142 -0
- package/scripts/validate-frontmatter.js +25 -0
- package/skills/animation-at-work/SKILL.md +270 -0
- package/skills/animation-at-work/assets/example_asset.txt +1 -0
- package/skills/animation-at-work/evals/evals.json +44 -0
- package/skills/animation-at-work/evals/results.json +13 -0
- package/skills/animation-at-work/examples/after.md +64 -0
- package/skills/animation-at-work/examples/before.md +35 -0
- package/skills/animation-at-work/references/api_reference.md +369 -0
- package/skills/animation-at-work/references/review-checklist.md +79 -0
- package/skills/animation-at-work/scripts/audit_animations.py +295 -0
- package/skills/animation-at-work/scripts/example.py +1 -0
- package/skills/clean-code-reviewer/SKILL.md +444 -0
- package/skills/clean-code-reviewer/audit.json +35 -0
- package/skills/clean-code-reviewer/evals/evals.json +185 -0
- package/skills/clean-code-reviewer/evals/results.json +13 -0
- package/skills/clean-code-reviewer/examples/after.md +48 -0
- package/skills/clean-code-reviewer/examples/before.md +33 -0
- package/skills/clean-code-reviewer/references/api_reference.md +158 -0
- package/skills/clean-code-reviewer/references/practices-catalog.md +282 -0
- package/skills/clean-code-reviewer/references/review-checklist.md +254 -0
- package/skills/clean-code-reviewer/scripts/pre-review.py +206 -0
- package/skills/data-intensive-patterns/SKILL.md +267 -0
- package/skills/data-intensive-patterns/assets/example_asset.txt +1 -0
- package/skills/data-intensive-patterns/evals/evals.json +54 -0
- package/skills/data-intensive-patterns/evals/results.json +13 -0
- package/skills/data-intensive-patterns/examples/after.md +61 -0
- package/skills/data-intensive-patterns/examples/before.md +38 -0
- package/skills/data-intensive-patterns/references/api_reference.md +34 -0
- package/skills/data-intensive-patterns/references/patterns-catalog.md +551 -0
- package/skills/data-intensive-patterns/references/review-checklist.md +193 -0
- package/skills/data-intensive-patterns/scripts/adr.py +213 -0
- package/skills/data-intensive-patterns/scripts/example.py +1 -0
- package/skills/data-pipelines/SKILL.md +259 -0
- package/skills/data-pipelines/assets/example_asset.txt +1 -0
- package/skills/data-pipelines/evals/evals.json +45 -0
- package/skills/data-pipelines/evals/results.json +13 -0
- package/skills/data-pipelines/examples/after.md +97 -0
- package/skills/data-pipelines/examples/before.md +37 -0
- package/skills/data-pipelines/references/api_reference.md +301 -0
- package/skills/data-pipelines/references/review-checklist.md +181 -0
- package/skills/data-pipelines/scripts/example.py +1 -0
- package/skills/data-pipelines/scripts/new_pipeline.py +444 -0
- package/skills/design-patterns/SKILL.md +271 -0
- package/skills/design-patterns/assets/example_asset.txt +1 -0
- package/skills/design-patterns/evals/evals.json +46 -0
- package/skills/design-patterns/evals/results.json +13 -0
- package/skills/design-patterns/examples/after.md +52 -0
- package/skills/design-patterns/examples/before.md +29 -0
- package/skills/design-patterns/references/api_reference.md +1 -0
- package/skills/design-patterns/references/patterns-catalog.md +726 -0
- package/skills/design-patterns/references/review-checklist.md +173 -0
- package/skills/design-patterns/scripts/example.py +1 -0
- package/skills/design-patterns/scripts/scaffold.py +807 -0
- package/skills/domain-driven-design/SKILL.md +142 -0
- package/skills/domain-driven-design/assets/example_asset.txt +1 -0
- package/skills/domain-driven-design/evals/evals.json +48 -0
- package/skills/domain-driven-design/evals/results.json +13 -0
- package/skills/domain-driven-design/examples/after.md +80 -0
- package/skills/domain-driven-design/examples/before.md +43 -0
- package/skills/domain-driven-design/references/api_reference.md +1 -0
- package/skills/domain-driven-design/references/patterns-catalog.md +545 -0
- package/skills/domain-driven-design/references/review-checklist.md +158 -0
- package/skills/domain-driven-design/scripts/example.py +1 -0
- package/skills/domain-driven-design/scripts/scaffold.py +421 -0
- package/skills/effective-java/SKILL.md +227 -0
- package/skills/effective-java/assets/example_asset.txt +1 -0
- package/skills/effective-java/evals/evals.json +46 -0
- package/skills/effective-java/evals/results.json +13 -0
- package/skills/effective-java/examples/after.md +83 -0
- package/skills/effective-java/examples/before.md +37 -0
- package/skills/effective-java/references/api_reference.md +1 -0
- package/skills/effective-java/references/items-catalog.md +955 -0
- package/skills/effective-java/references/review-checklist.md +216 -0
- package/skills/effective-java/scripts/checkstyle_setup.py +211 -0
- package/skills/effective-java/scripts/example.py +1 -0
- package/skills/effective-kotlin/SKILL.md +271 -0
- package/skills/effective-kotlin/assets/example_asset.txt +1 -0
- package/skills/effective-kotlin/audit.json +29 -0
- package/skills/effective-kotlin/evals/evals.json +45 -0
- package/skills/effective-kotlin/evals/results.json +13 -0
- package/skills/effective-kotlin/examples/after.md +36 -0
- package/skills/effective-kotlin/examples/before.md +38 -0
- package/skills/effective-kotlin/references/api_reference.md +1 -0
- package/skills/effective-kotlin/references/practices-catalog.md +1228 -0
- package/skills/effective-kotlin/references/review-checklist.md +126 -0
- package/skills/effective-kotlin/scripts/example.py +1 -0
- package/skills/effective-python/SKILL.md +441 -0
- package/skills/effective-python/evals/evals.json +44 -0
- package/skills/effective-python/evals/results.json +13 -0
- package/skills/effective-python/examples/after.md +56 -0
- package/skills/effective-python/examples/before.md +40 -0
- package/skills/effective-python/ref-01-pythonic-thinking.md +202 -0
- package/skills/effective-python/ref-02-lists-and-dicts.md +146 -0
- package/skills/effective-python/ref-03-functions.md +186 -0
- package/skills/effective-python/ref-04-comprehensions-generators.md +211 -0
- package/skills/effective-python/ref-05-classes-interfaces.md +188 -0
- package/skills/effective-python/ref-06-metaclasses-attributes.md +209 -0
- package/skills/effective-python/ref-07-concurrency.md +213 -0
- package/skills/effective-python/ref-08-robustness-performance.md +248 -0
- package/skills/effective-python/ref-09-testing-debugging.md +253 -0
- package/skills/effective-python/ref-10-collaboration.md +175 -0
- package/skills/effective-python/references/api_reference.md +218 -0
- package/skills/effective-python/references/practices-catalog.md +483 -0
- package/skills/effective-python/references/review-checklist.md +190 -0
- package/skills/effective-python/scripts/lint.py +173 -0
- package/skills/effective-typescript/SKILL.md +262 -0
- package/skills/effective-typescript/audit.json +29 -0
- package/skills/effective-typescript/evals/evals.json +37 -0
- package/skills/effective-typescript/evals/results.json +13 -0
- package/skills/effective-typescript/examples/after.md +70 -0
- package/skills/effective-typescript/examples/before.md +47 -0
- package/skills/effective-typescript/references/api_reference.md +118 -0
- package/skills/effective-typescript/references/practices-catalog.md +371 -0
- package/skills/effective-typescript/scripts/review.py +169 -0
- package/skills/kotlin-in-action/SKILL.md +261 -0
- package/skills/kotlin-in-action/assets/example_asset.txt +1 -0
- package/skills/kotlin-in-action/evals/evals.json +43 -0
- package/skills/kotlin-in-action/evals/results.json +13 -0
- package/skills/kotlin-in-action/examples/after.md +53 -0
- package/skills/kotlin-in-action/examples/before.md +39 -0
- package/skills/kotlin-in-action/references/api_reference.md +1 -0
- package/skills/kotlin-in-action/references/practices-catalog.md +436 -0
- package/skills/kotlin-in-action/references/review-checklist.md +204 -0
- package/skills/kotlin-in-action/scripts/example.py +1 -0
- package/skills/kotlin-in-action/scripts/setup_detekt.py +224 -0
- package/skills/lean-startup/SKILL.md +160 -0
- package/skills/lean-startup/assets/example_asset.txt +1 -0
- package/skills/lean-startup/evals/evals.json +43 -0
- package/skills/lean-startup/evals/results.json +13 -0
- package/skills/lean-startup/examples/after.md +80 -0
- package/skills/lean-startup/examples/before.md +34 -0
- package/skills/lean-startup/references/api_reference.md +319 -0
- package/skills/lean-startup/references/review-checklist.md +137 -0
- package/skills/lean-startup/scripts/example.py +1 -0
- package/skills/lean-startup/scripts/new_experiment.py +286 -0
- package/skills/microservices-patterns/SKILL.md +384 -0
- package/skills/microservices-patterns/evals/evals.json +45 -0
- package/skills/microservices-patterns/evals/results.json +13 -0
- package/skills/microservices-patterns/examples/after.md +69 -0
- package/skills/microservices-patterns/examples/before.md +40 -0
- package/skills/microservices-patterns/references/patterns-catalog.md +391 -0
- package/skills/microservices-patterns/references/review-checklist.md +169 -0
- package/skills/microservices-patterns/scripts/new_service.py +583 -0
- package/skills/programming-with-rust/SKILL.md +209 -0
- package/skills/programming-with-rust/evals/evals.json +37 -0
- package/skills/programming-with-rust/evals/results.json +13 -0
- package/skills/programming-with-rust/examples/after.md +107 -0
- package/skills/programming-with-rust/examples/before.md +59 -0
- package/skills/programming-with-rust/references/api_reference.md +152 -0
- package/skills/programming-with-rust/references/practices-catalog.md +335 -0
- package/skills/programming-with-rust/scripts/review.py +142 -0
- package/skills/refactoring-ui/SKILL.md +362 -0
- package/skills/refactoring-ui/assets/example_asset.txt +1 -0
- package/skills/refactoring-ui/evals/evals.json +45 -0
- package/skills/refactoring-ui/evals/results.json +13 -0
- package/skills/refactoring-ui/examples/after.md +85 -0
- package/skills/refactoring-ui/examples/before.md +58 -0
- package/skills/refactoring-ui/references/api_reference.md +355 -0
- package/skills/refactoring-ui/references/review-checklist.md +114 -0
- package/skills/refactoring-ui/scripts/audit_css.py +250 -0
- package/skills/refactoring-ui/scripts/example.py +1 -0
- package/skills/rust-in-action/SKILL.md +350 -0
- package/skills/rust-in-action/evals/evals.json +38 -0
- package/skills/rust-in-action/evals/results.json +13 -0
- package/skills/rust-in-action/examples/after.md +156 -0
- package/skills/rust-in-action/examples/before.md +56 -0
- package/skills/rust-in-action/references/practices-catalog.md +346 -0
- package/skills/rust-in-action/scripts/review.py +147 -0
- package/skills/skill-router/SKILL.md +186 -0
- package/skills/skill-router/evals/evals.json +38 -0
- package/skills/skill-router/evals/results.json +13 -0
- package/skills/skill-router/examples/after.md +63 -0
- package/skills/skill-router/examples/before.md +39 -0
- package/skills/skill-router/references/api_reference.md +24 -0
- package/skills/skill-router/references/routing-heuristics.md +89 -0
- package/skills/skill-router/references/skill-catalog.md +174 -0
- package/skills/skill-router/scripts/route.py +266 -0
- package/skills/spring-boot-in-action/SKILL.md +340 -0
- package/skills/spring-boot-in-action/evals/evals.json +39 -0
- package/skills/spring-boot-in-action/evals/results.json +13 -0
- package/skills/spring-boot-in-action/examples/after.md +185 -0
- package/skills/spring-boot-in-action/examples/before.md +84 -0
- package/skills/spring-boot-in-action/references/practices-catalog.md +403 -0
- package/skills/spring-boot-in-action/scripts/review.py +184 -0
- package/skills/storytelling-with-data/SKILL.md +241 -0
- package/skills/storytelling-with-data/assets/example_asset.txt +1 -0
- package/skills/storytelling-with-data/evals/evals.json +47 -0
- package/skills/storytelling-with-data/evals/results.json +13 -0
- package/skills/storytelling-with-data/examples/after.md +50 -0
- package/skills/storytelling-with-data/examples/before.md +33 -0
- package/skills/storytelling-with-data/references/api_reference.md +379 -0
- package/skills/storytelling-with-data/references/review-checklist.md +111 -0
- package/skills/storytelling-with-data/scripts/chart_review.py +301 -0
- package/skills/storytelling-with-data/scripts/example.py +1 -0
- package/skills/system-design-interview/SKILL.md +233 -0
- package/skills/system-design-interview/assets/example_asset.txt +1 -0
- package/skills/system-design-interview/evals/evals.json +46 -0
- package/skills/system-design-interview/evals/results.json +13 -0
- package/skills/system-design-interview/examples/after.md +94 -0
- package/skills/system-design-interview/examples/before.md +27 -0
- package/skills/system-design-interview/references/api_reference.md +582 -0
- package/skills/system-design-interview/references/review-checklist.md +201 -0
- package/skills/system-design-interview/scripts/example.py +1 -0
- package/skills/system-design-interview/scripts/new_design.py +421 -0
- package/skills/using-asyncio-python/SKILL.md +290 -0
- package/skills/using-asyncio-python/assets/example_asset.txt +1 -0
- package/skills/using-asyncio-python/evals/evals.json +43 -0
- package/skills/using-asyncio-python/evals/results.json +13 -0
- package/skills/using-asyncio-python/examples/after.md +68 -0
- package/skills/using-asyncio-python/examples/before.md +39 -0
- package/skills/using-asyncio-python/references/api_reference.md +267 -0
- package/skills/using-asyncio-python/references/review-checklist.md +149 -0
- package/skills/using-asyncio-python/scripts/check_blocking.py +270 -0
- package/skills/using-asyncio-python/scripts/example.py +1 -0
- package/skills/web-scraping-python/SKILL.md +280 -0
- package/skills/web-scraping-python/assets/example_asset.txt +1 -0
- package/skills/web-scraping-python/evals/evals.json +46 -0
- package/skills/web-scraping-python/evals/results.json +13 -0
- package/skills/web-scraping-python/examples/after.md +109 -0
- package/skills/web-scraping-python/examples/before.md +40 -0
- package/skills/web-scraping-python/references/api_reference.md +393 -0
- package/skills/web-scraping-python/references/review-checklist.md +163 -0
- package/skills/web-scraping-python/scripts/example.py +1 -0
- package/skills/web-scraping-python/scripts/new_scraper.py +231 -0
- package/skills/writing-plans/audit.json +34 -0
- package/tests/agent-detector.test.js +83 -0
- package/tests/corrections.test.js +245 -0
- package/tests/doctor/hook-installer.test.js +72 -0
- package/tests/doctor/usage-tracker.test.js +140 -0
- package/tests/engine/benchmark-eval.test.js +31 -0
- package/tests/engine/bm25-index.test.js +85 -0
- package/tests/engine/capture-command.test.js +35 -0
- package/tests/engine/capture.test.js +17 -0
- package/tests/engine/graph-augmented-search.test.js +107 -0
- package/tests/engine/graph-injector.test.js +44 -0
- package/tests/engine/graph.test.js +216 -0
- package/tests/engine/hybrid-searcher.test.js +74 -0
- package/tests/engine/indexer-bm25.test.js +37 -0
- package/tests/engine/mcp-tools.test.js +73 -0
- package/tests/engine/project-initializer-mcp.test.js +99 -0
- package/tests/engine/query-expander.test.js +36 -0
- package/tests/engine/reranker.test.js +51 -0
- package/tests/engine/rrf.test.js +49 -0
- package/tests/engine/srag-prefix.test.js +47 -0
- package/tests/instinct-block.test.js +23 -0
- package/tests/mcp-config-writer.test.js +60 -0
- package/tests/project-initializer-new-agents.test.js +48 -0
- package/tests/rules/rules-manager.test.js +230 -0
- package/tests/well-known-builder.test.js +40 -0
- package/tests/wizard/integration-detector.test.js +31 -0
- package/tests/wizard/project-detector.test.js +51 -0
- package/tests/wizard/prompt-session.test.js +61 -0
- package/tests/wizard/prompt.test.js +16 -0
- package/tests/wizard/registry-embeddings.test.js +35 -0
- package/tests/wizard/skill-recommender.test.js +34 -0
- package/tests/wizard/slot-count.test.js +25 -0
- package/vercel.json +21 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import matter from 'gray-matter';
|
|
4
|
+
|
|
5
|
+
const skillsRoot = './skills';
|
|
6
|
+
const outputFile = './llms-full.txt';
|
|
7
|
+
|
|
8
|
+
async function generateFullLLM() {
|
|
9
|
+
const skills = fs.readdirSync(skillsRoot)
|
|
10
|
+
.filter(name => fs.statSync(path.join(skillsRoot, name)).isDirectory() && fs.existsSync(path.join(skillsRoot, name, 'SKILL.md')));
|
|
11
|
+
|
|
12
|
+
let output = '# BookLib Full Skill Catalog\n\nThis file contains detailed descriptions and triggers for every skill in the BookLib library, optimized for RAG retrieval.\n\n';
|
|
13
|
+
|
|
14
|
+
for (const skill of skills) {
|
|
15
|
+
const skillPath = path.join(skillsRoot, skill, 'SKILL.md');
|
|
16
|
+
const content = fs.readFileSync(skillPath, 'utf8');
|
|
17
|
+
const { data: frontmatter } = matter(content);
|
|
18
|
+
|
|
19
|
+
output += `## Skill: ${frontmatter.name || skill}\n`;
|
|
20
|
+
output += `**Description**: ${frontmatter.description || 'No description available.'}\n`;
|
|
21
|
+
output += `**Directory**: \`skills/${skill}/\`\n`;
|
|
22
|
+
|
|
23
|
+
// Extract triggers if available in frontmatter or first paragraph
|
|
24
|
+
const triggerMatch = content.match(/Trigger on (.*)\./);
|
|
25
|
+
if (triggerMatch) {
|
|
26
|
+
output += `**Triggers**: ${triggerMatch[1]}\n`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
output += '\n---\n\n';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
fs.writeFileSync(outputFile, output.trim());
|
|
33
|
+
console.log(`Generated ${outputFile} with ${skills.length} skills.`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
generateFullLLM().catch(console.error);
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* gen-og.mjs — generates docs/og.png (1200×630) for GitHub Pages OG preview.
|
|
4
|
+
* Usage: node scripts/gen-og.mjs
|
|
5
|
+
* Requires: npm install -g puppeteer OR npx puppeteer is available
|
|
6
|
+
*/
|
|
7
|
+
import { writeFileSync, mkdirSync } from "fs";
|
|
8
|
+
import { join, dirname } from "path";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const OUT = join(__dirname, "../docs/og.png");
|
|
13
|
+
|
|
14
|
+
const HTML = `<!DOCTYPE html>
|
|
15
|
+
<html>
|
|
16
|
+
<head>
|
|
17
|
+
<meta charset="UTF-8"/>
|
|
18
|
+
<style>
|
|
19
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
20
|
+
body {
|
|
21
|
+
width: 1200px; height: 630px; overflow: hidden;
|
|
22
|
+
background: #0d0d1a;
|
|
23
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
justify-content: space-between;
|
|
27
|
+
padding: 0 80px;
|
|
28
|
+
position: relative;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Left: text content */
|
|
32
|
+
.left { flex: 0 0 auto; max-width: 540px; z-index: 2; }
|
|
33
|
+
|
|
34
|
+
.org {
|
|
35
|
+
font-size: 22px; font-weight: 500; color: #6366f1;
|
|
36
|
+
letter-spacing: 0.04em; margin-bottom: 16px;
|
|
37
|
+
font-family: "SF Mono", "Fira Code", monospace;
|
|
38
|
+
}
|
|
39
|
+
h1 {
|
|
40
|
+
font-size: 72px; font-weight: 800; color: #f1f5f9;
|
|
41
|
+
line-height: 1; letter-spacing: -0.04em; margin-bottom: 20px;
|
|
42
|
+
}
|
|
43
|
+
.tagline {
|
|
44
|
+
font-size: 24px; color: #64748b; line-height: 1.4; margin-bottom: 40px;
|
|
45
|
+
max-width: 460px;
|
|
46
|
+
}
|
|
47
|
+
.pills { display: flex; gap: 12px; flex-wrap: wrap; }
|
|
48
|
+
.pill {
|
|
49
|
+
background: #161625; border: 1px solid #2d2d4a;
|
|
50
|
+
border-radius: 999px; padding: 8px 20px;
|
|
51
|
+
font-size: 15px; color: #a5b4fc; font-weight: 600;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Right: book grid */
|
|
55
|
+
.books {
|
|
56
|
+
display: grid;
|
|
57
|
+
grid-template-columns: repeat(5, 1fr);
|
|
58
|
+
gap: 8px;
|
|
59
|
+
width: 420px;
|
|
60
|
+
flex-shrink: 0;
|
|
61
|
+
opacity: 0.92;
|
|
62
|
+
}
|
|
63
|
+
.book {
|
|
64
|
+
aspect-ratio: 2/3;
|
|
65
|
+
border-radius: 5px;
|
|
66
|
+
background: var(--c);
|
|
67
|
+
position: relative;
|
|
68
|
+
overflow: hidden;
|
|
69
|
+
}
|
|
70
|
+
.book::after {
|
|
71
|
+
content: "";
|
|
72
|
+
position: absolute; inset: 0;
|
|
73
|
+
background: linear-gradient(135deg, rgba(255,255,255,0.08) 0%, transparent 60%);
|
|
74
|
+
}
|
|
75
|
+
/* Spine line */
|
|
76
|
+
.book::before {
|
|
77
|
+
content: "";
|
|
78
|
+
position: absolute; top: 0; bottom: 0; left: 8px;
|
|
79
|
+
width: 2px; background: rgba(0,0,0,0.2);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Fade edge on left side of book grid */
|
|
83
|
+
.books-wrap {
|
|
84
|
+
position: relative;
|
|
85
|
+
flex-shrink: 0;
|
|
86
|
+
}
|
|
87
|
+
.books-wrap::before {
|
|
88
|
+
content: "";
|
|
89
|
+
position: absolute; top: 0; bottom: 0; left: -60px;
|
|
90
|
+
width: 80px;
|
|
91
|
+
background: linear-gradient(to right, #0d0d1a, transparent);
|
|
92
|
+
z-index: 1;
|
|
93
|
+
pointer-events: none;
|
|
94
|
+
}
|
|
95
|
+
</style>
|
|
96
|
+
</head>
|
|
97
|
+
<body>
|
|
98
|
+
<div class="left">
|
|
99
|
+
<div class="org">booklib-ai / skills</div>
|
|
100
|
+
<h1>Skills</h1>
|
|
101
|
+
<p class="tagline">Expert knowledge from 22 canonical programming books — packaged as AI agent skills.</p>
|
|
102
|
+
<div class="pills">
|
|
103
|
+
<span class="pill">22 skills</span>
|
|
104
|
+
<span class="pill">Claude Code</span>
|
|
105
|
+
<span class="pill">Cursor</span>
|
|
106
|
+
<span class="pill">Copilot</span>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<div class="books-wrap">
|
|
111
|
+
<div class="books">
|
|
112
|
+
${[
|
|
113
|
+
"#1e3a5f","#5f1e1e","#1e5f2a","#5f4a1e","#2a1e5f",
|
|
114
|
+
"#1e4d5f","#5f1e4a","#3d5f1e","#5f3d1e","#1e5f5f",
|
|
115
|
+
"#4a1e5f","#1e5f3d","#5f5f1e","#1e2a5f","#5f1e2a",
|
|
116
|
+
"#2a5f1e","#5f2a1e","#1e5f4a","#4a5f1e","#1e4a5f",
|
|
117
|
+
"#5f1e5f","#3d1e5f","#1e5f1e","#5f3d3d","#1e3d5f",
|
|
118
|
+
"#5f4d1e","#1e4d3d","#4d1e1e","#1e1e4d","#3d5f3d",
|
|
119
|
+
].map(c => `<div class="book" style="--c:${c}"></div>`).join("")}
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</body>
|
|
123
|
+
</html>`;
|
|
124
|
+
|
|
125
|
+
let puppeteer;
|
|
126
|
+
try {
|
|
127
|
+
puppeteer = await import("puppeteer");
|
|
128
|
+
} catch {
|
|
129
|
+
// Try puppeteer-core as fallback
|
|
130
|
+
puppeteer = await import("puppeteer-core");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const browser = await puppeteer.default.launch({ headless: true });
|
|
134
|
+
const page = await browser.newPage();
|
|
135
|
+
await page.setViewport({ width: 1200, height: 630, deviceScaleFactor: 2 });
|
|
136
|
+
await page.setContent(HTML, { waitUntil: "networkidle0" });
|
|
137
|
+
const buf = await page.screenshot({ type: "png" });
|
|
138
|
+
await browser.close();
|
|
139
|
+
|
|
140
|
+
mkdirSync(dirname(OUT), { recursive: true });
|
|
141
|
+
writeFileSync(OUT, buf);
|
|
142
|
+
console.log(`Written: ${OUT} (${(buf.length / 1024).toFixed(0)} KB)`);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import matter from 'gray-matter';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const SKILLS_DIR = path.resolve(fileURLToPath(import.meta.url), '../../skills');
|
|
8
|
+
const REQUIRED = ['name', 'description', 'version', 'tags', 'license'];
|
|
9
|
+
|
|
10
|
+
let failures = 0;
|
|
11
|
+
for (const skill of fs.readdirSync(SKILLS_DIR)) {
|
|
12
|
+
const file = path.join(SKILLS_DIR, skill, 'SKILL.md');
|
|
13
|
+
if (!fs.existsSync(file)) continue;
|
|
14
|
+
const { data } = matter(fs.readFileSync(file, 'utf8'));
|
|
15
|
+
const missing = REQUIRED.filter(field => {
|
|
16
|
+
const v = data[field];
|
|
17
|
+
return v === undefined || v === null || v === '' || (Array.isArray(v) && v.length === 0);
|
|
18
|
+
});
|
|
19
|
+
if (missing.length) {
|
|
20
|
+
console.log(`MISSING in ${skill}: ${missing.join(', ')}`);
|
|
21
|
+
failures++;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (failures === 0) console.log('All skills compliant.');
|
|
25
|
+
process.exit(failures > 0 ? 1 : 0);
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: animation-at-work
|
|
3
|
+
version: "1.0"
|
|
4
|
+
license: MIT
|
|
5
|
+
tags: [design, animation, ui]
|
|
6
|
+
description: >
|
|
7
|
+
Apply web animation principles from Animation at Work by Rachel Nabors.
|
|
8
|
+
Covers human perception of motion, 12 principles of animation, animation
|
|
9
|
+
patterns (transitions, supplements, feedback, demonstrations, decorations),
|
|
10
|
+
CSS transitions, CSS animations, Web Animations API, SVG/Canvas/WebGL,
|
|
11
|
+
communicating animation with storyboards and motion comps, performance
|
|
12
|
+
(composite-only properties, will-change, RAIL), accessibility (prefers-
|
|
13
|
+
reduced-motion, vestibular disorders), and team workflow. Trigger on
|
|
14
|
+
"animation", "transition", "CSS animation", "keyframe", "easing",
|
|
15
|
+
"motion design", "web animation", "prefers-reduced-motion", "storyboard",
|
|
16
|
+
"parallax", "loading animation", "hover effect", "micro-interaction".
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# Animation at Work Skill
|
|
20
|
+
|
|
21
|
+
You are an expert web animation advisor grounded in the 5 chapters from
|
|
22
|
+
*Animation at Work* by Rachel Nabors. You help in two modes:
|
|
23
|
+
|
|
24
|
+
1. **Design Application** — Apply animation principles to create purposeful, performant web animations
|
|
25
|
+
2. **Design Review** — Analyze existing animations and recommend improvements
|
|
26
|
+
|
|
27
|
+
## How to Decide Which Mode
|
|
28
|
+
|
|
29
|
+
- If the user asks to *create*, *add*, *implement*, *animate*, or *build* animations → **Design Application**
|
|
30
|
+
- If the user asks to *review*, *audit*, *evaluate*, *optimize*, or *fix* animations → **Design Review**
|
|
31
|
+
- If ambiguous, ask briefly which mode they'd prefer
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Mode 1: Design Application
|
|
36
|
+
|
|
37
|
+
When helping create animations, follow this decision flow:
|
|
38
|
+
|
|
39
|
+
### Step 1 — Classify the Animation's Purpose
|
|
40
|
+
|
|
41
|
+
Every animation must have a clear purpose. Classify using these five patterns:
|
|
42
|
+
|
|
43
|
+
| Pattern | Purpose | When to Use | Example |
|
|
44
|
+
|---------|---------|-------------|---------|
|
|
45
|
+
| **Transition** | Show state change between views/states | Navigating pages, opening panels, switching tabs | Page slide-in, modal open/close |
|
|
46
|
+
| **Supplement** | Bring elements into/out of a view that's already in place | Adding items to lists, showing notifications, revealing content | Toast notification slide-in, list item appear |
|
|
47
|
+
| **Feedback** | Confirm a user action was received | Button press, form submit, toggle | Button press ripple, checkbox animation |
|
|
48
|
+
| **Demonstration** | Explain how something works or draw attention | Onboarding, tutorials, feature discovery | Animated walkthrough, pulsing CTA |
|
|
49
|
+
| **Decoration** | Ambient, non-functional delight | Background effects, idle states | Parallax background, floating particles |
|
|
50
|
+
|
|
51
|
+
**Key principle**: If an animation doesn't fit any of these patterns, question whether it's needed. Decorations should be used sparingly — they add no functional value and can annoy users over time.
|
|
52
|
+
|
|
53
|
+
### Step 2 — Choose the Right Technology
|
|
54
|
+
|
|
55
|
+
Read `references/api_reference.md` for detailed API specifics. Quick decision guide:
|
|
56
|
+
|
|
57
|
+
| Need | Technology | Why |
|
|
58
|
+
|------|-----------|-----|
|
|
59
|
+
| Simple hover/focus effects | CSS Transitions | Declarative, performant, minimal code |
|
|
60
|
+
| Looping or multi-step animations | CSS Animations (@keyframes) | Built-in iteration, keyframe control |
|
|
61
|
+
| Playback control (play/pause/reverse/scrub) | Web Animations API | JavaScript control with CSS performance |
|
|
62
|
+
| Complex coordinated sequences | Web Animations API | Timeline coordination, promises, grouping |
|
|
63
|
+
| Character animation or complex graphics | SVG + SMIL or Canvas | Vector scalability, per-element control |
|
|
64
|
+
| 3D or particle effects | WebGL/Three.js | GPU-accelerated 3D rendering |
|
|
65
|
+
| Simple loading indicators | CSS Animations | Self-contained, no JS needed |
|
|
66
|
+
|
|
67
|
+
### Step 3 — Apply Motion Design Principles
|
|
68
|
+
|
|
69
|
+
**The 12 Principles of Animation** (from Disney, adapted for UI):
|
|
70
|
+
|
|
71
|
+
The most relevant for web UI:
|
|
72
|
+
|
|
73
|
+
- **Timing and spacing** — Duration and easing control perceived weight and personality. Fast (100–200ms) for feedback, medium (200–500ms) for transitions, slow (500ms+) for demonstrations
|
|
74
|
+
- **Anticipation** — Brief preparatory motion before the main action (button slight shrink before expanding)
|
|
75
|
+
- **Follow-through and overlapping action** — Elements don't all stop at once; stagger them for natural feel
|
|
76
|
+
- **Staging** — Direct user attention to what matters; animate the focal point, keep surroundings still
|
|
77
|
+
- **Ease in / ease out (slow in, slow out)** — Objects accelerate and decelerate naturally; avoid linear easing for UI
|
|
78
|
+
- **Arcs** — Natural motion follows curved paths, not straight lines
|
|
79
|
+
- **Secondary action** — Supporting animations that reinforce the main action without distracting
|
|
80
|
+
- **Exaggeration** — Amplify motion slightly for clarity (a bounce overshoot on a panel opening)
|
|
81
|
+
- **Appeal** — The animation should feel pleasant and appropriate for the brand
|
|
82
|
+
|
|
83
|
+
**Easing guidance**:
|
|
84
|
+
- `ease-out` — Best for elements **entering** (fast start, gentle stop)
|
|
85
|
+
- `ease-in` — Best for elements **leaving** (gentle start, fast exit)
|
|
86
|
+
- `ease-in-out` — Best for elements that **stay on screen** and move position
|
|
87
|
+
- `linear` — Only for continuous motion (progress bars, spinning loaders)
|
|
88
|
+
- Custom `cubic-bezier()` — For brand-specific personality
|
|
89
|
+
|
|
90
|
+
**Duration guidance**:
|
|
91
|
+
- Micro-interactions (feedback): 100–200ms
|
|
92
|
+
- Transitions between states: 200–500ms
|
|
93
|
+
- Complex demonstrations: 500ms–1s
|
|
94
|
+
- Page transitions: 300–500ms
|
|
95
|
+
- Never exceed 1s for functional animations (users feel delay)
|
|
96
|
+
|
|
97
|
+
### Step 4 — Build with Performance in Mind
|
|
98
|
+
|
|
99
|
+
**Composite-only properties** (GPU-accelerated, no layout/paint):
|
|
100
|
+
- `transform` (translate, scale, rotate)
|
|
101
|
+
- `opacity`
|
|
102
|
+
|
|
103
|
+
**Avoid animating**: `width`, `height`, `top`, `left`, `margin`, `padding`, `border`, `font-size` — these trigger layout recalculation.
|
|
104
|
+
|
|
105
|
+
**Performance tips**:
|
|
106
|
+
- Use `will-change` to hint browser about upcoming animations (but sparingly — overuse wastes memory)
|
|
107
|
+
- Promote elements to their own compositor layer for complex animations
|
|
108
|
+
- Use `requestAnimationFrame` for JS-driven animations
|
|
109
|
+
- Test on low-powered devices, not just your dev machine
|
|
110
|
+
- Follow the RAIL model: Response <100ms, Animation <16ms/frame, Idle <50ms, Load <1000ms
|
|
111
|
+
|
|
112
|
+
### Step 5 — Handle Accessibility
|
|
113
|
+
|
|
114
|
+
**Always implement `prefers-reduced-motion`**:
|
|
115
|
+
```css
|
|
116
|
+
@media (prefers-reduced-motion: reduce) {
|
|
117
|
+
*, *::before, *::after {
|
|
118
|
+
animation-duration: 0.01ms !important;
|
|
119
|
+
animation-iteration-count: 1 !important;
|
|
120
|
+
transition-duration: 0.01ms !important;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Vestibular disorder considerations**:
|
|
126
|
+
- Parallax scrolling can cause dizziness — provide alternative
|
|
127
|
+
- Large-scale motion across the screen is more triggering than small, contained animations
|
|
128
|
+
- Zooming/scaling effects are problematic
|
|
129
|
+
- Auto-playing animations should be pausable
|
|
130
|
+
- Flashing content (>3 times/sec) can trigger seizures — never do this
|
|
131
|
+
|
|
132
|
+
**Safe alternatives when motion is reduced**:
|
|
133
|
+
- Cross-fade (opacity) instead of sliding
|
|
134
|
+
- Instant state change instead of animated transition
|
|
135
|
+
- Static illustrations instead of animated demonstrations
|
|
136
|
+
|
|
137
|
+
### Design Application Examples
|
|
138
|
+
|
|
139
|
+
**Example 1 — Toast Notification (Supplement):**
|
|
140
|
+
```css
|
|
141
|
+
.toast {
|
|
142
|
+
transform: translateY(100%);
|
|
143
|
+
opacity: 0;
|
|
144
|
+
transition: transform 300ms ease-out, opacity 300ms ease-out;
|
|
145
|
+
}
|
|
146
|
+
.toast.visible {
|
|
147
|
+
transform: translateY(0);
|
|
148
|
+
opacity: 1;
|
|
149
|
+
}
|
|
150
|
+
@media (prefers-reduced-motion: reduce) {
|
|
151
|
+
.toast { transition-duration: 0.01ms !important; }
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Example 2 — Button Feedback:**
|
|
156
|
+
```css
|
|
157
|
+
.btn:active {
|
|
158
|
+
transform: scale(0.95);
|
|
159
|
+
transition: transform 100ms ease-in;
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Example 3 — Page Transition (Web Animations API):**
|
|
164
|
+
```js
|
|
165
|
+
const outgoing = currentPage.animate(
|
|
166
|
+
[{ opacity: 1, transform: 'translateX(0)' },
|
|
167
|
+
{ opacity: 0, transform: 'translateX(-20px)' }],
|
|
168
|
+
{ duration: 250, easing: 'ease-in', fill: 'forwards' }
|
|
169
|
+
);
|
|
170
|
+
outgoing.finished.then(() => {
|
|
171
|
+
nextPage.animate(
|
|
172
|
+
[{ opacity: 0, transform: 'translateX(20px)' },
|
|
173
|
+
{ opacity: 1, transform: 'translateX(0)' }],
|
|
174
|
+
{ duration: 250, easing: 'ease-out', fill: 'forwards' }
|
|
175
|
+
);
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Mode 2: Design Review
|
|
182
|
+
|
|
183
|
+
When reviewing animations, read `references/review-checklist.md` for the full checklist.
|
|
184
|
+
|
|
185
|
+
### Review Process
|
|
186
|
+
|
|
187
|
+
1. **Purpose scan** — Does every animation fit one of the 5 patterns (transition, supplement, feedback, demonstration, decoration)?
|
|
188
|
+
2. **Performance scan** — Are only composite properties animated? Any layout thrashing?
|
|
189
|
+
3. **Accessibility scan** — Is `prefers-reduced-motion` implemented? Any vestibular triggers?
|
|
190
|
+
4. **Timing scan** — Are durations appropriate? Any animation exceeding 1s for functional use?
|
|
191
|
+
5. **Easing scan** — Are easings appropriate for the direction of motion?
|
|
192
|
+
6. **Redundancy scan** — Are any decorations overused or distracting from content?
|
|
193
|
+
|
|
194
|
+
### Review Output Format
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
## Summary
|
|
198
|
+
One paragraph: overall animation quality, main strengths, key concerns.
|
|
199
|
+
|
|
200
|
+
## Purpose Issues
|
|
201
|
+
- **Animation**: which element/interaction
|
|
202
|
+
- **Problem**: missing purpose, wrong pattern, excessive decoration
|
|
203
|
+
- **Fix**: recommended change with pattern reference
|
|
204
|
+
|
|
205
|
+
## Performance Issues
|
|
206
|
+
- **Animation**: which element/property
|
|
207
|
+
- **Problem**: layout-triggering property, missing will-change, jank
|
|
208
|
+
- **Fix**: switch to composite-only property, optimize
|
|
209
|
+
|
|
210
|
+
## Accessibility Issues
|
|
211
|
+
- **Animation**: which element
|
|
212
|
+
- **Problem**: missing reduced-motion, vestibular trigger, no pause control
|
|
213
|
+
- **Fix**: add media query, provide alternative
|
|
214
|
+
|
|
215
|
+
## Timing/Easing Issues
|
|
216
|
+
- **Animation**: which element
|
|
217
|
+
- **Problem**: too slow, wrong easing, linear on UI element
|
|
218
|
+
- **Fix**: recommended duration and easing
|
|
219
|
+
|
|
220
|
+
## Recommendations
|
|
221
|
+
Priority-ordered list with specific chapter references.
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Common Animation Anti-Patterns to Flag
|
|
225
|
+
|
|
226
|
+
- **Animation for animation's sake** → Ch 2: Every animation needs a purpose from the 5 patterns
|
|
227
|
+
- **Linear easing on UI elements** → Ch 1: Real objects ease in/out; linear feels robotic
|
|
228
|
+
- **Animating layout properties** → Ch 3: Use transform/opacity only for performance
|
|
229
|
+
- **No reduced-motion support** → Ch 5: Always implement prefers-reduced-motion
|
|
230
|
+
- **Too-long duration** → Ch 1: Functional animations should be under 1s
|
|
231
|
+
- **Auto-playing without pause** → Ch 5: Users must be able to stop animations
|
|
232
|
+
- **Excessive decorations** → Ch 2: Decorations have diminishing returns and can annoy
|
|
233
|
+
- **Same easing for enter and exit** → Ch 1: Use ease-out for enter, ease-in for exit
|
|
234
|
+
- **Parallax without fallback** → Ch 5: Parallax triggers vestibular issues
|
|
235
|
+
- **Flash rate >3/sec** → Ch 5: Can trigger seizures; never exceed this
|
|
236
|
+
- **`display: none` ↔ `display: block` transitions** → Ch 3: `display` is not an animatable property; switching between `none` and `block` causes an instant jump — the animation runs but the element appears/disappears immediately. Fix: use `opacity`/`transform` combined with `visibility: hidden` or `pointer-events: none` to keep the element in the flow while visually hidden, or use the modern `@starting-style` rule.
|
|
237
|
+
|
|
238
|
+
### Praiseworthy Patterns to Recognize
|
|
239
|
+
|
|
240
|
+
When code already does these well, **explicitly acknowledge them** in your review:
|
|
241
|
+
|
|
242
|
+
- **Composite-only animation** — Animating only `transform` and `opacity` (GPU-accelerated, no layout/paint)
|
|
243
|
+
- **Correct easing directionality** — `ease-out` for entering elements, `ease-in` for exiting elements
|
|
244
|
+
- **Consistent duration hierarchy** — Durations ordered by interaction weight: 100ms (press feedback) → 200ms (hover/small UI) → 300ms (notifications) → 400ms (reveals) — shows intentional design
|
|
245
|
+
- **`prefers-reduced-motion` implementation** — Especially the global `*, *::before, *::after` block that sets `animation-duration: 0.01ms` and `transition-duration: 0.01ms` — this is the correct canonical approach
|
|
246
|
+
- **`pointer-events: none` on hidden elements** — Prevents interaction with invisible elements without removing from DOM; cleaner than `display: none` toggling
|
|
247
|
+
- **WAAPI with IntersectionObserver** — Using `element.animate()` inside an IntersectionObserver callback avoids scroll-event jank; calling `observer.unobserve()` after triggering prevents repeat-fire — both are signs of mature implementation
|
|
248
|
+
|
|
249
|
+
### Calibrating Review Severity
|
|
250
|
+
|
|
251
|
+
**Not every review needs problems.** When code is well-designed:
|
|
252
|
+
|
|
253
|
+
1. Lead with genuine praise for what's done correctly — be specific about which patterns are good and why
|
|
254
|
+
2. If you suggest improvements, frame them explicitly as "minor optional improvements" or "polish ideas" — do not label them 🔴 Critical or High unless they are genuine accessibility or performance regressions
|
|
255
|
+
3. Do not manufacture issues to appear thorough; a short, positive review of good code is more valuable than a padded list of nitpicks
|
|
256
|
+
4. The summary paragraph should reflect the overall quality honestly — if it's well-crafted, say so directly
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## General Guidelines
|
|
261
|
+
|
|
262
|
+
- **Purpose first** — Every animation must serve a functional purpose or be consciously decorative
|
|
263
|
+
- **Performance is non-negotiable** — Only animate composite properties (transform, opacity)
|
|
264
|
+
- **Accessibility is mandatory** — Always implement prefers-reduced-motion
|
|
265
|
+
- **Duration matters** — Fast for feedback (100–200ms), medium for transitions (200–500ms), slow for demos (500ms+)
|
|
266
|
+
- **Easing conveys personality** — ease-out for entering, ease-in for leaving, ease-in-out for repositioning
|
|
267
|
+
- **Less is more** — One well-crafted animation beats ten flashy ones
|
|
268
|
+
- **Test on real devices** — Animations that work on your MacBook may jank on budget phones
|
|
269
|
+
- For detailed API reference, read `references/api_reference.md`
|
|
270
|
+
- For review checklists, read `references/review-checklist.md`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"evals": [
|
|
3
|
+
{
|
|
4
|
+
"id": "eval-01-no-easing-layout-properties-inconsistent-duration",
|
|
5
|
+
"prompt": "Review these CSS animations:\n\n```css\n/* Modal open animation */\n.modal {\n display: none;\n width: 600px;\n padding: 40px;\n background: white;\n border-radius: 8px;\n position: fixed;\n top: 50%;\n left: 50%;\n margin-top: -200px;\n margin-left: -300px;\n}\n\n.modal.visible {\n display: block;\n animation: modal-open 0.4s linear;\n}\n\n@keyframes modal-open {\n from {\n margin-top: -400px;\n opacity: 0;\n width: 400px;\n }\n to {\n margin-top: -200px;\n opacity: 1;\n width: 600px;\n }\n}\n\n/* Button hover */\n.btn:hover {\n background-color: #0056b3;\n padding: 14px 28px;\n border-radius: 12px;\n transition: all 2s linear;\n}\n\n/* Notification badge */\n.badge-new {\n animation: pulse 0.8s linear infinite;\n}\n\n@keyframes pulse {\n 0% { transform: scale(1); }\n 50% { transform: scale(1.2); }\n 100% { transform: scale(1); }\n}\n```",
|
|
6
|
+
"expectations": [
|
|
7
|
+
"Flags `linear` easing on the modal open animation: linear motion feels robotic for UI elements entering the screen; recommends `ease-out` for elements entering (ease-out: fast start, gentle stop conveys natural deceleration)",
|
|
8
|
+
"Flags animating `margin-top` and `width` in the modal keyframes: these are layout properties that trigger full reflow on every frame; recommends replacing with `transform: translateY()` and `transform: scale()` or opacity (Ch 3 / Performance: only animate composite properties — transform and opacity)",
|
|
9
|
+
"Flags `transition: all 2s linear` on the button hover: 2 seconds is far too slow for a hover feedback interaction; functional UI feedback should be 100-200ms; recommends `transition: background-color 150ms ease-out` (Ch 1: duration guidance — micro-interactions 100-200ms)",
|
|
10
|
+
"Flags `transition: all` as an anti-pattern: it animates every changing property including layout properties like padding and border-radius that trigger reflow; recommends specifying only the intended properties",
|
|
11
|
+
"Flags animating `padding` and `border-radius` on the button hover for the same layout-thrashing reason",
|
|
12
|
+
"Flags the `linear` easing on the pulse badge animation: while linear is acceptable for continuous looping motion, there is no `prefers-reduced-motion` media query to disable or reduce this infinite animation for users with vestibular disorders",
|
|
13
|
+
"Notes the modal uses `display: none` switching to `display: block` which cannot be animated directly; the animation will jump; recommends using opacity/transform with visibility or pointer-events instead"
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "eval-02-hover-animation-too-slow",
|
|
18
|
+
"prompt": "Review these CSS hover and focus animations:\n\n```css\n/* Navigation link hover */\n.nav-link {\n color: #333;\n text-decoration: none;\n border-bottom: 2px solid transparent;\n transition: border-bottom-color 1.5s ease-in-out,\n color 1.5s ease-in-out;\n}\n\n.nav-link:hover,\n.nav-link:focus {\n color: #0066cc;\n border-bottom-color: #0066cc;\n}\n\n/* Card hover lift effect */\n.card {\n box-shadow: 0 1px 3px rgba(0,0,0,0.12);\n transition: box-shadow 1.2s ease,\n top 1.2s ease;\n position: relative;\n top: 0;\n}\n\n.card:hover {\n box-shadow: 0 8px 25px rgba(0,0,0,0.15);\n top: -4px;\n}\n\n/* Icon button feedback */\n.icon-btn:active {\n transform: scale(0.9);\n transition: transform 800ms ease;\n}\n```",
|
|
19
|
+
"expectations": [
|
|
20
|
+
"Flags the 1.5s transition on `.nav-link` hover as far too slow for a hover feedback: users expect near-instant response (100-200ms) for hover states; a 1.5s delay makes the interface feel broken or laggy (Ch 1: duration guidance — micro-interactions 100-200ms; functional animations under 1s)",
|
|
21
|
+
"Flags the 1.2s transition on `.card` hover for the same reason: hover lift effects should be 150-250ms to feel responsive",
|
|
22
|
+
"Flags animating `top` on the card hover: `top` is a layout property that triggers reflow; recommends replacing with `transform: translateY(-4px)` which is GPU-accelerated (performance: animate composite properties only)",
|
|
23
|
+
"Flags animating `box-shadow` on the card: box-shadow is not a composite-only property (Ch. 3: only transform and opacity are GPU-composited and avoid layout/paint triggers); recommends replacing with a transform-based approach",
|
|
24
|
+
"Flags the 800ms active/press feedback on `.icon-btn`: press feedback should be the fastest animation in the UI (100-150ms); 800ms means the animation outlasts the press itself and confuses the user",
|
|
25
|
+
"Flags `ease-in-out` on all hover effects: `ease-in-out` is appropriate for elements that move and stay on screen, but for hover state changes `ease-out` is more natural (fast onset, settles gently)",
|
|
26
|
+
"Notes the absence of a `prefers-reduced-motion` media query anywhere in the stylesheet"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "eval-03-clean-animation-transform-opacity-consistent-easing",
|
|
31
|
+
"prompt": "Review these CSS and JavaScript animations:\n\n```css\n/* Dropdown menu enter/exit */\n.dropdown {\n opacity: 0;\n transform: translateY(-8px);\n pointer-events: none;\n transition: opacity 200ms ease-out,\n transform 200ms ease-out;\n}\n\n.dropdown.open {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n/* Toast notification slide-in */\n.toast {\n transform: translateX(110%);\n transition: transform 300ms ease-out;\n}\n\n.toast.show {\n transform: translateX(0);\n}\n\n.toast.hide {\n transform: translateX(110%);\n transition: transform 200ms ease-in;\n}\n\n/* Button press feedback */\n.btn:active {\n transform: scale(0.96);\n transition: transform 100ms ease-in;\n}\n\n/* Reduced motion support */\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n```\n\n```js\n// Page section fade-in on scroll (Web Animations API)\ndocument.querySelectorAll('.section').forEach(section => {\n const observer = new IntersectionObserver(entries => {\n entries.forEach(entry => {\n if (entry.isIntersecting) {\n entry.target.animate(\n [{ opacity: 0, transform: 'translateY(20px)' },\n { opacity: 1, transform: 'translateY(0)' }],\n { duration: 400, easing: 'ease-out', fill: 'forwards' }\n );\n observer.unobserve(entry.target);\n }\n });\n }, { threshold: 0.15 });\n observer.observe(section);\n});\n```",
|
|
32
|
+
"expectations": [
|
|
33
|
+
"Recognizes this is a well-designed set of animations and says so explicitly",
|
|
34
|
+
"Praises animating only `transform` and `opacity` throughout: these are GPU-composited properties that avoid layout reflow and paint (performance: composite-only properties)",
|
|
35
|
+
"Praises using `ease-out` for entering elements (dropdown open, toast show, scroll fade-in) and `ease-in` for exiting elements (toast hide) — correct easing directionality (Ch 1: ease-out for entering, ease-in for leaving)",
|
|
36
|
+
"Praises consistent duration scale: 100ms for press feedback, 200ms for dropdown, 300ms for toast entry, 400ms for scroll reveal — all within appropriate ranges and ordered by interaction importance (Ch 1: duration guidance)",
|
|
37
|
+
"Praises the `prefers-reduced-motion` media query that effectively disables all transitions and animations for users who need it (Ch 5: accessibility, vestibular disorders)",
|
|
38
|
+
"Praises `pointer-events: none` on the hidden dropdown to prevent interaction with invisible elements without removing from DOM (correct implementation detail)",
|
|
39
|
+
"Praises using Web Animations API with IntersectionObserver for scroll-triggered animations: avoids scroll-event jank and unobserves after trigger preventing repeat animations (Ch 3: Web Animations API for playback control)",
|
|
40
|
+
"Does NOT manufacture issues to appear thorough; any suggestions are explicitly framed as minor optional improvements"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pass_rate": 0.955,
|
|
3
|
+
"passed": 21,
|
|
4
|
+
"total": 22,
|
|
5
|
+
"baseline_pass_rate": 0.636,
|
|
6
|
+
"baseline_passed": 14,
|
|
7
|
+
"baseline_total": 22,
|
|
8
|
+
"delta": 0.318,
|
|
9
|
+
"model": "default",
|
|
10
|
+
"evals_run": 3,
|
|
11
|
+
"date": "2026-03-28",
|
|
12
|
+
"non_standard_provider": true
|
|
13
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# After
|
|
2
|
+
|
|
3
|
+
The navigation drawer animation switches to composite-only properties (`transform` + `opacity`), uses `ease-out` easing, a 250ms duration, and respects `prefers-reduced-motion`.
|
|
4
|
+
|
|
5
|
+
```css
|
|
6
|
+
/* Nav drawer — animate only composite properties (transform, opacity) */
|
|
7
|
+
.nav-drawer {
|
|
8
|
+
/* Position off-screen using transform — not width/height */
|
|
9
|
+
transform: translateX(-280px);
|
|
10
|
+
opacity: 0;
|
|
11
|
+
width: 280px; /* fixed dimensions, never animated */
|
|
12
|
+
height: 100vh;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
background-color: #1a1a2e;
|
|
15
|
+
/* ease-out: fast start → gentle stop — natural for entering elements (Ch 1) */
|
|
16
|
+
transition:
|
|
17
|
+
transform 250ms ease-out,
|
|
18
|
+
opacity 200ms ease-out;
|
|
19
|
+
/* Hint the browser to promote this element to its own compositor layer */
|
|
20
|
+
will-change: transform;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.nav-drawer.open {
|
|
24
|
+
transform: translateX(0);
|
|
25
|
+
opacity: 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Menu items stagger in using animation-delay for follow-through (Ch 1) */
|
|
29
|
+
.nav-drawer .menu-item {
|
|
30
|
+
opacity: 0;
|
|
31
|
+
transform: translateX(-12px);
|
|
32
|
+
transition:
|
|
33
|
+
opacity 180ms ease-out,
|
|
34
|
+
transform 180ms ease-out;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.nav-drawer.open .menu-item {
|
|
38
|
+
opacity: 1;
|
|
39
|
+
transform: translateX(0);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Stagger each item for natural overlapping action */
|
|
43
|
+
.nav-drawer.open .menu-item:nth-child(1) { transition-delay: 60ms; }
|
|
44
|
+
.nav-drawer.open .menu-item:nth-child(2) { transition-delay: 90ms; }
|
|
45
|
+
.nav-drawer.open .menu-item:nth-child(3) { transition-delay: 120ms; }
|
|
46
|
+
.nav-drawer.open .menu-item:nth-child(4) { transition-delay: 150ms; }
|
|
47
|
+
|
|
48
|
+
/* Accessibility: remove all motion for users who prefer it (Ch 5) */
|
|
49
|
+
@media (prefers-reduced-motion: reduce) {
|
|
50
|
+
.nav-drawer,
|
|
51
|
+
.nav-drawer .menu-item {
|
|
52
|
+
transition: opacity 150ms linear !important;
|
|
53
|
+
transform: none !important;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Key improvements:
|
|
59
|
+
- `transform: translateX()` replaces `width`/`height` animation — `transform` and `opacity` are the only composite-only properties that animate on the GPU without triggering layout recalculation (Ch 3: Performance — composite-only properties)
|
|
60
|
+
- Duration reduced from 1.5s to 250ms — functional UI animations should be 200–500ms; 1.5s feels sluggish and blocks the user (Ch 1: Timing and duration)
|
|
61
|
+
- `ease-out` replaces `linear` — entering elements should start fast and slow to a stop; linear easing feels robotic for UI elements (Ch 1: 12 Principles — ease in / ease out)
|
|
62
|
+
- `will-change: transform` promotes the drawer to its own compositor layer, enabling smooth 60fps animation on mobile devices (Ch 3: will-change)
|
|
63
|
+
- Staggered `transition-delay` on menu items creates overlapping action — the drawer and its children don't all stop simultaneously, producing a more natural feel (Ch 1: 12 Principles — follow-through and overlapping action)
|
|
64
|
+
- `@media (prefers-reduced-motion: reduce)` is implemented — users with vestibular disorders receive a simple fade instead of a lateral sweep (Ch 5: Accessibility — prefers-reduced-motion)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Before
|
|
2
|
+
|
|
3
|
+
A CSS animation on a navigation drawer that animates `width` and `height` (layout-triggering properties) with `linear` easing and a 1.5-second duration, with no `prefers-reduced-motion` support.
|
|
4
|
+
|
|
5
|
+
```css
|
|
6
|
+
.nav-drawer {
|
|
7
|
+
width: 0;
|
|
8
|
+
height: 0;
|
|
9
|
+
overflow: hidden;
|
|
10
|
+
background-color: #1a1a2e;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.nav-drawer.open {
|
|
14
|
+
width: 280px;
|
|
15
|
+
height: 100vh;
|
|
16
|
+
/* Animates layout properties — forces browser to recalculate layout
|
|
17
|
+
on every frame, causing jank on low-powered devices */
|
|
18
|
+
transition: width 1.5s linear, height 1.5s linear;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.nav-drawer .menu-item {
|
|
22
|
+
opacity: 0;
|
|
23
|
+
/* Also animates layout property margin */
|
|
24
|
+
margin-left: -280px;
|
|
25
|
+
transition: opacity 1.5s linear, margin-left 1.5s linear;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.nav-drawer.open .menu-item {
|
|
29
|
+
opacity: 1;
|
|
30
|
+
margin-left: 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* No prefers-reduced-motion support — users with vestibular
|
|
34
|
+
disorders experience the full 1.5s sweep animation */
|
|
35
|
+
```
|