-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
docs(site): add figure visual style guide and contributor docs #302
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nitindavegit
wants to merge
1
commit into
rohitg00:main
Choose a base branch
from
nitindavegit:docs/figure-style-guide
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,273 @@ | ||
| # Contributing Figures | ||
|
|
||
| This guide covers how to create, register, embed, and maintain figures in the curriculum. Two figure systems exist: | ||
|
|
||
| - **Interactive widgets** — slider-driven, theme-aware, vanilla JS (134+ across 13 modules) | ||
| - **Animated SVG explainers** — auto-looping, hover-pause, SVG-based (10 core figures) | ||
| - **Static SVGs** — hand-crafted, standalone diagrams in `assets/figures/` | ||
|
|
||
| --- | ||
|
|
||
| ## Quick Start: Embed an Existing Figure | ||
|
|
||
| Open any lesson's `docs/en.md` and add a fenced block: | ||
|
|
||
| ````markdown | ||
| ```figure | ||
| attention-matrix | ||
| ``` | ||
| ```` | ||
|
|
||
| The lesson renderer (`lesson.html:2268`) converts this into a `<div class="lesson-figure" data-figure="attention-matrix">`, and the mount system hydrates it on page load. | ||
|
|
||
| To pass configuration: | ||
|
|
||
| ````markdown | ||
| ```figure | ||
| kv-cache | ||
| {"layers": 32, "kvHeads": 8, "headDim": 128} | ||
| ``` | ||
| ```` | ||
|
|
||
| --- | ||
|
|
||
| ## Interactive Widgets (140+ existing) | ||
|
|
||
| These are slider/select-driven tools embedded inside a styled card (`.lf` container). Users drag parameters and see the output update in real time. | ||
|
|
||
| ### File Organization | ||
|
|
||
| Pick the right module file based on the target lesson's phase: | ||
|
|
||
| | Module file | Phases | | ||
| |-------------|--------| | ||
| | `figures-math.js` | P1 (math foundations) | | ||
| | `figures-ml.js` | P2 (ML fundamentals) | | ||
| | `figures-dl.js` | P3 (deep learning core) | | ||
| | `figures-vision-speech.js` | P4 (vision), P6 (speech) | | ||
| | `figures-transformers.js` | P5 (NLP), P7 (transformers) | | ||
| | `figures-genai-rl.js` | P8 (generative AI), P9 (RL) | | ||
| | `figures-llms-systems.js` | P10 (LLMs), P12 (multimodal), P13 (tools) | | ||
| | `figures-agents-alignment.js` | P11 (LLM eng), P14 (agents), P16 (swarms), P18 (alignment) | | ||
| | `figures-math2.js` | P1 (advanced math) | | ||
| | `figures-nlp2.js` | P5 (advanced NLP) | | ||
| | `figures-llms2.js` | P10 (LLM internals) | | ||
| | `figures-infra.js` | P17 (infrastructure) | | ||
| | `figures-frontier.js` | P15 (autonomy), P19 (capstones) | | ||
|
|
||
| If your concept spans phases not covered by an existing module, create a new file named `figures-<topic>.js`. | ||
|
|
||
| ### Anatomy of a Widget | ||
|
|
||
| ```javascript | ||
| (function () { | ||
| 'use strict'; | ||
| var LF = window.LF; | ||
| if (!LF) { return; } | ||
| var el = LF.el, svgEl = LF.svgEl, slider = LF.slider, clamp = LF.clamp; | ||
|
|
||
| // ── widget-name: one-line description ────────────────────────────── | ||
| function widgetName(host) { | ||
| // 1. State object — all mutable parameters live here | ||
| var state = { param: 1.0, count: 5 }; | ||
|
|
||
| // 2. SVG surface | ||
| var W = 520, H = 240, PAD = 28; | ||
| var svg = svgEl('svg', { viewBox: '0 0 ' + W + ' ' + H }); | ||
| var num = el('span', { class: 'lf-num' }); | ||
| var meta = el('div', { class: 'lf-meta' }); | ||
| var formula = el('div', { class: 'lf-formula' }); | ||
|
|
||
| // 3. Coordinate helpers | ||
| function px(x) { return PAD + x / maxX * (W - 2 * PAD); } | ||
| function py(y) { return H - PAD - y / maxY * (H - 2 * PAD); } | ||
|
|
||
| // 4. Render function — called on every slider change | ||
| state._render = function () { | ||
| while (svg.firstChild) svg.removeChild(svg.firstChild); | ||
| // Rebuild SVG content deterministically from state | ||
| // Update text nodes: num.innerHTML, meta.textContent, formula.textContent | ||
| }; | ||
|
|
||
| // 5. Controls | ||
| var grid = el('div', { class: 'lf-grid' }, [ | ||
| slider(state, 'param', 'label', 0, 10, 0.1), | ||
| ]); | ||
|
|
||
| // 6. Assemble the card | ||
| host.appendChild(el('div', { class: 'lf' }, [ | ||
| el('div', { class: 'lf-head' }, [ | ||
| el('span', { class: 'lf-label' }, ['UPPERCASE NAME']), | ||
| el('span', {}, ['interaction hint']) | ||
| ]), | ||
| el('div', { class: 'lf-body' }, [ | ||
| grid, | ||
| el('div', { class: 'lf-out' }, [svg, num, meta, formula]) | ||
| ]), | ||
| el('div', { class: 'lf-cap' }, ['Educational caption explaining the concept.']) | ||
| ])); | ||
|
|
||
| // 7. Initial render | ||
| state._render(); | ||
| } | ||
|
|
||
| // 8. Register the widget | ||
| LF.register({ 'widget-name-slug': widgetName }); | ||
| })(); | ||
| ``` | ||
|
|
||
| ### State Contract | ||
|
|
||
| - All mutable parameters in a `state` object. | ||
| - `state._render` clears and fully rebuilds the SVG on each call (deterministic). | ||
| - Controls (`slider`/`select`) call `state._render()` automatically. | ||
| - No randomness in `_render` — use pre-computed or seeded data. | ||
|
|
||
| ### Available Controls | ||
|
|
||
| ```javascript | ||
| // Slider: range input with live value display | ||
| slider(state, key, label, min, max, step, formatFn?) | ||
| // Example: | ||
| slider(state, 'layers', 'layers', 1, 128, 1, fmtInt) | ||
| slider(state, 'lr', 'learning rate', 0.01, 1.2, 0.01) | ||
|
|
||
| // Select: dropdown | ||
| select(state, key, label, [['Display Name', value], ...]) | ||
| // Example: | ||
| select(state, 'kernel', 'kernel', [['Edge', 'edge'], ['Blur', 'blur']]) | ||
|
|
||
| // Text: raw text node | ||
| el('text', { x: 100, y: 50, 'font-family': 'monospace' }, [txt('label')]) | ||
| ``` | ||
|
|
||
| ### Output Elements | ||
|
|
||
| ```html | ||
| <span class="lf-num">3.14 <small>GiB</small></span> <!-- Large highlighted number --> | ||
| <div class="lf-bar"><i></i></div> <!-- Progress/usage bar --> | ||
| <div class="lf-meta">context line of text</div> <!-- Secondary description --> | ||
| <div class="lf-formula">f(x) = x + 1</div> <!-- Math formula --> | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Animated SVG Explainers (10 existing) | ||
|
|
||
| These are auto-looping, hover-pause SVG animations that live in `figures.js`. They work well for processes with a natural temporal flow (tokenization, attention, embedding arithmetic). | ||
|
|
||
| ### Adding a New Animated Explainer | ||
|
|
||
| 1. Define a function in `figures.js` that takes a `host` DOM element. | ||
| 2. Inside, create an SVG element and append it to `host`. | ||
| 3. Use the `loop(host, fn, period, opts)` utility: | ||
|
|
||
| ```javascript | ||
| function myNewFigure(host) { | ||
| var W = 760, H = 540; | ||
| var svg = el('svg', { viewBox: '0 0 ' + W + ' ' + H, width: '100%', | ||
| role: 'img', 'aria-label': 'Description' }); | ||
| host.appendChild(svg); | ||
|
|
||
| // ... build static SVG elements ... | ||
|
|
||
| loop(host, function (t) { | ||
| // t floats 0→1 over the period | ||
| // Update element attributes based on t | ||
| }, 10000); // period in ms | ||
| } | ||
| ``` | ||
|
|
||
| 4. Register in the `FIGURES` map at the bottom of `figures.js`. | ||
|
|
||
| ### loop() API | ||
|
|
||
| ```javascript | ||
| loop(host, fn, period = 6000, opts = {}) | ||
| // fn(localT) — called every frame. localT is 0→1 over the period. | ||
| // opts.staticT — frame to show when motion is reduced (default: 0.62) | ||
| // Hover-pause: built in (mouseenter pauses, mouseleave resumes) | ||
| // Reduced-motion: renders one static frame and stops | ||
| ``` | ||
|
|
||
| ### Animation Patterns | ||
|
|
||
| - **Staged progress**: `var stage = Math.floor(t * stages)` to divide animation into discrete steps. | ||
| - **Sub-stage timing**: `var tInStage = (t * stages) - stage` for progress within a step. | ||
| - **Easing**: use `easeIO(t)` for smooth multi-segment motion. | ||
| - **Softmax for attention**: `softmax(scores, temperature)` for attention weight visualization. | ||
|
|
||
| --- | ||
|
|
||
| ## Static SVG Figures (6 existing) | ||
|
|
||
| Standalone SVGs in `site/assets/figures/`. These are not interactive — they are embedded in lesson markdown as standard images. | ||
|
|
||
| ### Adding a Static SVG | ||
|
|
||
| 1. Author an SVG following the style guide (`STYLE.md`). | ||
| 2. Save as `site/assets/figures/<NNN>-<slug>.svg` using the next available FIG number from `INDEX.md`. | ||
| 3. Add a row to the table in `INDEX.md`. | ||
| 4. Reference in lesson markdown: | ||
| ```markdown | ||
|  | ||
| ``` | ||
| 5. Verify at 480px, 720px, 1200px viewport widths. | ||
|
|
||
| --- | ||
|
|
||
| ## Embedding in Lessons | ||
|
|
||
| ### Interactive or Animated Figure | ||
|
|
||
| ```markdown | ||
| ```figure | ||
| widget-name-slug | ||
| ``` | ||
|
|
||
| ```figure | ||
| widget-name-slug | ||
| {"configKey": "configValue"} | ||
| ``` | ||
| ``` | ||
|
|
||
| ### Static SVG | ||
|
|
||
| ```markdown | ||
|  | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Testing | ||
|
|
||
| ### Interactive Widgets | ||
|
|
||
| 1. Open the lesson on the deployed site or locally via `site/lesson.html?path=phases/XX-phase/YY-lesson`. | ||
| 2. Verify the figure mounts with no console errors. | ||
| 3. Drag every slider — output should update in real time. | ||
| 4. Test both light and dark themes (toggle top-right). | ||
| 5. Test at 320px, 768px, and 1200px viewport widths. | ||
|
|
||
| ### Animated Explainers | ||
|
|
||
| 1. Open the target lesson page. | ||
| 2. Verify the animation loops smoothly at 60 fps. | ||
| 3. Hover over the figure — animation should pause. | ||
| 4. Enable `prefers-reduced-motion` in browser DevTools — figure should show a static frame. | ||
|
|
||
| --- | ||
|
|
||
| ## Convention Summary | ||
|
|
||
| | Rule | Details | | ||
| |------|---------| | ||
| | Language | Vanilla ES5 for module files, ES6+ for `figures.js` | | ||
| | Dependencies | None — stdlib only | | ||
| | Theming | CSS custom properties (`var(--blueprint, #3553ff)`) | | ||
| | Reduced motion | Required — every entry point must check | | ||
| | Coordinates | Always `.toFixed(1)` | | ||
| | Figure naming | `kebab-case-slug` matching the concept | | ||
| | Registration | `LF.register({...})` for interactive, `FIGURES` map for animated | | ||
| | Embedding | ` ```figure ` fence in `docs/en.md` | | ||
| | Caption | Every figure needs an educational `.lf-cap` | | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,9 @@ | |
|
|
||
| Every figure shipped under `site/assets/figures/` is listed below. FIG numbers are global, monotonically increasing, and never reused. | ||
|
|
||
| The aesthetic is documented in the `blueprint-diagram` Claude Code skill, which is distributed separately from this repo (per the project's "no vendor/tooling artifacts in repos" rule). The skill source lives under `~/.claude/skills/blueprint-diagram/` once installed; ask a maintainer for the install path or follow the [How to add](#how-to-add) section below for a manual workflow that does not require the skill. | ||
| The visual style is defined in [`STYLE.md`](STYLE.md) — read it before authoring a new figure. For the interactive widget system (slider-driven, theme-aware figures embedded via the ` ```figure ` fence), see [`site/CONTRIBUTING-FIGURES.md`](../CONTRIBUTING-FIGURES.md). | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the contributor-guide link target. From Suggested fix- see [`site/CONTRIBUTING-FIGURES.md`](../CONTRIBUTING-FIGURES.md)
+ see [`site/CONTRIBUTING-FIGURES.md`](../../CONTRIBUTING-FIGURES.md)Also applies to: 35-35 🤖 Prompt for AI Agents |
||
|
|
||
| The aesthetic is also documented in the `blueprint-diagram` Claude Code skill, distributed separately from this repo. The skill source lives under `~/.claude/skills/blueprint-diagram/` once installed; ask a maintainer for the install path or follow the [How to add](#how-to-add) section below for a manual workflow that does not require the skill. | ||
|
|
||
| | FIG | slug | phase | lesson | added | notes | | ||
| |---|---|---|---|---|---| | ||
|
|
@@ -25,14 +27,29 @@ The aesthetic is documented in the `blueprint-diagram` Claude Code skill, which | |
|
|
||
| ## How to add | ||
|
|
||
| ### Interactive figure (slider-driven, theme-aware) | ||
|
|
||
| 1. Add a widget function in the appropriate `site/figures-<topic>.js` module file. | ||
| 2. Register it via `LF.register({ 'slug-name': fn })`. | ||
| 3. Embed in the lesson's `docs/en.md` with a ` ```figure ` fence block. | ||
| 4. See [`site/CONTRIBUTING-FIGURES.md`](../CONTRIBUTING-FIGURES.md) for the full walkthrough. | ||
|
|
||
| ### Animated SVG explainer (auto-loop, hover-pause) | ||
|
|
||
| 1. Add a function in `site/figures.js` using the `loop()` utility. | ||
| 2. Add to the `FIGURES` map at the bottom of the file. | ||
| 3. Embed via the same ` ```figure ` fence. | ||
|
|
||
| ### Static SVG diagram | ||
|
|
||
| If you have the `blueprint-diagram` skill installed: | ||
|
|
||
| 1. Run the skill with a description of the concept. | ||
| 2. The skill writes the SVG to `site/assets/figures/NNN-slug.svg`, appends a row here with the next available number, and (if asked) wires the figure into the relevant lesson markdown via ``. | ||
|
|
||
| If you don't have the skill, do it manually: | ||
|
|
||
| 1. Author an SVG in the cream + blueprint aesthetic (cream `#fafaf5` paper, `#3553ff` blueprint blue strokes, JetBrains Mono uppercase labels with leader lines, no other chromatic accents). | ||
| 1. Follow the style conventions in [`STYLE.md`](STYLE.md) (cream `#fafaf5` paper, `#3553ff` blueprint blue strokes, JetBrains Mono uppercase labels with leader lines, no other chromatic accents). | ||
| 2. Save as `site/assets/figures/<NNN>-<slug>.svg` using the next available FIG number from the table above. | ||
| 3. Add a row to the table here with the FIG number, slug, target phase + lesson, today's date, and a one-line note. | ||
| 4. Reference the figure from the lesson markdown as ``. | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reconcile the widget count with the style guide.
This says
140+ existing, butSTYLE.mdalready says134+ across 13 modules. Please keep the headline in sync or remove the exact count.🤖 Prompt for AI Agents