AGENTS.md — Guide for AI Assistants
This file orients an AI coding/writing agent working in Fractal Notes. Read it before editing. It describes what the project is, how it is built, and — most importantly — the conventions for writing new math notes so they match the existing voice and render correctly.
Human note:
README.mdis the human-facing setup guide,PROJECT_NOTES.mdis the technical cheat-sheet, and this file is the agent-facing map. Keep the three consistent when you change build steps or structure.
1. What this project is
Fractal Notes (fractalnotes.com) is a Persian-language (Farsi), right-to-left math education website. It is a collection of short, intuitive notes — “small sheets of understanding” — that each open a window onto a bigger idea. The author’s method: to learn (or re-learn) something, write about it so simply that anyone would understand it, and share the excitement.
The content is the product. The code (Jekyll, prerender, Docker) exists only
to publish the notes cleanly. Most work here is writing and editing .md
notes, not changing infrastructure.
- Language of the notes: Persian (فارسی), RTL. Math is universal (LaTeX).
- Language of the docs/code/comments: English.
- Tone: warm, curious, conversational, intuition-first. Prefer a picture or a concrete example over a formal definition. Rigor is welcome but never at the cost of clarity.
2. Tech stack (the short version)
| Piece | What it is |
|---|---|
| Jekyll | Static site generator. Turns .md → _site/ HTML. |
| Kramdown | Markdown engine. math_engine: mathjax emits \(...\) / \[...\]. |
| KaTeX 0.16.9 | Math rendering, self-hosted under assets/katex/ (not a CDN). |
| Vazirmatn | Persian font, self-hosted at assets/fonts/Vazirmatn-wght.woff2. |
| Playwright | Headless-browser prerender step: bakes KaTeX + inline JS into the HTML so there is no first-load flash. |
| GitHub Pages | Hosting. GitHub Actions runs Jekyll → prerender → deploy. |
| Docker + Nginx | Optional: serves the same prerendered HTML locally. |
Single layout: _layouts/default.html (<html lang="fa" dir="rtl">).
3. Repository map
index.md Homepage. Lists every note by looping over site_index.yml.
_config.yml Jekyll config (title, SEO, kramdown math, plugins).
_data/site_index.yml ★ SINGLE SOURCE OF TRUTH for the note list / menu.
_layouts/default.html The only layout (head, KaTeX loader, nav, SEO JSON-LD).
scripts/prerender.js Playwright prerender script.
scripts/prerender-whitelist.json Directories that get prerendered.
assets/
css/style.css All styling (RTL, typography, image/table handling).
katex/ Self-hosted KaTeX (js, css, fonts).
fonts/ Self-hosted Vazirmatn.
img/ All note images (PNG diagrams).
Makefile All dev/build/docker commands (`make help`).
Dockerfile / compose.yml Multi-stage prerendered image + Nginx.
Content directories (each holds topic notes as .md files):
complex-numbers/ اعداد مختلط
induction/ استقرای ریاضی
trigonometry/ مثلثات
pigeonhole-principle/ اصل لانهٔ کبوتر
linear-algebra/ جبر خطی
problems/ مسئلهها (standalone problems)
problem-solving/
symmetry/ تقارن
recasting/ تغییر نگاه به مسئله
There is only one index.md (the site root). Sub-directories do not have
their own index pages; all navigation flows through _data/site_index.yml.
4. ★ How to add a new note (the core workflow)
This is the most common task. Follow every step or the note won’t appear/render.
-
Create the file as
<topic-dir>/<kebab-case-name>.md(English filename, even though the content is Persian). Put it in the right topic directory, or create a new directory for a new topic (see step 5). The quickest start is to copy the ready-made skeleton at_templates/note-template.md. - Write the front matter (YAML).
titleanddescriptionare required;imageis optional (used for social/SEO cards):--- title: "عنوان یادداشت" # short Persian title (no "# " here) description: "یک جملهٔ توصیفی برای SEO و کارتهای اشتراکگذاری." image: "/assets/img/logo.png" # optional; a relevant diagram is better --- -
Write the body following the note conventions in §5.
- Register the note in
_data/site_index.ymlso it shows on the homepage and in the side menu. Add an entry in the reading order you want: ```yaml- title: “عنوان یادداشت” # can match the front-matter title
path: “topic-dir/kebab-case-name” # NO leading slash, NO .md
```
Titles here often carry a topic prefix, e.g.
"استقرای ریاضی؛ مسئلهٔ ...". A note not listed here is invisible on the site (though the URL still works once built). Example of an existing unlisted draft:problem-solving/recasting/putnam-icosahedron-problem.md.
- title: “عنوان یادداشت” # can match the front-matter title
path: “topic-dir/kebab-case-name” # NO leading slash, NO .md
```
Titles here often carry a topic prefix, e.g.
-
New topic directory? Add its path to
scripts/prerender-whitelist.json(e.g."number-theory"or"problem-solving/invariants"), otherwise pages under it are served un-prerendered (math renders in-browser with a small delay). Files added under an already-listed directory are picked up automatically. - Verify locally:
make dev, openhttp://localhost:4000, confirm the note appears in the list, the math renders, and RTL/images look right.
5. Note writing conventions (match the house style)
Study an existing note before writing — good models:
complex-numbers/introduction.md, problems/sum_of_power_1.md,
problem-solving/symmetry/pill-problem.md.
Structure
- Start the body with an H1 title and a bold one-line subtitle, then an intro
paragraph:
# عنوان اصلی **یک زیرعنوانِ کوتاه و گیرا** یک یا دو جملهٔ مقدماتی که خواننده را وارد فضای مسئله میکند. - Separate major sections with a horizontal rule
---and## headings. - Use
>blockquotes for a key principle, a quote (e.g. Pólya), or a punchline. - Keep paragraphs short. Intuition first, formalism second.
Math (KaTeX via Kramdown)
- Inline:
$ ... $· Display:$$ ... $$on their own lines. - Standard LaTeX. Persian text and LaTeX mix freely on a line.
- Test every formula in the local preview — a broken delimiter silently fails to render.
Images
- Store PNGs in
assets/img/with descriptivesnake_casenames. - Center them and always set
widthandheight(prevents layout shift):<p align="center"> <img src="/assets/img/your_diagram.png" alt="توضیح فارسی تصویر" width="320" height="320"> </p> - Use absolute
/assets/img/...paths. Write a meaningful Persianalt.
Language
- Body text in Persian with correct RTL punctuation; use the ZWNJ (نیمفاصله) where Persian requires it (e.g. «میشود», «یادداشتها»).
- Do not translate standard math terms awkwardly — keep the note readable.
6. Build & run commands
Run make help for the full list. Most-used:
make install-deps # Ruby gems + Node/Playwright (first-time setup)
make dev # Local Jekyll server + livereload → localhost:4000
make build # Build static site into _site/
make build-prerender # Full pipeline: build + Playwright prerender
make serve # Serve the prerendered _site to test it
make check-prerender # Verify the LIVE site is serving prerendered HTML
make docker-up # Build + run the Nginx image → localhost:8080
Deployment is automatic: pushing to main triggers GitHub Actions
(Jekyll → prerender → deploy) when Pages source is set to GitHub Actions.
7. Guardrails for agents
- Prefer content work. The default task is writing/editing notes. Touch
_layouts/,assets/css/,scripts/,Dockerfile, or CI only when the task is explicitly about infrastructure. - Keep the three docs in sync. If you change build steps or structure, update
README.md,PROJECT_NOTES.md, and this file together. - Never hand-edit generated output (
_site/,Gemfile.lock,node_modules/— all gitignored). - Two registries must agree with reality: every visible note is in
_data/site_index.yml; every content directory is in the prerender whitelist. - Don’t add external CDNs. KaTeX and the font are self-hosted on purpose (reliability + no first-load jank). Keep new assets local.
- Verify math renders in a local preview before considering a note done — it’s the single most common silent failure.
- This is a personal learning project. When the author is “learning something together” with you, the goal is a clear, correct, delightful note — accuracy of the math matters more than speed.