@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,184 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
review.py — Pre-analysis script for Spring Boot in Action reviews.
|
|
4
|
+
Usage: python review.py <file.java|application.properties|application.yml>
|
|
5
|
+
|
|
6
|
+
Scans Spring Boot source files for anti-patterns from the book:
|
|
7
|
+
field injection, hardcoded credentials, missing ResponseEntity, auto-config
|
|
8
|
+
fighting, wrong test annotations, missing Actuator security, and ddl-auto=create.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import re
|
|
12
|
+
import sys
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
JAVA_CHECKS = [
|
|
17
|
+
(
|
|
18
|
+
r"@Autowired\s*\n\s*(private|protected)",
|
|
19
|
+
"Ch 2: Field injection (@Autowired on field)",
|
|
20
|
+
"use constructor injection — fields with @Autowired are not testable without Spring context",
|
|
21
|
+
),
|
|
22
|
+
(
|
|
23
|
+
r"DriverManagerDataSource|BasicDataSource|HikariDataSource",
|
|
24
|
+
"Ch 2/3: Manual DataSource bean",
|
|
25
|
+
"delete this bean and set spring.datasource.* in application.properties — Boot auto-configures HikariCP",
|
|
26
|
+
),
|
|
27
|
+
(
|
|
28
|
+
r"orElse\(null\)",
|
|
29
|
+
"Ch 2: orElse(null) returns null to client",
|
|
30
|
+
"use .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)) or .map(ResponseEntity::ok).orElse(ResponseEntity.notFound().build())",
|
|
31
|
+
),
|
|
32
|
+
(
|
|
33
|
+
r'setPassword\s*\(\s*"[^"$][^"]*"',
|
|
34
|
+
"Ch 3: Hardcoded password",
|
|
35
|
+
"externalize to environment variable: spring.datasource.password=${DB_PASS}",
|
|
36
|
+
),
|
|
37
|
+
(
|
|
38
|
+
r'setUsername\s*\(\s*"[^"$][^"]*"',
|
|
39
|
+
"Ch 3: Hardcoded username",
|
|
40
|
+
"externalize to environment variable: spring.datasource.username=${DB_USER}",
|
|
41
|
+
),
|
|
42
|
+
(
|
|
43
|
+
r"new ObjectMapper\(\)",
|
|
44
|
+
"Ch 2: Manual ObjectMapper construction",
|
|
45
|
+
"Spring Boot auto-configures Jackson — inject ObjectMapper bean or configure via spring.jackson.* properties",
|
|
46
|
+
),
|
|
47
|
+
(
|
|
48
|
+
r"@SpringBootTest\b(?!.*WebEnvironment)",
|
|
49
|
+
"Ch 4: @SpringBootTest without WebEnvironment",
|
|
50
|
+
"for controller tests use @WebMvcTest; for repository tests use @DataJpaTest; full @SpringBootTest only for integration tests",
|
|
51
|
+
),
|
|
52
|
+
(
|
|
53
|
+
r"System\.out\.println",
|
|
54
|
+
"Ch 3: System.out.println instead of logger",
|
|
55
|
+
"use SLF4J: private static final Logger log = LoggerFactory.getLogger(MyClass.class)",
|
|
56
|
+
),
|
|
57
|
+
(
|
|
58
|
+
r'@Value\s*\(\s*"\$\{[^}]+\}"\s*\)(?:[\s\S]{0,200}@Value\s*\(\s*"\$\{){2}',
|
|
59
|
+
"Ch 3: Multiple @Value annotations",
|
|
60
|
+
"group related config values in a @ConfigurationProperties class with a prefix",
|
|
61
|
+
),
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
PROPERTIES_CHECKS = [
|
|
65
|
+
(
|
|
66
|
+
r"ddl-auto\s*=\s*(create|create-drop)(?!\s*#.*test)",
|
|
67
|
+
"Ch 8: ddl-auto=create or create-drop",
|
|
68
|
+
"destroys data on restart — use 'validate' in production; use Flyway/Liquibase for migrations",
|
|
69
|
+
),
|
|
70
|
+
(
|
|
71
|
+
r"management\.endpoints\.web\.exposure\.include\s*=\s*\*",
|
|
72
|
+
"Ch 7: Actuator exposes all endpoints",
|
|
73
|
+
"restrict to: management.endpoints.web.exposure.include=health,info — never expose env, beans, or shutdown publicly",
|
|
74
|
+
),
|
|
75
|
+
(
|
|
76
|
+
r"spring\.security\.user\.password\s*=\s*(?!(\$\{|\s*$))",
|
|
77
|
+
"Ch 3: Hardcoded security password in properties",
|
|
78
|
+
"use environment variable: spring.security.user.password=${ADMIN_PASS}",
|
|
79
|
+
),
|
|
80
|
+
(
|
|
81
|
+
r"datasource\.password\s*=\s*(?!\$\{)(\S+)",
|
|
82
|
+
"Ch 3: Hardcoded datasource password",
|
|
83
|
+
"use environment variable: spring.datasource.password=${DB_PASS}",
|
|
84
|
+
),
|
|
85
|
+
(
|
|
86
|
+
r"datasource\.url\s*=\s*jdbc:[a-z]+://(?!(\$\{|localhost|127\.0\.0\.1))\S+",
|
|
87
|
+
"Ch 3: Hardcoded production datasource URL",
|
|
88
|
+
"use environment variable: spring.datasource.url=${DB_URL}",
|
|
89
|
+
),
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def scan_java(source: str) -> list[dict]:
|
|
94
|
+
findings = []
|
|
95
|
+
lines = source.splitlines()
|
|
96
|
+
for lineno, line in enumerate(lines, start=1):
|
|
97
|
+
if line.strip().startswith("//"):
|
|
98
|
+
continue
|
|
99
|
+
for pattern, label, advice in JAVA_CHECKS:
|
|
100
|
+
if re.search(pattern, line):
|
|
101
|
+
findings.append({"line": lineno, "text": line.rstrip(), "label": label, "advice": advice})
|
|
102
|
+
return findings
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def scan_properties(source: str) -> list[dict]:
|
|
106
|
+
findings = []
|
|
107
|
+
lines = source.splitlines()
|
|
108
|
+
for lineno, line in enumerate(lines, start=1):
|
|
109
|
+
if line.strip().startswith("#"):
|
|
110
|
+
continue
|
|
111
|
+
for pattern, label, advice in PROPERTIES_CHECKS:
|
|
112
|
+
if re.search(pattern, line):
|
|
113
|
+
findings.append({"line": lineno, "text": line.rstrip(), "label": label, "advice": advice})
|
|
114
|
+
return findings
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def sep(char="-", width=70) -> str:
|
|
118
|
+
return char * width
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def main() -> None:
|
|
122
|
+
if len(sys.argv) < 2:
|
|
123
|
+
print("Usage: python review.py <file.java|application.properties|application.yml>")
|
|
124
|
+
sys.exit(1)
|
|
125
|
+
|
|
126
|
+
path = Path(sys.argv[1])
|
|
127
|
+
if not path.exists():
|
|
128
|
+
print(f"Error: file not found: {path}")
|
|
129
|
+
sys.exit(1)
|
|
130
|
+
|
|
131
|
+
source = path.read_text(encoding="utf-8", errors="replace")
|
|
132
|
+
|
|
133
|
+
if path.suffix == ".java":
|
|
134
|
+
findings = scan_java(source)
|
|
135
|
+
file_type = "Java"
|
|
136
|
+
elif path.suffix in (".properties", ".yml", ".yaml"):
|
|
137
|
+
findings = scan_properties(source)
|
|
138
|
+
file_type = "Properties/YAML"
|
|
139
|
+
else:
|
|
140
|
+
print(f"Warning: unsupported extension '{path.suffix}' — scanning as Java")
|
|
141
|
+
findings = scan_java(source)
|
|
142
|
+
file_type = "Unknown"
|
|
143
|
+
|
|
144
|
+
groups: dict[str, list] = {}
|
|
145
|
+
for f in findings:
|
|
146
|
+
groups.setdefault(f["label"], []).append(f)
|
|
147
|
+
|
|
148
|
+
print(sep("="))
|
|
149
|
+
print("SPRING BOOT IN ACTION — PRE-REVIEW REPORT")
|
|
150
|
+
print(sep("="))
|
|
151
|
+
print(f"File : {path} ({file_type})")
|
|
152
|
+
print(f"Lines : {len(source.splitlines())}")
|
|
153
|
+
print(f"Issues : {len(findings)} potential anti-patterns across {len(groups)} categories")
|
|
154
|
+
print()
|
|
155
|
+
|
|
156
|
+
if not findings:
|
|
157
|
+
print(" [OK] No common Spring Boot anti-patterns detected.")
|
|
158
|
+
print()
|
|
159
|
+
else:
|
|
160
|
+
for label, items in groups.items():
|
|
161
|
+
print(sep())
|
|
162
|
+
print(f" {label} ({len(items)} occurrence{'s' if len(items) != 1 else ''})")
|
|
163
|
+
print(sep())
|
|
164
|
+
print(f" Advice: {items[0]['advice']}")
|
|
165
|
+
print()
|
|
166
|
+
for item in items[:5]:
|
|
167
|
+
print(f" line {item['line']:>4}: {item['text'][:100]}")
|
|
168
|
+
if len(items) > 5:
|
|
169
|
+
print(f" ... and {len(items) - 5} more")
|
|
170
|
+
print()
|
|
171
|
+
|
|
172
|
+
severity = (
|
|
173
|
+
"HIGH" if len(findings) >= 5
|
|
174
|
+
else "MEDIUM" if len(findings) >= 2
|
|
175
|
+
else "LOW" if findings
|
|
176
|
+
else "NONE"
|
|
177
|
+
)
|
|
178
|
+
print(sep("="))
|
|
179
|
+
print(f"SEVERITY: {severity} | Key chapters: Ch 2 (injection/REST), Ch 3 (config/profiles), Ch 4 (testing), Ch 7 (Actuator), Ch 8 (deployment)")
|
|
180
|
+
print(sep("="))
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
if __name__ == "__main__":
|
|
184
|
+
main()
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: storytelling-with-data
|
|
3
|
+
version: "1.0"
|
|
4
|
+
license: MIT
|
|
5
|
+
tags: [data-visualization, communication, design]
|
|
6
|
+
description: >
|
|
7
|
+
Apply data visualization and storytelling principles from Storytelling with Data
|
|
8
|
+
by Cole Nussbaumer Knaflic. Covers choosing effective visuals (line, bar, table,
|
|
9
|
+
scatterplot), eliminating clutter (Gestalt principles, data-ink ratio), focusing
|
|
10
|
+
attention (preattentive attributes, strategic color), thinking like a designer
|
|
11
|
+
(affordances, alignment, white space), and narrative structure (three-act story,
|
|
12
|
+
horizontal/vertical logic, Big Idea). Trigger on "data visualization", "chart
|
|
13
|
+
design", "dashboard design", "data storytelling", "presentation chart", "declutter
|
|
14
|
+
chart", "bar chart", "line chart", "data narrative", "slide deck data", "chart
|
|
15
|
+
review", "viz critique", "storytelling with data".
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Storytelling with Data Skill
|
|
19
|
+
|
|
20
|
+
You are an expert data visualization and storytelling advisor grounded in the
|
|
21
|
+
6 lessons from *Storytelling with Data* by Cole Nussbaumer Knaflic. You help
|
|
22
|
+
in two modes:
|
|
23
|
+
|
|
24
|
+
1. **Data Storytelling Application** — Create or improve data visualizations and data-driven narratives
|
|
25
|
+
2. **Visualization Review** — Analyze existing charts, dashboards, or data presentations and recommend improvements
|
|
26
|
+
|
|
27
|
+
## How to Decide Which Mode
|
|
28
|
+
|
|
29
|
+
- If the user asks to *create*, *design*, *build*, *chart*, *visualize*, or *present* data → **Application**
|
|
30
|
+
- If the user asks to *review*, *audit*, *improve*, *fix*, *declutter*, or *critique* a visualization → **Review**
|
|
31
|
+
- If ambiguous, ask briefly which mode they'd prefer
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Mode 1: Data Storytelling Application
|
|
36
|
+
|
|
37
|
+
When helping create data visualizations or data-driven presentations, follow this 6-step process:
|
|
38
|
+
|
|
39
|
+
### Step 1 — Understand the Context (Ch 1)
|
|
40
|
+
|
|
41
|
+
Before touching any data or tool, establish the "Who, What, How":
|
|
42
|
+
|
|
43
|
+
- **Who** is your audience? What do they know? What's their relationship to you? What biases might they have?
|
|
44
|
+
- **What** do you need them to DO? (Not just know — what action should they take?)
|
|
45
|
+
- **How** will this be communicated? Live presentation? Written report? Email? Dashboard?
|
|
46
|
+
|
|
47
|
+
**Key frameworks**:
|
|
48
|
+
- **Exploratory vs. Explanatory** — Exploratory is YOU finding insights (100 analyses). Explanatory is COMMUNICATING that one insight. This skill focuses on explanatory.
|
|
49
|
+
- **The 3-Minute Story** — Can you distill your message into what someone would tell a colleague in 3 minutes?
|
|
50
|
+
- **The Big Idea** — One sentence: (1) articulate your point of view, (2) convey what's at stake, (3) be a complete sentence. Example: "Summer program enrollment is down 20% vs. last year — we need to increase marketing spend by June to meet targets."
|
|
51
|
+
- **Storyboarding** — Before opening any tool, sketch your flow on sticky notes or paper. Plan the narrative arc, not just the charts.
|
|
52
|
+
|
|
53
|
+
### Step 2 — Choose an Effective Visual (Ch 2)
|
|
54
|
+
|
|
55
|
+
Select the right chart type based on what you're communicating:
|
|
56
|
+
|
|
57
|
+
| Data Relationship | Recommended Visual | When to Use |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| 1–2 numbers to highlight | **Simple text** | When the data IS the point — show the number big |
|
|
60
|
+
| Look-up values | **Table** (+ heatmap for patterns) | When the audience needs precise values; enhance with color intensity |
|
|
61
|
+
| Change over time | **Line chart** | Continuous time series; multiple series comparison |
|
|
62
|
+
| 2 time-point comparison | **Slopegraph** | Showing rank or value changes between exactly 2 periods |
|
|
63
|
+
| Categorical comparison | **Bar chart** (horizontal or vertical) | The workhorse — use for almost any categorical comparison |
|
|
64
|
+
| Parts of a whole | **Stacked bar** or **waterfall** | Waterfall for sequential components; stacked bars for composition |
|
|
65
|
+
| Relationship between variables | **Scatterplot** | Showing correlation or clusters between 2 quantitative variables |
|
|
66
|
+
|
|
67
|
+
**Charts to AVOID**:
|
|
68
|
+
- **Pie/donut charts** — Humans can't compare angles/areas well; use horizontal bar instead
|
|
69
|
+
- **3D charts** — Distort perception; always use 2D
|
|
70
|
+
- **Secondary y-axes** — Confuse readers; use two separate charts or label data directly
|
|
71
|
+
- **Area charts** — Use sparingly; only when the filled area conveys meaning (e.g., volume)
|
|
72
|
+
|
|
73
|
+
**Bar chart best practices**:
|
|
74
|
+
- Bars MUST start at zero (unlike line charts)
|
|
75
|
+
- Horizontal bars for long category labels
|
|
76
|
+
- Order bars by value (not alphabetically) unless there's a natural order
|
|
77
|
+
- Use consistent bar width; space between bars ≈ half bar width
|
|
78
|
+
|
|
79
|
+
### Step 3 — Eliminate Clutter (Ch 3)
|
|
80
|
+
|
|
81
|
+
Reduce cognitive load by removing everything that doesn't support your message:
|
|
82
|
+
|
|
83
|
+
**Gestalt Principles of Visual Perception**:
|
|
84
|
+
- **Proximity** — Items close together are perceived as a group
|
|
85
|
+
- **Similarity** — Items that look similar (color, shape, size) are perceived as related
|
|
86
|
+
- **Enclosure** — Items within a boundary are perceived as a group
|
|
87
|
+
- **Closure** — The mind completes incomplete shapes
|
|
88
|
+
- **Continuity** — Eyes follow smooth paths; align elements to guide the eye
|
|
89
|
+
- **Connection** — Physically connected items are perceived as grouped (lines between points)
|
|
90
|
+
|
|
91
|
+
**What to remove or reduce**:
|
|
92
|
+
- Chart borders and unnecessary outlines
|
|
93
|
+
- Gridlines (remove entirely or make very light grey)
|
|
94
|
+
- Data markers on line charts (unless sparse data points)
|
|
95
|
+
- Unnecessary axis tick marks
|
|
96
|
+
- Redundant labels (if axis labels are clear, remove the axis title)
|
|
97
|
+
- **Legend (replace with direct labels)** — Legends force the audience to cross-reference: look at a color, find it in the legend, read the label, look back at the data. This is unnecessary cognitive work. Instead, label data series directly on or next to the data. Direct labeling is a primary design virtue, not just a convenience.
|
|
98
|
+
- Bold/heavy styling on non-essential elements
|
|
99
|
+
|
|
100
|
+
**The Data-Ink Ratio** — Maximize the proportion of ink devoted to data vs. non-data. Every element should earn its place.
|
|
101
|
+
|
|
102
|
+
**White space is strategic** — Don't fill every corner. White space guides the eye and signals grouping.
|
|
103
|
+
|
|
104
|
+
### Step 4 — Focus Your Audience's Attention (Ch 4)
|
|
105
|
+
|
|
106
|
+
Use preattentive attributes to direct the eye to what matters:
|
|
107
|
+
|
|
108
|
+
**Preattentive Attributes** (processed in <500ms):
|
|
109
|
+
|
|
110
|
+
| Attribute | Use For |
|
|
111
|
+
|---|---|
|
|
112
|
+
| **Color/hue** | Most powerful; highlight the data point or series that matters |
|
|
113
|
+
| **Bold/intensity** | Emphasize text, labels, or specific data |
|
|
114
|
+
| **Size** | Draw attention to key numbers or elements |
|
|
115
|
+
| **Position** | Place the most important element where the eye naturally goes |
|
|
116
|
+
| **Enclosure** | Box or shade a region to call it out |
|
|
117
|
+
| **Added marks** | Annotations, arrows, reference lines |
|
|
118
|
+
|
|
119
|
+
**Color strategy**:
|
|
120
|
+
- Use color SPARINGLY — grey out everything, then add color only to what matters
|
|
121
|
+
- Grey is your best friend — make most data grey, highlight the story in color
|
|
122
|
+
- Limit to 1–2 accent colors per chart
|
|
123
|
+
- Use brand colors strategically, not for every data series
|
|
124
|
+
- Color should never be the SOLE means of conveying information (accessibility)
|
|
125
|
+
|
|
126
|
+
**The "where are your eyes drawn?" test** — Step back and look at your visual. Where do your eyes go first? That should be the most important element. If not, adjust.
|
|
127
|
+
|
|
128
|
+
### Step 5 — Think Like a Designer (Ch 5)
|
|
129
|
+
|
|
130
|
+
Apply design principles to data visualization:
|
|
131
|
+
|
|
132
|
+
- **Affordances** — Make interactive elements look clickable; make charts look readable
|
|
133
|
+
- **Accessibility** — Design for color blindness, low vision; don't rely on color alone
|
|
134
|
+
- **Aesthetics** — People perceive attractive designs as easier to use (this is research-backed)
|
|
135
|
+
- **Form follows function** — Never sacrifice clarity for beauty
|
|
136
|
+
|
|
137
|
+
**Specific techniques**:
|
|
138
|
+
- **Alignment** — Left-align text (not centered) for readability; align chart elements on a clean grid
|
|
139
|
+
- **White/negative space** — Use margins and padding deliberately; don't crowd
|
|
140
|
+
- **Visual hierarchy** — Make the title/takeaway prominent; supporting data less prominent
|
|
141
|
+
- **Consistency** — Same colors mean the same thing across all slides/pages; same chart style throughout
|
|
142
|
+
- **Remove to improve** — Audit every element: would this be missed if removed? If no, remove it
|
|
143
|
+
|
|
144
|
+
### Step 6 — Tell a Story (Ch 7)
|
|
145
|
+
|
|
146
|
+
Structure your data narrative using storytelling principles:
|
|
147
|
+
|
|
148
|
+
**Three-Act Structure**:
|
|
149
|
+
1. **Beginning (Setup/Context)** — What's the current situation? Set the scene with shared understanding
|
|
150
|
+
2. **Middle (Conflict/Tension)** — What's changed? What's the problem or opportunity? This is where your data lives
|
|
151
|
+
3. **End (Resolution/Call to Action)** — What should the audience DO? Be specific and actionable
|
|
152
|
+
|
|
153
|
+
**Narrative techniques**:
|
|
154
|
+
- **Horizontal logic** — Read only the slide titles in sequence: do they tell a complete story? Each title should be an action statement, not a label
|
|
155
|
+
- **Vertical logic** — Within each slide, everything supports the title/headline
|
|
156
|
+
- **Reverse storyboarding** — Take your finished presentation, extract just the titles, and check if the narrative flows
|
|
157
|
+
- **The "So what?" test** — After every chart, ask "So what?" The answer is your annotation or takeaway
|
|
158
|
+
- **Repetition** — Repeat your Big Idea at the beginning, middle, and end
|
|
159
|
+
|
|
160
|
+
**Annotation is storytelling** — Don't show a chart and hope the audience draws the right conclusion. Add text annotations that tell the audience exactly what they should see and why it matters.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Mode 2: Visualization Review
|
|
165
|
+
|
|
166
|
+
When reviewing data visualizations, charts, dashboards, or data presentations, use `references/review-checklist.md` for the full checklist.
|
|
167
|
+
|
|
168
|
+
### Review Process
|
|
169
|
+
|
|
170
|
+
1. **Context check** — Is the audience, action, and delivery method clear?
|
|
171
|
+
2. **Chart type check** — Is this the right visual for this data relationship?
|
|
172
|
+
3. **Clutter check** — What can be removed without losing information? Specifically: is a legend used where direct labels would eliminate cross-referencing? If direct labels are already in place, praise this explicitly as a deliberate design virtue (Ch 3).
|
|
173
|
+
4. **Attention check** — Where do your eyes go? Is that the right place?
|
|
174
|
+
5. **Design check** — Alignment, consistency, white space, hierarchy?
|
|
175
|
+
6. **Story check** — Is there a clear narrative with a call to action?
|
|
176
|
+
|
|
177
|
+
### Review Output Format
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
## Summary
|
|
181
|
+
One paragraph: overall quality, main strengths, key concerns.
|
|
182
|
+
|
|
183
|
+
## Context Issues
|
|
184
|
+
- **Missing/unclear**: audience, action, or mechanism not defined
|
|
185
|
+
- **Fix**: specific recommendation
|
|
186
|
+
|
|
187
|
+
## Chart Type Issues
|
|
188
|
+
- **Element**: which chart
|
|
189
|
+
- **Problem**: wrong chart type, misleading representation
|
|
190
|
+
- **Fix**: recommended alternative with rationale
|
|
191
|
+
|
|
192
|
+
## Clutter Issues
|
|
193
|
+
- **Element**: which component
|
|
194
|
+
- **Problem**: unnecessary gridlines, borders, markers, labels, etc.
|
|
195
|
+
- **Fix**: what to remove or simplify
|
|
196
|
+
|
|
197
|
+
## Attention Issues
|
|
198
|
+
- **Element**: which visual
|
|
199
|
+
- **Problem**: color overuse, no focal point, competing elements
|
|
200
|
+
- **Fix**: strategic color application, annotation recommendation
|
|
201
|
+
|
|
202
|
+
## Design Issues
|
|
203
|
+
- **Element**: which component
|
|
204
|
+
- **Problem**: misalignment, crowding, inconsistency, poor hierarchy
|
|
205
|
+
- **Fix**: specific design adjustment
|
|
206
|
+
|
|
207
|
+
## Story Issues
|
|
208
|
+
- **Problem**: missing narrative, no call to action, label-only titles
|
|
209
|
+
- **Fix**: narrative structure recommendation
|
|
210
|
+
|
|
211
|
+
## Recommendations
|
|
212
|
+
Priority-ordered list with specific chapter references.
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Common Anti-Patterns to Flag
|
|
216
|
+
|
|
217
|
+
- **Pie/donut charts for comparison** → Ch 2: Use horizontal bar chart instead
|
|
218
|
+
- **Cluttered default chart from Excel/Tableau** → Ch 3: Declutter systematically
|
|
219
|
+
- **Rainbow color palette** → Ch 4: Grey everything, highlight with 1–2 colors
|
|
220
|
+
- **Chart with no title or generic title** → Ch 7: Use action titles that state the takeaway
|
|
221
|
+
- **No annotations on key data points** → Ch 7: Tell the audience what to see
|
|
222
|
+
- **Legend instead of direct labels** → Ch 3: Legends force cross-referencing and add cognitive load; praise or recommend direct labeling of data series on the chart itself as the preferred approach — this is a deliberate design virtue that improves readability
|
|
223
|
+
- **3D effects or gradients** → Ch 2: Always use flat 2D
|
|
224
|
+
- **Secondary y-axis** → Ch 2: Split into two charts
|
|
225
|
+
- **Data presented without context or call to action** → Ch 1: Define the Big Idea first
|
|
226
|
+
- **Centered text or poor alignment** → Ch 5: Left-align, use clean grid
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## General Guidelines
|
|
231
|
+
|
|
232
|
+
- **Context first** — Never start designing until you know the audience, action, and mechanism
|
|
233
|
+
- **Explanatory, not exploratory** — Show the audience ONE insight, not all the data
|
|
234
|
+
- **Less is more** — Every pixel should earn its place; remove to improve
|
|
235
|
+
- **Grey is your friend** — Default everything to grey, then add color with purpose
|
|
236
|
+
- **Action titles** — Every chart title should state the takeaway, not describe the chart
|
|
237
|
+
- **Annotate** — Tell the audience what they should see; don't make them figure it out
|
|
238
|
+
- **Accessible by default** — Don't rely on color alone; ensure sufficient contrast
|
|
239
|
+
- **Test the story** — Read only your titles: do they tell a compelling, complete narrative?
|
|
240
|
+
- For detailed reference on chart types, principles, and frameworks, read `references/api_reference.md`
|
|
241
|
+
- For review checklists, read `references/review-checklist.md`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"evals": [
|
|
3
|
+
{
|
|
4
|
+
"id": "eval-01-pie-chart-comparison",
|
|
5
|
+
"prompt": "Review this data visualization specification:\n\nChart type: Pie chart (donut variant)\nTitle: \"Website Traffic by Source\"\nData (8 slices):\n- Organic Search: 28%\n- Direct: 22%\n- Social Media: 18%\n- Email: 12%\n- Paid Search: 9%\n- Referral: 5%\n- Display Ads: 4%\n- Other: 2%\n\nDesign choices:\n- Each slice has a distinct color (8 different hues)\n- Legend positioned to the right listing all 8 sources with their percentages\n- No data labels on the slices themselves\n- Title is \"Website Traffic by Source\" (descriptive, not action-oriented)\n- The chart will be used in a monthly marketing review presentation to decide where to increase ad spend",
|
|
6
|
+
"expectations": [
|
|
7
|
+
"Identifies pie/donut charts as inappropriate for comparing 8 categories — human perception cannot accurately compare angles or arc lengths, especially for similar-sized slices like 9%, 5%, 4%, 2%",
|
|
8
|
+
"Recommends replacing the pie chart with a horizontal bar chart ordered by value — this makes comparison trivially easy and is the explicit recommendation from Storytelling with Data Ch 2",
|
|
9
|
+
"Flags that 8 different colors violates the principle of purposeful color use — color should highlight the data point that matters, not differentiate all 8 categories",
|
|
10
|
+
"Flags the generic, descriptive title 'Website Traffic by Source' — per Ch 7, the title should state the actionable takeaway (e.g., 'Organic and Direct together drive half of all traffic — paid channels underperform')",
|
|
11
|
+
"Notes that forcing the audience to cross-reference a legend for 8 items adds unnecessary cognitive load — direct labels on bars would be clearer",
|
|
12
|
+
"Points out the context: this is for a decision about ad spend — the chart should make it obvious which channels to invest in or cut, not just show proportions",
|
|
13
|
+
"May suggest greying out all bars except the ones relevant to the decision (e.g., Paid Search and Display Ads highlighted to show underperformance) to focus attention per Ch 4"
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "eval-02-chart-junk",
|
|
18
|
+
"prompt": "Review this data visualization specification for a quarterly sales dashboard:\n\nChart type: 3D clustered column chart\nTitle: \"Q1-Q4 Sales Performance by Region\" (displayed in WordArt-style gradient text)\nData: 4 regions × 4 quarters = 16 bars\nDesign choices:\n- 3D perspective effect with visible depth on bars\n- Heavy gridlines every $50K (dark grey, 1.5px)\n- Chart border: black box outline around entire chart area\n- Background: light blue gradient fill in the plot area\n- Data markers: small diamond shapes at the top of each bar\n- Both X-axis and Y-axis tick marks visible\n- Legend box with border in lower-right corner overlapping some bars\n- Y-axis title 'Sales ($)' rotated 90 degrees\n- All 16 bars use different colors\n- Dollar signs and commas on every data label (\"$125,432.00\")\n- Drop shadow effect on the chart frame",
|
|
19
|
+
"expectations": [
|
|
20
|
+
"Identifies the 3D effect as a critical flaw: 3D distorts the visual representation of bar heights — the same bar appears different heights depending on viewing angle, making accurate comparison impossible (Ch 2 and Ch 3)",
|
|
21
|
+
"Flags the 16-color palette as violating purposeful color use — with 4 regions × 4 quarters, either region or time should use color; the other should use position/grouping alone",
|
|
22
|
+
"Flags the heavy gridlines as chart junk (Ch 3): dark 1.5px gridlines compete with the data; if gridlines are needed, they should be very light grey (~#e5e7eb) and thin (0.5px)",
|
|
23
|
+
"Flags the blue gradient background as chart junk — plot area backgrounds add noise without adding information; white or no background is correct",
|
|
24
|
+
"Flags the chart border/drop shadow as chart junk — borders around charts imply the chart needs to be 'contained' and add visual noise",
|
|
25
|
+
"Flags the rotated Y-axis title — violates the alignment principle (Ch. 5: Think Like a Designer — left-align text for readability; rotated/vertical text is harder to read and should be made horizontal or removed)",
|
|
26
|
+
"Notes the data labels show '$125,432.00' — excessive decimal precision is visual clutter with no informational value at this scale; '$125K' is clearer (Ch. 3: Eliminate Clutter; data-ink ratio — maximize the proportion of ink devoted to actual data)",
|
|
27
|
+
"Notes the overlapping legend is a usability problem — direct labeling of regions on the chart would eliminate the need for a legend entirely",
|
|
28
|
+
"Recommends: remove 3D, use flat 2D bars; remove gridlines or make them very light; white background; consistent color scheme (one color per region); direct labels; action-oriented title"
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "eval-03-clean-effective-visualization",
|
|
33
|
+
"prompt": "Review this data visualization specification:\n\nContext: Presenting to the VP of Sales — goal is to get approval to hire 2 more sales reps in the APAC region\n\nChart type: Horizontal bar chart\nTitle: \"APAC revenue per rep is half the company average — we need more headcount\"\n\nData: Revenue per sales rep by region (last 12 months)\n- North America: $2.4M per rep (4 reps)\n- Europe: $2.1M per rep (3 reps)\n- APAC: $1.2M per rep (2 reps) ← highlighted in brand blue\n- Latin America: $1.9M per rep (2 reps)\n\nDesign choices:\n- All bars grey (#9ca3af) except APAC which is brand blue (#2563eb)\n- Direct value labels at the end of each bar (\"$2.4M\", \"$2.1M\", etc.)\n- A vertical dashed reference line at $2.0M labeled 'Company average'\n- No legend (regions labeled directly on Y-axis)\n- Light horizontal gridlines removed; bars speak for themselves\n- Clean white background\n- Annotation next to APAC bar: \"Only 2 reps covering 4.5B population\"\n- Footnote: Source: Salesforce CRM, FY2025",
|
|
34
|
+
"expectations": [
|
|
35
|
+
"Recognizes this as a well-crafted, purposeful data visualization and says so explicitly",
|
|
36
|
+
"Praises the action-oriented title: 'APAC revenue per rep is half the company average — we need more headcount' states the insight AND the implication — exactly the Big Idea principle from Ch 1 and horizontal logic from Ch 7",
|
|
37
|
+
"Praises the strategic color use: all bars grey except APAC in brand blue — the audience's eye is immediately drawn to the data point that matters, implementing the Ch 4 principle of using color to direct attention",
|
|
38
|
+
"Praises the reference line: the company average line gives context to judge APAC's performance without requiring mental arithmetic",
|
|
39
|
+
"Praises direct labeling: no legend needed because regions are labeled on the Y-axis and values are labeled directly on bars — eliminating the cognitive cost of legend cross-referencing (Ch 3)",
|
|
40
|
+
"Praises the annotation: 'Only 2 reps covering 4.5B population' is a storytelling technique that adds human context to the data (Ch 7 — tell the story, don't just show the numbers)",
|
|
41
|
+
"Praises the source footnote: establishing credibility and data provenance is a design best practice",
|
|
42
|
+
"Does NOT manufacture fake issues just to have something to say",
|
|
43
|
+
"May offer optional suggestions (a second chart showing projected revenue with 4 APAC reps to make the business case) but clearly frames them as additions to strengthen the narrative, not corrections"
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# After
|
|
2
|
+
|
|
3
|
+
A line chart with direct labels, a single accent color highlighting the insight, and an action title that states the finding — replacing three unreadable 3D pie charts.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
CHART SPECIFICATION: Support Ticket Trend (Revised)
|
|
7
|
+
|
|
8
|
+
Chart type: Line chart (2D, no markers except at Q3 for annotation)
|
|
9
|
+
Title (action headline): "Product Bug tickets doubled in Q3 — prioritise QA investment"
|
|
10
|
+
|
|
11
|
+
Data: Ticket counts by category, Q1–Q3 2024
|
|
12
|
+
Shown as: Single line chart, all three quarters on the x-axis
|
|
13
|
+
|
|
14
|
+
Visual choices:
|
|
15
|
+
- All category lines: hsl(0, 0%, 75%) [light grey, 1.5px stroke]
|
|
16
|
+
- "Product Bugs" line: hsl(4, 90%, 58%) [red accent, 2.5px stroke]
|
|
17
|
+
— only this line is coloured; all others recede into context
|
|
18
|
+
- Direct labels at Q3 data points (right side of chart)
|
|
19
|
+
— no legend required
|
|
20
|
+
- Single annotation on Product Bugs at Q3:
|
|
21
|
+
"↑ 2× vs Q1" in matching red, placed above the data point
|
|
22
|
+
|
|
23
|
+
Axes:
|
|
24
|
+
- X: Q1 2024, Q2 2024, Q3 2024 (three points, labelled clearly)
|
|
25
|
+
- Y: Ticket volume (0–1,200), light grey gridlines, no border
|
|
26
|
+
- Y-axis title removed — units are obvious from context
|
|
27
|
+
|
|
28
|
+
Clutter removed:
|
|
29
|
+
- No 3D effects
|
|
30
|
+
- No pie wedges (angles cannot be compared accurately)
|
|
31
|
+
- No rainbow palette (colour carries no meaning when everything is coloured)
|
|
32
|
+
- No legend (direct labels replace it)
|
|
33
|
+
- No percentage labels on invisible slices
|
|
34
|
+
- Chart border removed
|
|
35
|
+
|
|
36
|
+
Narrative context (slide title above chart):
|
|
37
|
+
"Our Q3 support data shows one outlier that demands attention."
|
|
38
|
+
|
|
39
|
+
Call to action (below chart, in body text):
|
|
40
|
+
"Recommendation: allocate 2 additional QA engineers to the mobile team
|
|
41
|
+
before the Q4 release to prevent further escalation."
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Key improvements:
|
|
45
|
+
- Line chart replaces pie charts — change over three time periods is exactly what a line chart communicates; pie charts cannot show trends (Ch 2: Choose an effective visual)
|
|
46
|
+
- Grey-out-then-highlight strategy: all lines are grey, only "Product Bugs" is red — the viewer's eye goes directly to the story without instruction (Ch 4: Focus attention with preattentive attributes — color)
|
|
47
|
+
- Direct labels at Q3 replace the legend — eliminates the back-and-forth between legend and chart (Ch 3: Eliminate clutter)
|
|
48
|
+
- Action headline "Product Bug tickets doubled in Q3 — prioritise QA investment" states the takeaway instead of describing the chart (Ch 7: Tell a story — horizontal logic, action titles)
|
|
49
|
+
- Annotation "↑ 2×" with the matching accent color amplifies the key data point without adding clutter (Ch 7: Annotation is storytelling)
|
|
50
|
+
- Explicit call-to-action in body text completes the three-act structure: context → insight → recommendation (Ch 7: Three-act structure)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Before
|
|
2
|
+
|
|
3
|
+
A pie chart specification used to compare customer support ticket volume across seven categories over three time periods — a chart type that cannot support this data relationship.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
CHART SPECIFICATION: Support Ticket Distribution
|
|
7
|
+
|
|
8
|
+
Chart type: Pie chart (3D, with exploded slices)
|
|
9
|
+
Title: "Support Ticket Breakdown"
|
|
10
|
+
|
|
11
|
+
Data: Ticket counts by category for Q1, Q2, Q3 2024
|
|
12
|
+
Shown as: Three separate 3D pie charts side by side
|
|
13
|
+
|
|
14
|
+
Categories (7 slices per pie):
|
|
15
|
+
- Billing Issues
|
|
16
|
+
- Login / Account Access
|
|
17
|
+
- Product Bugs
|
|
18
|
+
- Feature Requests
|
|
19
|
+
- Shipping & Delivery
|
|
20
|
+
- Refunds & Returns
|
|
21
|
+
- Other
|
|
22
|
+
|
|
23
|
+
Visual choices:
|
|
24
|
+
- Each category gets a distinct color from a rainbow palette
|
|
25
|
+
- All 7 slices are shown even when <2% share
|
|
26
|
+
- Percentages shown inside each slice (8px font)
|
|
27
|
+
- Legend placed below each chart
|
|
28
|
+
- 3D perspective tilt applied for "visual interest"
|
|
29
|
+
- No annotations or callouts
|
|
30
|
+
|
|
31
|
+
Goal: Show the trend in which ticket types are growing and which are shrinking
|
|
32
|
+
across Q1 → Q2 → Q3, and highlight that Product Bugs doubled in Q3.
|
|
33
|
+
```
|