{"id":"857a1ec8-5059-41d2-b18a-62ad23d5c33e","shortId":"C9btYW","kind":"skill","title":"blog-chart","tagline":"Generate dark-mode-compatible inline SVG data visualization charts for blog posts. Supports horizontal bar, grouped bar, donut, line, lollipop, area, and radar charts with automatic platform detection (HTML vs JSX/MDX). Enforces chart type diversity, accessible markup (role=img, ","description":"# Blog Chart -- Built-In SVG Data Visualization\n\nGenerates dark-mode-compatible inline SVG charts for blog posts. Invoked\ninternally by `blog-write` and `blog-rewrite` when chart-worthy data is\nidentified. Not a standalone user-facing command.\n\n**Styling source of truth:** `references/visual-media.md`\n\n## Input Format\n\nThe writer or researcher passes a chart request:\n\n```\nChart Request:\n- Type: horizontal bar\n- Title: \"AI Citation Sources by Platform\"\n- Data: ChatGPT 43.8%, Perplexity 6.6%, Google AI Overviews 2.2%, Reddit 7.15%\n- Source: Ahrefs, December 2025\n- Platform: mdx (or html)\n```\n\n## Chart Type Selection\n\nSelect based on the data pattern. Diversity is mandatory - never repeat a\ntype within one post.\n\n| Data Pattern | Best Chart Type |\n|-------------|-----------------|\n| Before/after comparison | Grouped bar chart |\n| Ranked factors / correlations | Lollipop chart |\n| Parts of whole / market share | Donut chart |\n| Trend over time | Line chart |\n| Percentage improvement | Horizontal bar chart |\n| Distribution / range | Area chart |\n| Multi-dimensional scoring | Radar chart |\n\n## Styling Rules (Non-Negotiable)\n\nAll charts must work on both dark and light backgrounds:\n\n```\nText elements:     fill=\"currentColor\"\nGrid lines:        stroke=\"currentColor\" opacity=\"0.08\"\nAxis lines:        stroke=\"currentColor\" opacity=\"0.3\"\nBackground:        transparent (no fill on root SVG)\nSubtitle text:     fill=\"currentColor\" opacity=\"0.45\"\nSource text:        fill=\"currentColor\" opacity=\"0.35\"\nLabel text:        fill=\"currentColor\" opacity=\"0.8\"\n```\n\n### Color Palette\n\n| Color | Hex | Use Case |\n|-------|-----|----------|\n| Orange | `#f97316` | Primary / highest value |\n| Sky Blue | `#38bdf8` | Secondary / comparison |\n| Purple | `#a78bfa` | Tertiary / special category |\n| Green | `#22c55e` | Quaternary / positive indicator |\n\nFor text inside colored elements: `fill=\"white\"` with `fontWeight=\"800\"`.\n\n## Standard SVG Shell (HTML)\n\n```xml\n<svg\n  viewBox=\"0 0 560 380\"\n  style=\"max-width: 100%; height: auto; font-family: 'Inter', system-ui, sans-serif\"\n  role=\"img\"\n  aria-label=\"Chart description with key data point\"\n>\n  <title>Chart Title</title>\n  <desc>Description for screen readers with all key data points and source</desc>\n\n  <!-- Chart content -->\n\n  <text x=\"280\" y=\"372\" text-anchor=\"middle\" font-size=\"10\" fill=\"currentColor\" opacity=\"0.35\">\n    Source: Source Name (Year)\n  </text>\n</svg>\n```\n\n## JSX/MDX Shell (camelCase attributes)\n\n```jsx\n<svg\n  viewBox=\"0 0 560 380\"\n  style={{maxWidth: '100%', height: 'auto', fontFamily: \"'Inter', system-ui, sans-serif\"}}\n  role=\"img\"\n  aria-label=\"Chart description\"\n>\n  <title>Chart Title</title>\n  <desc>Description for screen readers</desc>\n\n  {/* Chart content */}\n\n  <text x=\"280\" y=\"372\" textAnchor=\"middle\" fontSize=\"10\" fill=\"currentColor\" opacity=\"0.35\">\n    Source: Source Name (Year)\n  </text>\n</svg>\n```\n\n## JSX Attribute Conversion (Required for MDX)\n\n| HTML | JSX |\n|------|-----|\n| `stroke-width` | `strokeWidth` |\n| `stroke-dasharray` | `strokeDasharray` |\n| `stroke-linecap` | `strokeLinecap` |\n| `text-anchor` | `textAnchor` |\n| `font-size` | `fontSize` |\n| `font-weight` | `fontWeight` |\n| `font-family` | `fontFamily` |\n| `class` | `className` |\n| `style=\"...\"` | `style={{...}}` |\n\n## Chart Type Construction\n\n### Horizontal Bar Chart\n\nBest for: percentage improvements, single-metric comparisons.\n\n1. Define chart area: x=80, y=40, width=440, height=280\n2. Calculate bar height: `chartHeight / dataCount - gap` (gap=8)\n3. Calculate bar width: `(value / maxValue) * chartWidth`\n4. Position bars: `y = chartY + index * (barHeight + gap)`\n5. Label on left (right-aligned at x=75): category name\n6. Value label at end of bar: percentage or number\n7. Source text at bottom center\n\n### Grouped Bar Chart\n\nBest for: before/after, A vs B comparisons.\n\n1. Define groups along Y axis, bars within each group\n2. Use 2 colors (primary + secondary) for the two series\n3. Add legend at top: colored square + label for each series\n4. Gap between groups > gap within groups\n\n### Donut Chart\n\nBest for: parts of whole, market share.\n\n1. Center: cx=280, cy=180, outer radius=140, inner radius=80\n2. Calculate arc segments using cumulative angles\n3. Each segment: `<path d=\"M... A... L... A... Z\" fill=\"color\" />`\n4. Center text: total or key label\n5. Legend below chart with color squares + labels + values\n\n### Line Chart\n\nBest for: trends over time.\n\n1. X axis: time periods, evenly spaced\n2. Y axis: value range with 4-5 grid lines\n3. Draw grid lines: `stroke=\"currentColor\" opacity=\"0.08\"`\n4. Plot data points: `<circle cx=... cy=... r=\"4\" fill=\"color\" />`\n5. Connect with: `<polyline points=\"...\" fill=\"none\" stroke=\"color\" strokeWidth=\"2\" />`\n6. Optional: area fill below line with `opacity=\"0.1\"`\n\n### Lollipop Chart\n\nBest for: ranked factors, correlations.\n\n1. Horizontal orientation (like bar chart but with circles)\n2. Thin line from axis to data point: `stroke=\"currentColor\" opacity=\"0.15\" strokeWidth=\"1\"`\n3. Circle at data point: `r=\"6\"` with fill color\n4. Value label next to circle\n5. Categories on Y axis (left-aligned)\n\n### Area Chart\n\nBest for: distribution, cumulative data.\n\n1. Same as line chart but with filled area below\n2. Area fill: `<path d=\"M... L... L... Z\" fill=\"color\" opacity=\"0.15\" />`\n3. Line on top: `stroke=\"color\" strokeWidth=\"2\" fill=\"none\"`\n4. Grid lines behind the area\n\n### Radar Chart\n\nBest for: multi-dimensional scoring (5-7 axes).\n\n1. Center: cx=280, cy=190\n2. Draw concentric polygons for grid (3-4 levels)\n3. Calculate axis endpoints at equal angles\n4. Plot data points on each axis proportional to value\n5. Connect data points with filled polygon: `fill=\"color\" opacity=\"0.2\" stroke=\"color\"`\n6. Label each axis at the outer edge\n\n## Output Format\n\nWrap every chart in a `<figure>` element:\n\n**HTML:**\n```html\n<figure>\n  <svg viewBox=\"0 0 560 380\" style=\"max-width: 100%; height: auto; font-family: 'Inter', system-ui, sans-serif\" role=\"img\" aria-label=\"[description]\">\n    <title>[Chart Title]</title>\n    <desc>[Full description with data points for screen readers]</desc>\n    <!-- chart content -->\n    <text x=\"280\" y=\"372\" text-anchor=\"middle\" font-size=\"10\" fill=\"currentColor\" opacity=\"0.35\">\n      Source: [Source Name] ([Year])\n    </text>\n  </svg>\n</figure>\n```\n\n**MDX:**\n```mdx\n<figure className=\"chart-container\" style={{margin: '2.5rem 0', textAlign: 'center', padding: '1.5rem', borderRadius: '12px'}}>\n  <svg viewBox=\"0 0 560 380\" style={{maxWidth: '100%', height: 'auto', fontFamily: \"'Inter', system-ui, sans-serif\"}} role=\"img\" aria-label=\"[description]\">\n    <title>[Chart Title]</title>\n    <desc>[Full description]</desc>\n    {/* chart content with camelCase attributes */}\n    <text x=\"280\" y=\"372\" textAnchor=\"middle\" fontSize=\"10\" fill=\"currentColor\" opacity=\"0.35\">\n      Source: [Source Name] ([Year])\n    </text>\n  </svg>\n</figure>\n```\n\n## Quality Checklist (Verify Before Returning)\n\n- [ ] No hardcoded text colors (all use `currentColor`)\n- [ ] No white/light backgrounds (transparent or none)\n- [ ] Source attribution text present at bottom\n- [ ] `role=\"img\"` and `aria-label` present on `<svg>`\n- [ ] `<title>` and `<desc>` present inside `<svg>`\n- [ ] Chart type not already used in this post\n- [ ] If MDX: all attributes camelCased (no hyphens in attribute names)\n- [ ] Data values match the source data exactly\n- [ ] Color palette uses only approved colors\n- [ ] ViewBox is `0 0 560 380` (standard) or justified alternative","tags":["blog","chart","claude","agricidaniel","agent-skills","ai-citations","ai-content","ai-marketing","ai-marketing-hub","blog-writing","claude-code","claude-code-skill"],"capabilities":["skill","source-agricidaniel","skill-blog-chart","topic-agent-skills","topic-ai-citations","topic-ai-content","topic-ai-marketing","topic-ai-marketing-hub","topic-blog","topic-blog-writing","topic-claude-code","topic-claude-code-skill","topic-claude-plugin","topic-claude-skill","topic-content-creation"],"categories":["claude-blog"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/AgriciDaniel/claude-blog/blog-chart","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add AgriciDaniel/claude-blog","source_repo":"https://github.com/AgriciDaniel/claude-blog","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 753 github stars · SKILL.md body (7,487 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:53:29.725Z","embedding":null,"createdAt":"2026-05-18T12:54:52.243Z","updatedAt":"2026-05-18T18:53:29.725Z","lastSeenAt":"2026-05-18T18:53:29.725Z","tsv":"'-4':725 '-5':584 '-7':710 '0':314,315,800,810,811,914,915 '0.08':217,594 '0.1':610 '0.15':638 '0.2':754 '0.3':223 '0.35':242 '0.45':236 '0.8':248 '1':404,478,525,570,618,640,672,712 '1.5':804 '100':320,816 '12px':807 '140':533 '180':530 '190':717 '2':416,488,490,537,577,627,682,692,718 '2.2':121 '2.5':798 '2025':127 '22c55e':271 '280':415,528,715 '3':425,498,544,587,641,685,724,727 '380':317,813,917 '38bdf8':262 '4':432,509,547,583,595,651,695,734 '40':411 '43.8':115 '440':413 '5':440,554,599,657,709,744 '560':316,812,916 '6':452,602,647,757 '6.6':117 '7':462 '7.15':123 '75':449 '8':424 '80':409,536 '800':284 'a78bfa':266 'access':40 'add':499 'ahref':125 'ai':108,119 'align':446,664 'along':481 'alreadi':884 'altern':921 'anchor':372 'angl':543,733 'approv':910 'arc':539 'area':25,185,407,604,665,680,683,700 'aria':334,830,874 'aria-label':333,829,873 'attribut':310,351,841,865,892,897 'auto':322,818 'automat':30 'axe':711 'axi':218,483,572,579,631,661,729,740,760 'b':476 'background':207,224,860 'bar':19,21,106,159,181,394,418,427,434,458,469,484,622 'barheight':438 'base':136 'before/after':156,473 'behind':698 'best':153,396,471,518,565,613,667,703 'blog':2,15,44,61,67,71 'blog-chart':1 'blog-rewrit':70 'blog-writ':66 'blue':261 'borderradius':806 'bottom':466,869 'built':47 'built-in':46 'calcul':417,426,538,728 'camelcas':309,840,893 'case':254 'categori':269,450,658 'center':467,526,548,713,802 'chart':3,13,28,37,45,59,75,100,102,132,154,160,165,172,177,182,186,192,199,290,336,338,344,390,395,406,470,517,557,564,612,623,666,676,702,769,775,794,833,837,881 'chart-contain':793 'chart-worthi':74 'chartheight':420 'charti':436 'chartwidth':431 'chatgpt':114 'checklist':847 'circl':626,642,656 'citat':109 'class':386 'classnam':387,792 'color':249,251,278,491,503,559,650,690,752,756,854,906,911 'command':86 'comparison':157,264,403,477 'compat':8,56 'concentr':720 'connect':600,745 'construct':392 'contain':795 'content':345,838 'convers':352 'correl':163,617 'cumul':542,670 'currentcolor':211,215,221,234,240,246,592,636,857 'cx':527,714 'cy':529,716 'dark':6,54,204 'dark-mode-compat':5,53 'dasharray':364 'data':11,50,77,113,139,151,299,597,633,644,671,736,746,780,899,904 'datacount':421 'decemb':126 'defin':405,479 'descript':292,337,340,778,832,836 'detect':32 'dimension':189,707 'distribut':183,669 'divers':39,141 'donut':22,171,516 'draw':588,719 'edg':764 'element':209,279,772 'end':456 'endpoint':730 'enforc':36 'equal':732 'even':575 'everi':768 'exact':905 'f97316':256 'face':85 'factor':162,616 'famili':384 'figur':791 'fill':210,227,233,239,245,280,605,649,679,684,693,749,751 'font':375,379,383 'font-famili':382 'font-siz':374 'font-weight':378 'fontfamili':323,385,819 'fontsiz':377 'fontweight':283,381 'format':93,766 'full':777,835 'gap':422,423,439,510,513 'generat':4,52 'googl':118 'green':270 'grid':212,585,589,696,723 'group':20,158,468,480,487,512,515 'hardcod':852 'height':321,414,419,817 'hex':252 'highest':258 'horizont':18,105,180,393,619 'html':33,131,288,356,773,774 'hyphen':895 'identifi':79 'img':43,332,828,871 'improv':179,399 'index':437 'indic':274 'inlin':9,57 'inner':534 'input':92 'insid':277,880 'inter':324,820 'intern':64 'invok':63 'jsx':311,350,357 'jsx/mdx':35,307 'justifi':920 'key':298,552 'label':243,335,441,454,505,553,561,653,758,831,875 'left':443,663 'left-align':662 'legend':500,555 'level':726 'light':206 'like':621 'line':23,176,213,219,563,586,590,607,629,675,686,697 'linecap':368 'lollipop':24,164,611 'mandatori':143 'margin':797 'market':169,523 'markup':41 'match':901 'maxvalu':430 'maxwidth':319,815 'mdx':129,355,789,790,890 'metric':402 'mode':7,55 'multi':188,706 'multi-dimension':187,705 'must':200 'name':305,348,451,787,844,898 'negoti':197 'never':144 'next':654 'non':196 'non-negoti':195 'none':694,863 'number':461 'one':149 'opac':216,222,235,241,247,593,609,637,753 'option':603 'orang':255 'orient':620 'outer':531,763 'output':765 'overview':120 'pad':803 'palett':250,907 'part':166,520 'pass':98 'pattern':140,152 'percentag':178,398,459 'period':574 'perplex':116 'platform':31,112,128 'plot':596,735 'point':300,598,634,645,737,747,781 'polygon':721,750 'posit':273,433 'post':16,62,150,888 'present':867,876,879 'primari':257,492 'proport':741 'purpl':265 'qualiti':846 'quaternari':272 'r':646 'radar':27,191,701 'radius':532,535 'rang':184,581 'rank':161,615 'reader':295,343,784 'reddit':122 'references/visual-media.md':91 'rem':799,805 'repeat':145 'request':101,103 'requir':353 'research':97 'return':850 'rewrit':72 'right':445 'right-align':444 'role':42,331,827,870 'root':229 'rule':194 'san':329,825 'sans-serif':328,824 'score':190,708 'screen':294,342,783 'secondari':263,493 'segment':540,546 'select':134,135 'seri':497,508 'serif':330,826 'share':170,524 'shell':287,308 'singl':401 'single-metr':400 'size':376 'skill' 'skill-blog-chart' 'sky':260 'sourc':88,110,124,237,302,303,304,346,347,463,785,786,842,843,864,903 'source-agricidaniel' 'space':576 'special':268 'squar':504,560 'standalon':82 'standard':285,918 'stroke':214,220,359,363,367,591,635,689,755 'stroke-dasharray':362 'stroke-linecap':366 'stroke-width':358 'strokedasharray':365 'strokelinecap':369 'strokewidth':361,639,691 'style':87,193,318,388,389,796,814 'subtitl':231 'support':17 'svg':10,49,58,230,286,312,808 'system':326,822 'system-ui':325,821 'tertiari':267 'text':208,232,238,244,276,371,464,549,853,866 'text-anchor':370 'textalign':801 'textanchor':373 'thin':628 'time':175,569,573 'titl':107,291,339,776,834 'top':502,688 'topic-agent-skills' 'topic-ai-citations' 'topic-ai-content' 'topic-ai-marketing' 'topic-ai-marketing-hub' 'topic-blog' 'topic-blog-writing' 'topic-claude-code' 'topic-claude-code-skill' 'topic-claude-plugin' 'topic-claude-skill' 'topic-content-creation' 'total':550 'transpar':225,861 'trend':173,567 'truth':90 'two':496 'type':38,104,133,147,155,391,882 'ui':327,823 'use':253,489,541,856,885,908 'user':84 'user-fac':83 'valu':259,429,453,562,580,652,743,900 'verifi':848 'viewbox':313,809,912 'visual':12,51 'vs':34,475 'weight':380 'white':281 'white/light':859 'whole':168,522 'width':360,412,428 'within':148,485,514 'work':201 'worthi':76 'wrap':767 'write':68 'writer':95 'x':408,448,571 'xml':289 'y':410,435,482,578,660 'year':306,349,788,845","prices":[{"id":"a3d84fbe-23cd-474b-b408-4e8f31a89217","listingId":"857a1ec8-5059-41d2-b18a-62ad23d5c33e","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"AgriciDaniel","category":"claude-blog","install_from":"skills.sh"},"createdAt":"2026-05-18T12:54:52.243Z"}],"sources":[{"listingId":"857a1ec8-5059-41d2-b18a-62ad23d5c33e","source":"github","sourceId":"AgriciDaniel/claude-blog/blog-chart","sourceUrl":"https://github.com/AgriciDaniel/claude-blog/tree/main/skills/blog-chart","isPrimary":false,"firstSeenAt":"2026-05-18T12:54:52.243Z","lastSeenAt":"2026-05-18T18:53:29.725Z"}],"details":{"listingId":"857a1ec8-5059-41d2-b18a-62ad23d5c33e","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"AgriciDaniel","slug":"blog-chart","github":{"repo":"AgriciDaniel/claude-blog","stars":753,"topics":["agent-skills","ai","ai-citations","ai-content","ai-marketing","ai-marketing-hub","blog","blog-writing","claude-code","claude-code-skill","claude-plugin","claude-skill","content-creation","content-optimization","content-strategy","eeat","geo","multilingual","open-source","seo"],"license":"mit","html_url":"https://github.com/AgriciDaniel/claude-blog","pushed_at":"2026-05-15T04:45:18Z","description":"Claude Code blog skill suite: 30 sub-skills, 5 agents, 5-gate v1.9.0 Blog Delivery Contract, dual-optimized for Google rankings and AI citations. Active development at AI-Marketing-Hub/claude-blog (AI Marketing Hub Pro community); public releases ship here.","skill_md_sha":"e28d16cbb508e753c7320c41f386de5c112957e2","skill_md_path":"skills/blog-chart/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/AgriciDaniel/claude-blog/tree/main/skills/blog-chart"},"layout":"multi","source":"github","category":"claude-blog","frontmatter":{"name":"blog-chart","description":"Generate dark-mode-compatible inline SVG data visualization charts for blog posts. Supports horizontal bar, grouped bar, donut, line, lollipop, area, and radar charts with automatic platform detection (HTML vs JSX/MDX). Enforces chart type diversity, accessible markup (role=img, aria-label), source attribution, and transparent backgrounds. Use whenever the user mentions data visualization, charts, graphs, comparison tables that need to be visualized, or wants to embed inline SVG visualizations in a blog post, even if not invoking blog-write. Use when user says \"blog chart\", \"generate chart\", \"data visualization\", \"svg chart\", \"blog graph\", \"visualize data\", or when the blog-write workflow identifies chart-worthy data points (3+ comparable metrics, trends, before/after data)."},"skills_sh_url":"https://skills.sh/AgriciDaniel/claude-blog/blog-chart"},"updatedAt":"2026-05-18T18:53:29.725Z"}}