CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Personal website and blog for James H Wade (jameshwade.com), built with Quarto and deployed to Netlify via GitHub Actions.
Build & Preview
quarto preview # Start live dev server with hot reload
quarto preview --port 4567 # Specify a port
quarto render # Full site build (outputs to _site/)Deployment is automated: push to main triggers GitHub Actions → Quarto render → Netlify publish.
Architecture
_quarto.yml— Main config: site metadata, navbar, theme (light/dark), fonts, footer, freeze settings_brand.yml— Brand definitions: color palette, typography, and social links. Referenced by_quarto.ymlvia thebrandtheme layercustom.scss— Light theme: color palette (cream/teal/amber), typography (Bricolage Grotesque headings, Newsreader body, JetBrains Mono code), hero section, card styles, responsive breakpoints. Uses Quarto SCSS partitions (/*-- scss:defaults --*/and/*-- scss:rules --*/)custom-dark.scss— Dark theme: inverted palette (navy background, light text, brightened accents). Loaded automatically when user prefers dark mode or toggles the navbar switchindex.qmd— Homepage with custom hero section (.hero-sectiondivs) and grid listing of postsabout.qmd— Uses Quarto’strestlesabout template with profile image and social linkstalks.qmd— Talks page with embedded YouTube iframesposts/— Blog posts, each a.qmdfileposts/_metadata.yml— Default frontmatter applied to all posts (freeze: true)_freeze/— Cached execution outputs (committed to git so CI doesn’t need R). Do not edit directly; regenerated byquarto render_extensions/— Quarto extensions:shinylive(interactive Shiny embeds),webr(R-in-browser), andpyodide(Python-in-browser)
Writing Posts
Naming convention: posts/YYYY-MM-DD_slug.qmd
Standard frontmatter:
---
title: "Post Title"
author: James H Wade
date: YYYY-MM-DD
description: "Short description for the listing card"
image: https://url-or-local-path
execute:
freeze: auto
eval: false
format:
html:
toc: true
code-copy: true
code-link: true
categories:
- Category1
---Most posts set eval: false since code blocks are illustrative. The freeze: auto setting caches execution output so builds don’t re-run code unless the source changes.
Theming
The site uses automatic light/dark mode via two custom SCSS files, not a Bootswatch preset:
custom.scss— Light theme. All colors, typography, spacing, and component styles.custom-dark.scss— Dark theme. Overrides the color palette and component styles for dark backgrounds._brand.yml— Canonical color palette and font definitions. Both SCSS files should stay in sync with these values.
Google Fonts are loaded via include-in-header in _quarto.yml. When modifying styles, edit the SCSS files. The styles.css file exists but is not actively used.
When adding colors or changing the palette, update all three files: _brand.yml, custom.scss, and custom-dark.scss.
Quarto Extensions
Three extensions are installed in _extensions/: - shinylive — Embeds interactive Shiny apps that run entirely in the browser - webr — Runs R code in-browser via WebAssembly (requires COOP/COEP headers, configured in netlify.toml) - pyodide — Runs Python code in-browser via WebAssembly (same COOP/COEP header requirements)
Deployment
Push to main triggers .github/workflows/publish.yml: checkout, Quarto render, deploy to Netlify. The workflow uses a NETLIFY_AUTH_TOKEN secret. To manually re-run a failed deploy, use the GitHub Actions UI or gh workflow run publish.yml.
Posts using WebAssembly extensions (webr, pyodide) require COOP/COEP headers configured per-path in netlify.toml.
Content Guidelines
- Keep employer references vague (“a large chemicals R&D organization”) — do not name the company directly
- Internal projects (Hyperdrive, Citizen Data Science program details) should stay private
- Open source projects (shinymcp, deputy, gptstudio, dsprrr, tempest, measure) can be discussed freely
- Title is “Research Scientist” (not associate)
Writing Style
Write like a working programmer explaining something to a peer — direct, concrete, opinionated where warranted. Match the voice in existing posts: first person, conversational but not chatty, technically precise.
Avoid these AI writing tropes: - Filler phrases: “dive into”, “it’s worth noting”, “let’s explore”, “in today’s landscape”, “the power of” - Hollow intensifiers: “incredibly”, “extremely”, “truly”, “revolutionary”, “game-changing” - Sycophantic hedging: “Great question!”, “That’s a really interesting point” - Bullet-point-itis: not everything needs a list. Prefer prose when the content flows naturally - Fake enthusiasm or forced excitement about mundane things - Summary paragraphs that just restate what was already said (“In this post, we explored…”) - Em dashes — avoid them. Use periods, commas, or colons instead. Only use an em dash when it genuinely clarifies structure - Starting sentences with “So,” or “Now,” as transitions - The word “leverage” when “use” works fine - “Straightforward”, “robust”, “seamless”, “comprehensive” — vague adjectives that say nothing
Do: - Be specific. Say what the thing does, not that it’s powerful - Use short sentences when making a point. Save longer ones for explanation - Let code speak for itself — don’t narrate what the reader can see - Cut the first paragraph if the second one is where it gets interesting - End cleanly. No “happy coding!” or “I hope this helps!”