Files
chart-sins/README.md
T
Claude 2e17f8fa59 Scaffold Chart Sins site with Astro + build-time Vega-Lite
Set up the static-site tech stack: Astro 5 with Markdown content
collections, Vega-Lite specs rendered to static SVG at build time
(zero client JS), plain scoped CSS, and a GitHub Pages deploy workflow.

Includes three sample sins (truncated y-axis, dual-axis deception,
pie chart overload), each with a bad and fixed chart spec, plus a
gallery index and per-sin detail pages.

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

87 lines
3.4 KiB
Markdown

# 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](https://astro.build). Charts are authored as
[Vega-Lite](https://vega.github.io/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) |
| Styling | Plain scoped CSS + one global stylesheet |
| Hosting | GitHub Pages (via GitHub Actions) |
| Language | TypeScript |
## 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:
```yaml
---
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`.