CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Quarto-based technical blog at https://projects.ansonbiggs.com with automatic cross-posting to Ghost blog at https://notes.ansonbiggs.com. Features computational posts with Julia code execution.

Build Commands

# Render the main site
quarto render --to html --output-dir public

# Render ghost-optimized version (minimal HTML for content extraction)
quarto render --profile ghost --to html --output-dir public/ghost-content

# Run the Ghost sync tool (requires GHOST_TOKEN env var)
cd ghost-upload && cargo run

# Force sync all posts (ignores timestamp checks)
cd ghost-upload && cargo run -- --force

Architecture

Dual rendering pipeline: Site builds twice in CI—once with full theme, once with minimal ghost profile for clean content extraction.

Key directories: - posts/YYYY-MM-DD-slug/index.qmd - Blog post sources - ghost-upload/ - Rust tool that parses RSS, extracts HTML from ghost-content, and publishes to Ghost API - _freeze/ - Cached computation results (Quarto freeze feature)

Configuration: - _quarto.yml - Two profiles: default (full site) and ghost (minimal) - posts/_metadata.yml - Shared post metadata (author, license, bibliography)

Post Structure

Posts use YAML frontmatter with freeze: true to cache expensive Julia computations:

---
title: "Post Title"
description: |
  Brief description
date: YYYY-MM-DD
categories:
  - Julia
  - Category
image: filename.png
image-alt: Alt text
freeze: true
---

CI/CD Pipeline (GitLab)

  1. build - Docker image with Julia, Python, R, Quarto
  2. staging - Render both site versions
  3. pages - Deploy to GitLab Pages
  4. publish - Rust ghost-upload syncs new posts to Ghost

Ghost Upload Tool

The ghost-upload/ directory contains a Rust tool that syncs posts to Ghost. See ghost-upload/CONTENT_MANIPULATION_PLAYBOOK.md for detailed documentation on how content is transformed during sync.

Key features handled: - Plotly charts (embedded with base64-encoded data) - Observable JS (runtime injection) - Code annotations (custom HTML + CSS/JS) - Code folds (preserved via HTML cards) - LaTeX math (MathJax injection) - SVG optimization and upload

Verifying Changes

All changes to the ghost-upload tool or site rendering must be verified on the live Ghost site using the Playwright MCP.

After syncing: 1. Use mcp__playwright__browser_navigate to open the post on notes.ansonbiggs.com 2. Use mcp__playwright__browser_snapshot to check content structure 3. Use mcp__playwright__browser_take_screenshot for visual verification 4. Check mcp__playwright__browser_console_messages for JavaScript errors

Notes

  • Julia environment locked to v1.11 (see Project.toml)
  • site-url must be at top level of _quarto.yml for RSS feed generation
  • Ghost sync requires GHOST_TOKEN environment variable