This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
pythonplot.com is a static website that provides a visual comparison of different Python plotting libraries (pandas, matplotlib, seaborn, plotnine, plotly, altair) and R's ggplot2 for exploratory data analysis. It serves as a "Rosetta Stone" showing how to create the same plots across different libraries.
The site is generated from a Jupyter notebook (Examples.ipynb) that contains tagged code cells. The build process:
- Executes the notebook using
jupyter nbconvert - Extracts tagged cells using
render.py - Generates static HTML using Jinja2 templates
- Outputs PNG images and an HTML file to the
web/directory
- Examples.ipynb: Source notebook containing plot examples for each library
- render.py: Core build script that:
- Extracts cells tagged with metadata (ex, name:, package:)
- Extracts base64 PNG images from cell outputs and saves them to web/img/plots/
- Parses cell source code and optional markdown comments
- Renders the final HTML using Jinja2
- templates/t_index.html: Jinja2 template for the website
- web/: Output directory for generated site
- INTRO.md: Markdown content for the site introduction
Notebook cells must be tagged with metadata for the render script to process them:
ex # Marks cell as an example
name:scatter-plot # Maps to names dict in render.py
package:seaborn # Maps to packages dict in render.py
Valid plot names and packages are defined in dictionaries at the top of render.py (lines 19-43).
make dev_environment # Installs Python and R dependencies using uv
make setup # Alternative command (same as dev_environment)Prerequisites:
- Python 3.11+ installed on system
- R 4.0+ installed separately (via Homebrew, apt, or CRAN)
- uv package manager (auto-installed by make targets if missing)
Manual Setup:
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install Python dependencies
uv pip install -r requirements.txt
# Install R packages (ggplot2, mgcv)
./setup_r.shmake qrender # Quick render from Examples.ipynb without executing
make render # Full build: execute notebook, then render (creates timestamped .ipynb)
make # Full build + S3 uploadThe render process:
make renderruns the notebook withjupyter nbconvert --execute- Creates a git-commit-stamped copy (Examples..ipynb)
- Runs
python render.pyto extract cells and generate web/index.html - PNG images are extracted and saved to web/img/plots/ with MD5-based filenames
make test # Run pytest tests
python -m pytest tests/The test suite (tests/test_plots.py) validates that Examples.ipynb contains all expected plot/package combinations defined in the defined_plots dictionary.
After rendering, serve locally:
cd web && python -m http.serverAll plots are rendered to static PNG images:
- Plotly: Uses Kaleido for local rendering (no authentication required with v5+)
- Altair: Uses native rendering or selenium/geckodriver
- R/ggplot2: Uses rpy2 to interface with system R installation
Note: Plotly authentication is no longer needed with plotly v5+. The old authentication code in .travis/authenticate_plotly.py is deprecated.
- Add the plot name to the
namesdictionary in render.py - Add a new cell in Examples.ipynb with code that produces a PNG output
- Tag the cell with:
ex,name:<plot-name>,package:<library-name> - Keep code lines under ~46 characters to avoid horizontal scrolling in the UI
- Optionally add a markdown comment in triple quotes on the first line
- Update tests/test_plots.py to include the new plot in defined_plots
- Run
make qrenderto test (ormake renderfor full rebuild)
- Plot code must generate PNG output in the notebook cell
- For plotly, images must be generated via their server (requires credentials)
- R code cells must start with
%%Rmagic command - Altair cells must start with
%%altairmagic command - Code lines should wrap to ~46 characters for proper display
- All image paths are MD5 hashes of the base64-encoded PNG data
- Python: 3.11+ (specified in runtime.txt and pyproject.toml)
- Package Manager: uv (modern, fast alternative to pip)
- Jupyter: For notebook execution
- pandas 2.0+
- matplotlib 3.7+
- seaborn 0.13+
- plotnine 0.13+
- plotly 5.24+ (with Kaleido for image export)
- altair 5.0+
- statsmodels 0.14+
- R: 4.0+ (system installation required)
- R Packages: ggplot2, mgcv
- Python-R Bridge: rpy2 3.5+
- Jinja2 with jinja2-highlight for templating
- selenium 4.15+ with geckodriver for browser automation
- markdown for text processing
Configuration Files:
pyproject.toml: Modern Python project metadata and dependenciesrequirements.txt: Pin-free dependency listsetup_r.sh: R package installation script
The project uses GitHub Actions for continuous integration and deployment (migrated from Travis CI).
On Every Push:
- Setup R 4.3 using r-lib/setup-r action
- Install R packages (ggplot2, mgcv)
- Setup Python 3.11
- Install uv and Python dependencies
- Setup Firefox and geckodriver for selenium
- Run pytest tests with xvfb (virtual display)
- Execute notebook and render site
- Deploy to Netlify:
- master branch: Production deployment
- Other branches: Preview deployments
Required Secrets:
NETLIFY_AUTH_TOKEN: Netlify authentication tokenNETLIFY_SITE_ID: Netlify site identifier
Environment Variables:
R_HOME: Set to R installation path (e.g.,/opt/R/4.3.3/lib/Ron GitHub runners)
.travis.yml: Old Travis CI config (deprecated).travis/: Old CI scripts (mostly deprecated).travis/authenticate_plotly.py: No longer needed with plotly v5+