block by jsundram a187ff2619b90eaf68d449462b1f9795

Periodic Table of Boccherini String Quartets

Full Screen

Periodic Table of Boccherini String Quartets

An interactive visualization of Luigi Boccherini’s complete string quartet output (1761-1804), displayed as a periodic table-inspired grid.

View it (via gisthack, see below for details):

Updating the Gist

Quick Start (First Time Setup)

# 1. Configure git to use GitHub CLI credentials (do this once)
gh auth setup-git

# 2. Save your gist ID (do this once)
gh gist list | head -1 | awk '{print $1}' > .gist_id

# 3. Create a sync script (do this once)
cat > sync-gist.sh << 'EOF'
#!/bin/bash

# Usage: ./sync-gist.sh "commit message" file1 file2 ...
# Or: ./sync-gist.sh file1 file2 ... (uses default message)

# If first arg looks like a commit message (has spaces or quotes), use it
if [[ "$1" == *" "* ]] || [[ "$1" == \"*\" ]]; then
    MESSAGE="$1"
    shift
    FILES="$@"
else
    MESSAGE="Update gist"
    FILES="${@:-index.html}"
fi

# Add, commit, and push with message
git add $FILES
git commit -m "$MESSAGE"
git push
EOF
chmod +x sync-gist.sh

Daily Workflow

# 1. Make your changes to index.html, opera.json, or README.md

# 2. Check what changed
git diff                    # See all changes
git diff index.html         # See specific file changes

# 3. Update the gist with a commit message
./sync-gist.sh "Fix title alignment" index.html

# Or update multiple files
./sync-gist.sh "Update visualization and docs" index.html README.md

# Or use default message "Update gist"
./sync-gist.sh index.html

How it works

The script uses standard git commands to update the gist:

  1. git add - stages your files
  2. git commit -m "message" - commits with your message
  3. git push - pushes to the gist

Your commit messages appear in the gist history instead of just “revised”.

Manual method (if you prefer)

# Standard git workflow
git add index.html
git commit -m "Your commit message"
git push

# Check status
git status
git log --oneline

Viewing Online

Get the raw file URL and use githack.com to serve it:

  1. Get the raw URL from your gist:

    https://gist.githubusercontent.com/USERNAME/GIST_ID/raw/index.html
  2. Replace gist.githubusercontent.com with gist.githack.com:

    https://gist.githack.com/USERNAME/GIST_ID/raw/index.html

Example for this gist:

https://gist.githack.com/jsundram/a187ff2619b90eaf68d449462b1f9795/raw/index.html

Why githack.com?

Note: htmlpreview.github.io doesn’t work because it can’t load external scripts like D3.js.

Data Overview (opera.json)

Structure

The data is organized as an array of opus groups, where each opus contains:

{
  "opus": 2,                    // Opus number
  "year": 1761,                 // Year of composition
  "dedication": "...",          // Optional: dedicatee
  "imslp": "...",              // Optional: IMSLP link for the opus
  "quartets": [...]            // Array of quartets in this opus
}

Each quartet contains:

{
  "number": 1,                 // Quartet number within opus
  "gerard": 159,               // Gerard catalog number
  "key": "C",                  // Key (e.g., "C", "E-flat")
  "major": false,              // true = major, false = minor
  "nickname": "...",           // Optional: nickname
  "imslp": "...",             // Optional: IMSLP link
  "mvmts": [...],             // Array of movement names
  "category": "opera grande"   // "opera grande" or "opera piccola" variants
}

Data Usage

Displayed in visualization:

Used in interactions:

Notable transformations:

Unused/Metadata

All data fields are currently utilized either in the display, tooltips, or interactions. The data is comprehensive and fully integrated.

Technical Overview (index.html)

Architecture

Single-file design: All HTML, CSS, and JavaScript in one file for easy gist hosting and sharing.

Technology stack:

Design Decisions

1. Periodic Table Metaphor

2. Visual Alignment Strategy The design emphasizes vertical alignment across three levels:

Row Header          ↔  Quartet Cards
─────────────────────────────────────
Year (age)          ↔  Mode bar (G# / quartet #)
Opus number         ↔  Key signature
Category badge Movement count

This creates strong visual relationships between semantically related information.

3. Color Encoding System

Mode bar (top of each card):

Movement count (diverging purple-green palette):

Category badges use the same palette:

Row background gradients:

4. Layout System

Flexbox throughout:

Height constraints:

5. Typography Hierarchy

Dramatic size contrast in row headers:

Code Intricacies

1. Commented sections for easy tweaking The opus label CSS and JavaScript are heavily commented with clear section markers (e.g., === OPUS LABEL SECTION ===) to facilitate experimentation with layout and sizing.

2. Dynamic class application Category background gradients are applied dynamically:

const categoryClass = opus.quartets[0].category.includes('grande')
  ? 'grande-bg' : 'piccola-bg';

3. Unicode transformation Flat symbols are rendered using Unicode replacement:

const keyDisplay = quartet.key.replace('-flat', '♭');

4. Nested container pattern Cards use multiple nested containers for precise alignment:

This allows independent control of each vertical section.

5. Age calculation Boccherini’s age is calculated inline from a constant:

const BOCCHERINI_BIRTH_YEAR = 1743;
const age = opus.year - BOCCHERINI_BIRTH_YEAR;

Browser Compatibility

Requires modern browser support for:

Tested in Chrome, Firefox, Safari, and Edge (2023+).


Created: December 2025 Data source: Luigi Boccherini quartet catalog (G.159-249)

generate-pdf.py

parts.json

peters.json