This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a Jekyll-based academic/professional portfolio site (aaronzoll.github.io) using the Minimal Mistakes remote theme. It showcases research, teaching materials, and interactive math visualizations built with Desmos.
# Local development server with live reload
bundle exec jekyll serve
# Build for production
bundle exec jekyll build
# Install/update Ruby dependencies
bundle install
The site auto-deploys to GitHub Pages on push to main.
.markdown files — main site pages (index, about, research, teaching, projects, contact, CV)desmos/ — 18 individual interactive Desmos graph pages; use desmos/_template.md when adding new onesDesmosGallery.html — gallery page linking all Desmos visualizations_config.yml — site config: remote theme, author profile, plugins, MathJax/spaceship settings_data/navigation.yml — main nav links (Home, About, Research, Teaching, Desmos Gallery)_includes/mathjax-config.html — MathJax 3 setup; disables jekyll-spaceship math processors to avoid conflictsThe Minimal Mistakes theme is pulled as a remote theme — local files in _includes/, _layouts/, and _sass/ override the remote theme’s defaults.
Sass lives in _sass/minimal-mistakes/ and is compiled from assets/css/main.scss. Custom per-page styles are embedded in front matter or inline <style> blocks within the markdown.
desmos/ embeds a Desmos calculator. The preferred method is a JSON embed (downloaded from Desmos); the template also shows an iframe fallback.assets/particles.json, library at assets/js/particles.js._includes/mathjax-config.html. Pages must include `(function () { function preprocessLatex(el) { var h = el.innerHTML; var stash = [];
// Normalize LaTeX typographic double-quotes → Unicode
h = h.replace(/``/g, '“').replace(/''/g, '”');
// Strip block environments that have no web equivalent (figures, tikz)
h = h.replace(/\\begin\{figure\*?\}[\s\S]*?\\end\{figure\*?\}/g, '');
h = h.replace(/\\begin\{tikzpicture\}[\s\S]*?\\end\{tikzpicture\}/g, '');
h = h.replace(/\\begin\{algorithm\}[\s\S]*?\\end\{algorithm\}/g, '');
// Normalize \begin{env}{}{} / \begin{env}{} → \begin{env}
// (thmtools sometimes adds extra {} optional arguments)
h = h.replace(/\\begin\{(\w+)\}(\{\}){1,2}/g, '\\begin{$1}');
function save(s) { var i = stash.length; stash.push(s); return '\x00' + i + '\x00'; }
function restoreAll(s) {
// Iteratively restore in case stashed blocks contain other stash markers
var prev;
do {
prev = s;
s = s.replace(/\x00(\d+)\x00/g, function (_, i) { return stash[+i]; });
} while (s !== prev);
return s;
}
// 1. Stash and wrap standalone LaTeX display environments in \[...\]
var displayEnvs = ['align', 'alignat', 'equation', 'gather', 'multline', 'flalign', 'split'];
displayEnvs.forEach(function (e) {
[e, e + '*'].forEach(function (env) {
var esc = env.replace('*', '\\*');
h = h.replace(
new RegExp('\\\\begin\\{' + esc + '\\}([\\s\\S]*?)\\\\end\\{' + esc + '\\}', 'g'),
function (m) { return save('\\[' + m + '\\]'); }
);
});
});
// 2. Stash existing \[...\] and $$...$$ display math
h = h.replace(/\\\[([\s\S]*?)\\\]/g, function (m) { return save(m); });
h = h.replace(/\$\$([\s\S]*?)\$\$/g, function (m) { return save(m); });
// 3. Convert theorem environments to HTML, then stash
var envs = {
theorem: ['Theorem', false],
definition: ['Definition', false],
proposition: ['Proposition', false],
lemma: ['Lemma', false],
corollary: ['Corollary', false],
remark: ['Remark', false],
example: ['Example', false],
problem: ['Problem', false],
algo: ['Algorithm', false],
assumption: ['Assumption', false],
proof: ['Proof', true ],
};
function inlineFormat(s) {
s = s.replace(/\\textbf\{([^}]*)\}/g, '<strong>$1</strong>');
s = s.replace(/\\textit\{([^}]*)\}/g, '<em>$1</em>');
s = s.replace(/\\emph\{([^}]*)\}/g, '<em>$1</em>');
s = s.replace(/\\texttt\{([^}]*)\}/g, '<code>$1</code>');
s = s.replace(/\\underline\{([^}]*)\}/g, '<u>$1</u>');
return s;
}
Object.keys(envs).forEach(function (name) {
var label = envs[name][0], isProof = envs[name][1];
h = h.replace(
new RegExp('\\\\begin\\{' + name + '\\}(\\[([^\\]]*)\\])?([\\s\\S]*?)\\\\end\\{' + name + '\\}', 'g'),
function (_, _br, opt, body) {
body = inlineFormat(body);
var html;
if (isProof) {
var cleaned = body
.replace(/\\qed\b/g, '')
.replace(/\\hfill\s*\$\\square\$\s*/g, '');
html = '<div class="math-proof"><span class="math-env-title">Proof.</span> ' +
cleaned +
'<div class="proof-end">$\\square$</div></div>';
} else {
var t = opt ? label + ' (' + opt + ')' : label;
html = '<div class="math-env math-env-' + name + '">' +
'<span class="math-env-title">' + t + '.</span> ' +
body + '</div>';
}
return save(html);
}
);
});
// 4. Stash section headings
h = h.replace(/\\section\*?\{([^}]*)\}/g, function (_, t) { return save('<h2>' + t + '</h2>'); });
h = h.replace(/\\subsection\*?\{([^}]*)\}/g, function (_, t) { return save('<h3>' + t + '</h3>'); });
h = h.replace(/\\subsubsection\*?\{([^}]*)\}/g, function (_, t) { return save('<h4>' + t + '</h4>'); });
// 5. Stash list environments
h = h.replace(/\\begin\{itemize\}([\s\S]*?)\\end\{itemize\}/g, function (_, c) {
var items = c.split(/\\item/).slice(1).map(function (s) { return '<li>' + s.trim() + '</li>'; });
return save('<ul>' + items.join('') + '</ul>');
});
h = h.replace(/\\begin\{enumerate\}([\s\S]*?)\\end\{enumerate\}/g, function (_, c) {
var items = c.split(/\\item/).slice(1).map(function (s) { return '<li>' + s.trim() + '</li>'; });
return save('<ol>' + items.join('') + '</ol>');
});
// 6. Inline text formatting (simple, non-nested arguments)
h = h.replace(/\\textbf\{([^}]*)\}/g, '<strong>$1</strong>');
h = h.replace(/\\textit\{([^}]*)\}/g, '<em>$1</em>');
h = h.replace(/\\emph\{([^}]*)\}/g, '<em>$1</em>');
h = h.replace(/\\texttt\{([^}]*)\}/g, '<code>$1</code>');
h = h.replace(/\\underline\{([^}]*)\}/g, '<u>$1</u>');
h = h.replace(/\\medskip\b/g, '<div style="margin:0.6rem 0"></div>');
h = h.replace(/\\bigskip\b/g, '<div style="margin:1.2rem 0"></div>');
h = h.replace(/\\smallskip\b/g,'<div style="margin:0.3rem 0"></div>');
h = h.replace(/\\noindent\b/g, '');
h = h.replace(/\\newline\b|\\\\(?!\[)/g, '<br>');
// 7. Strip \label, resolve \ref / \eqref as placeholders
h = h.replace(/\\label\{[^}]*\}/g, '');
h = h.replace(/\\eqref\{([^}]*)\}/g, '(?)');
h = h.replace(/\\[Cc]ref\{[^}]*\}/g, '?');
h = h.replace(/\\ref\{[^}]*\}/g, '?');
// 8. Paragraph wrapping: split on blank lines
var chunks = h.split(/\n{2,}/);
h = chunks.map(function (chunk) {
chunk = chunk.trim();
if (!chunk) return '';
// Chunk that is purely a stash marker — restore as-is (block element)
if (/^\x00\d+\x00$/.test(chunk)) return chunk;
return '<p>' + chunk + '</p>';
}).filter(Boolean).join('\n');
el.innerHTML = restoreAll(h); }
window._preprocessLatex = preprocessLatex; })();
// ── MathJax 3 configuration ──────────────────────────────────────────────────
window.MathJax = {
tex: {
inlineMath: [[’$’, ‘$’], [’\(‘, ‘\)’]],
displayMath: [[’\(', '\)’], [’\[’, ‘\]’]],
tags: ‘ams’,
macros: {
// ── Trace / matrix ops ──────────────────────────────────────────────
tr: ‘\mathrm{Tr}’,
trace: ‘\mathrm{Tr}’,
vect: ‘\mathbf{vec}’,
bvec: [’{\mathbf{#1}}’, 1],
matrx: [’\begin{bmatrix}#1\end{bmatrix}’, 1],
diag: ‘\operatorname{diag}’,
Diag: ‘\operatorname{Diag}’,
rank: ‘\operatorname{rank}’,
sign: ‘\operatorname{sign}’,
// ── Calligraphic / script ────────────────────────────────────────────
cI: ‘\mathcal{I}’,
cX: ‘\mathcal{X}’,
cB: ‘\mathcal{B}’,
cE: ‘\mathcal{E}’,
cA: ‘\mathcal{A}’,
cU: ‘\mathcal{U}’,
cS: ‘\mathcal{S}’,
Lcal: ‘\mathcal{L}’,
Fscr: ‘\mathscr{F}’,
// ── Blackboard bold ──────────────────────────────────────────────────
F: ‘\mathbb{F}’,
C: ‘\mathbb{C}’,
R: ‘\mathbb{R}’,
N: ‘\mathbb{N}’,
NN: ‘\mathbb{N}’,
ZZ: ‘\mathbb{Z}’,
Q: ‘\mathbb{Q}’,
EE: ‘\mathbb{E}’,
Expect: ‘\mathbb{E}’,
// ── Linear algebra / analysis operators ──────────────────────────────
Dim: ‘\operatorname{dim}’,
spann: ‘\operatorname{span}’,
im: ‘\operatorname{Im}’,
gph: ‘\operatorname{gph}’,
supp: ‘\operatorname{supp}’,
lip: ‘\operatorname{lip}’,
var: ‘\operatorname{var}’,
Var: ‘\operatorname{Var}’,
op: ‘\mathrm{op}’,
dist: ‘{\mathbf{dist}}’,
proj: ‘\operatorname{proj}’,
prox: ‘\operatorname{prox}’,
St: ‘\text{subject to}’,
// ── Delimiters / paired macros ───────────────────────────────────────
norm: [’\left\|#1\right\|’, 1],
opnorm: [’\left\|#1\right\|_{\mathrm{op}}’, 1],
abs: [’\left|#1\right|’, 1],
inner: [’\left\langle#1,\,#2\right\rangle’, 2],
Prob: [’\mathbb{P}\!\left(#1\right)’, 1],
Expec: [’\mathbb{E}\!\left(#1\right)’, 1],
dom: [’\operatorname{dom}(#1)’, 1],
// ── Convex analysis ──────────────────────────────────────────────────
epi: ‘\operatorname{epi}’,
hypo: ‘\operatorname{hypo}’,
interior: ‘\operatorname{int}’,
bdry: ‘\operatorname{bdy}’,
relint: ‘\operatorname{ri}’,
argmin: ‘\operatorname{argmin}’,
argmax: ‘\operatorname{argmax}’,
mini: ‘\operatorname{minimize}’,
ls: ‘\operatorname{limsup}’,
// ── Misc ─────────────────────────────────────────────────────────────
bcdot: ‘\ \mathbf{\cdot}\ ‘,
eps: ‘\varepsilon’,
Holder: ‘\text{Hölder}’,
},
},
options: {
skipHtmlTags: [‘script’, ‘noscript’, ‘style’, ‘textarea’, ‘pre’, ‘code’],
},
startup: {
ready() {
function doPreprocess() {
document.querySelectorAll(‘.latex-body’).forEach(function (el) {
window._preprocessLatex(el);
});
MathJax.startup.defaultReady();
}
if (document.readyState === ‘loading’) {
document.addEventListener(‘DOMContentLoaded’, doPreprocess);
} else {
doPreprocess();
}
},
},
};
</script>
` in their front matter header or body.
Most content pages use the splash layout with a hero header block (overlay color + image from picsum.photos). Research and teaching pages contain embedded HTML/CSS for custom grid layouts and slide presentations.
assets/ subdirectoriesassets/images/desmos/_template.md and linked from both DesmosGallery.html and teaching.markdown_site/ directory is the generated build output — do not edit files there directly