Claude f010ec6a3c Remove internal build decisions from visitor-facing content
The public site (and DOM) shouldn't advertise our tooling choices:

- Drop the design-system credit and typeface note from the footer; replace
  with visitor-useful copy ("Built to be sent" / "The canon")
- Remove the external-inspiration reference from the homepage lede
- Neutralize the meta description
- Rename the `cds-` CSS class prefix to `site-`
- Scrub internal names from source comments and the chart theme variable

Functional font-family references are kept; only the advertising is removed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XPEvmMbac2fCvKXpQcovj8
2026-08-05 13:40:59 +00:00
2026-08-05 12:41:00 +00:00

Chart Sins

A catalogue of data-visualization sins — for each one: the chart that misleads, why it fools the eye, and the honest version that fixes it.

Built with Astro and styled on the Carbon Design System. Charts are authored as Vega-Lite specs and rendered to static SVG at build time, so pages ship with zero client-side JavaScript.

Tech stack

Concern Choice
Framework Astro 5 (static output)
Content Markdown/MDX via Astro Content Collections
Charts Vega-Lite specs → SVG at build (headless Vega)
Design Carbon Design System — tokens, type scale, spacing, motion, themes
Typeface IBM Plex Sans / Mono (self-hosted via @fontsource)
Styling Token-driven CSS (src/styles/global.css)
Hosting GitHub Pages (via GitHub Actions)
Language TypeScript

On the Carbon adoption

Carbon ships React/web-component libraries built for application UIs and they ship JavaScript; this is a static content site, so instead of the component runtime we adopt Carbon at the design-token level — its color tokens and White/Gray-100 themes, the 8px spacing scale, the productive/expressive type distinction (IBM Plex), motion tokens, square geometry, the focus ring, and Carbon's data-visualization palette for the charts (validated for colorblind-safety and contrast on the chart surface).

Project layout

src/
├── content.config.ts        # typed frontmatter schema for a "sin"
├── content/sins/            # one Markdown file per sin
├── charts/                  # Vega-Lite JSON specs (bad + fixed)
├── components/VegaChart.astro   # build-time Vega-Lite → SVG renderer
├── layouts/BaseLayout.astro
├── lib/charts.ts            # spec lookup + severity helper
├── pages/
│   ├── index.astro          # the gallery
│   └── sins/[...slug].astro # a sin's detail page
└── styles/global.css

Adding a new sin

  1. Author two Vega-Lite specs in src/charts/, e.g. my-sin-bad.json and my-sin-fixed.json.

    Omit $schema, config, and outer width/height tuning you don't need — keep specs focused on the data and encoding.

  2. Create src/content/sins/my-sin.md with frontmatter:

    ---
    title: "My Sin"
    summary: "One-line description shown on the gallery."
    category: "Misleading Scales"
    severity: 3            # 1 (venial) … 5 (mortal)
    tags: ["bar chart"]
    badChart: "my-sin-bad"      # basename in src/charts/, no .json
    fixedChart: "my-sin-fixed"
    date: 2026-08-05
    ---
    
    Prose explaining the sin, why it deceives, and the repentance.
    
  3. npm run dev and check it. The typed schema will flag a mistyped field or a missing chart spec at build time.

Making a chart interactive (opt-in)

Charts are static SVG by default. To make one interactive, render it client-side with vega-embed in a small Astro island (client:visible) on that page only, instead of using <VegaChart>. This keeps the default fast while allowing hover/zoom where a specific sin benefits from it.

Commands

Command Action
npm install Install dependencies
npm run dev Start the dev server at localhost:4321
npm run build Build the static site to ./dist
npm run preview Preview the production build locally

Deployment

Pushing to main triggers .github/workflows/deploy.yml, which builds the site and publishes it to GitHub Pages. Enable it once under Settings → Pages → Build and deployment → Source: GitHub Actions.

The site is configured for the project path https://olehomelchenko.github.io/chart-sins (site + base in astro.config.mjs). If you move to a custom domain, set site to it and remove base.

S
Description
website to shame you for your chart sins
Readme 676 KiB
Languages
TypeScript 37.1%
CSS 34%
Astro 28.3%
JavaScript 0.6%