feat(makie): add Julia + Makie.jl as the third language (Phase 5)#7613
Merged
Conversation
Adds Julia as anyplot's third language with Makie.jl (CairoMakie backend for headless PNG rendering) as its first library entry. Generalizes the multi-language plumbing introduced for R/ggplot2 in #6944 + follow-ups (#6947, #6961, #7066) so every `python | r` dispatch now handles `python | r | julia` uniformly. Closes #7612. Note on phase ordering: this ships Phase 5 (Julia) before Phases 1+2 (JavaScript family). The multi-language pipeline is already proven on R; shipping Julia next provides a cheap second non-Python validation that surfaces multi-language gaps the JS work would otherwise hit cold. The JavaScript phases remain planned in unchanged order. See §9 of docs/concepts/library-expansion.md. Why Makie over Plots.jl: distinct scientific stack (not a wrapper), ~45 % share within Julia, MIT-licensed. CairoMakie is the right backend for CI — pure-Cairo, headless, no GPU/GLFW window. PlotlyJS.jl is a plotly.js wrapper (already covered via Python Plotly). Plots.jl is the alternative; revisit only if Plausible data flips. ## Changes Constants + registry: - core/constants.py: add julia language, makie library - tests/unit/core/test_constants.py: assert julia + makie CI runtime: - .github/actions/setup-julia/action.yml: install Julia 1.11, restore from Project.toml/Manifest.toml, smoke-test a CairoMakie render - Project.toml: pin CairoMakie + Makie + dataset packages Workflows (each derives LANGUAGE+EXT from LIBRARY via a case statement; every case now has matplotlib→python, ggplot2→r, makie→julia): - impl-generate.yml, impl-repair.yml, impl-review.yml, impl-merge.yml: add the makie→julia arm; install setup-julia when language==julia; detect Julia version via `julia -e 'print(VERSION)'`; detect Makie version via Pkg.dependencies() - impl-review.yml: extend canvas-gate library-cause map with a Makie entry; extend header-rewrite step to handle `# anyplot.ai` Julia comment blocks (prepend fallback when missing) - bulk-generate.yml: add makie to library choices and ALL_LIBRARIES - impl-merge.yml: derive completion total from the actual library list rather than hardcoding 9 Prompts: - prompts/library/makie.md: new — no-workarounds policy, NOT_FEASIBLE for primary-interactivity specs, canvas hard rule (Figure(resolution=(1600,900)) + px_per_unit=2 → 3200×1800; resolution=(1200,1200) + px_per_unit=2 → 2400×2400), ANYPLOT_THEME mapping, forbidden patterns (no Plots.jl, no display(fig), no GLMakie/WGLMakie), `# `-comment header style - prompts/plot-generator.md: extend lead, available environment, forbidden patterns with Julia/Makie section - prompts/quality-evaluator.md, ai-quality-review.md: extend the static-libraries list (AR-08) with makie; extend the language allow-list with julia - prompts/workflow-prompts/impl-generate-claude.md, impl-repair-claude.md: add the julia | .jl | `julia --project=.` row to the (language, ext, runner) table - prompts/workflow-prompts/impl-similarity-claude.md: third arm for julia in the `{language}` mapping Frontend (avoids the two-follow-up-PR pattern from #6961 / #7066): - app/src/constants/index.ts: add makie to LIBRARIES, LIB_ABBREV (mk), LIB_TO_LANG (julia), LANG_DISPLAY (Julia), LANG_EXT (jl) - app/src/components/CodeHighlighter.tsx: register `julia` Prism grammar - app/src/types/react-syntax-highlighter.d.ts: declare the `prism/julia` module locally (TS7016 fix in same PR, not deferred) - app/src/components/LibraryCard.tsx: description for makie - app/src/components/PlotOfTheDay.tsx, PlotOfTheDayTerminal.tsx: `julia --project=.` runner token + .jl extension when language is julia - app/src/pages/LibrariesPage.tsx, AboutPage.tsx, PlotsPage.tsx: meta-description bumps "Eleven libraries across Python, R, and Julia" - app/src/pages/DebugPage.tsx: makie column in SpecStatus interface (grid uses LIBRARIES.length so the matrix grows automatically) Backend: - api/routers/debug.py: SpecStatusItem and library_names entries for makie Tests: - app/src/components/CodeHighlighter.test.tsx: julia-grammar case - app/src/hooks/useCodeFetch.test.ts: julia ?language= case + three- language cache-key test - app/src/pages/DebugPage.test.tsx: makie field on fixture Docs: - docs/concepts/library-expansion.md: §1 current-state table grows to 11 entries; §8 Phase 5 marked shipped; §9 records the phase- skip rationale, Makie-over-Plots.jl decision, and the CairoMakie- only scope - docs/reference/repository.md: implementations/ layout shows python/ + r/ + julia/ siblings - docs/concepts/vision.md, docs/reference/style-guide.md: pipeline- story copy ("eleven libraries in three languages") - docs/reference/plausible.md: language slug list now includes julia - prompts/README.md, agentic/docs/project-guide.md: Makie added Manifest.toml is intentionally not committed — it gets resolved by the first CI run of setup-julia; the action falls back to `Pkg.add(...)` when Manifest.toml is absent so first-run doesn't hard-fail.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds Julia as a third supported implementation language and introduces Makie.jl (via the CairoMakie backend) as the first Julia plotting library, extending the existing multi-language (Python/R) plumbing across CI workflows, prompts, backend, and frontend.
Changes:
- Extend core registries to include
julia+makie, and update unit tests accordingly. - Add CI support for Julia (composite setup action + workflow dispatch mapping + header rewrite rules).
- Wire Julia/Makie through the frontend code viewer/highlighting and related UI copy, plus targeted tests.
Reviewed changes
Copilot reviewed 36 out of 38 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
core/constants.py |
Adds julia language metadata and makie library metadata/IDs. |
tests/unit/core/test_constants.py |
Updates constants tests for makie + julia and file extensions. |
Project.toml |
Introduces Julia project deps/compat for CairoMakie-based rendering. |
.github/actions/setup-julia/action.yml |
New composite action to install Julia + deps and smoke-test CairoMakie rendering. |
.github/workflows/impl-generate.yml |
Adds makie→julia dispatch, Julia setup, and Julia version/library version detection. |
.github/workflows/impl-repair.yml |
Adds makie→julia dispatch and Julia setup step for repair runs. |
.github/workflows/impl-review.yml |
Adds makie→julia dispatch, canvas-gate guidance, and Julia header rewrite support. |
.github/workflows/impl-merge.yml |
Adds makie→julia dispatch and updates “all libraries complete” accounting for 11 libs. |
.github/workflows/bulk-generate.yml |
Adds makie to library choices and ALL_LIBRARIES. |
api/routers/specs.py |
Updates endpoint doc comment to reflect makie as Julia. |
api/routers/debug.py |
Extends debug status model/maps to include makie. |
app/src/constants/index.ts |
Adds makie to library lists and maps it to julia + jl display extension. |
app/src/components/CodeHighlighter.tsx |
Registers Prism grammar for julia. |
app/src/types/react-syntax-highlighter.d.ts |
Adds local TS module declaration for Prism Julia grammar import. |
app/src/components/CodeHighlighter.test.tsx |
Adds test coverage for Julia highlighting selection. |
app/src/components/LibraryCard.tsx |
Adds Makie library description copy. |
app/src/components/PlotOfTheDay.tsx |
Extends runner/ext display and language label/version fallback for Julia. |
app/src/components/PlotOfTheDayTerminal.tsx |
Extends runner/ext display for Julia (julia --project=. / .jl). |
app/src/hooks/useCodeFetch.test.ts |
Adds tests ensuring ?language=julia URL behavior and cache key separation. |
app/src/pages/DebugPage.tsx |
Extends SpecStatus interface with makie column field. |
app/src/pages/DebugPage.test.tsx |
Updates fixture to include makie field. |
app/src/pages/LibrariesPage.tsx |
Updates meta-description copy for 11 libraries / 3 languages. |
app/src/pages/PlotsPage.tsx |
Updates meta-description copy for 11 libraries / 3 languages. |
app/src/pages/AboutPage.tsx |
Updates meta-description copy for 11 libraries / 3 languages. |
prompts/library/makie.md |
New Makie-specific generation rules (CairoMakie-only, canvas rules, theme mapping, header style). |
prompts/plot-generator.md |
Extends generator rules for Julia/Makie runtime, header style, and feasibility constraints. |
prompts/quality-evaluator.md |
Extends evaluator framing for Julia/Makie and static-library rules. |
prompts/workflow-prompts/ai-quality-review.md |
Extends workflow review prompt for .jl + Julia language allow-list. |
prompts/workflow-prompts/impl-generate-claude.md |
Adds Julia row to (language/ext/runner) table and Julia-specific run notes. |
prompts/workflow-prompts/impl-repair-claude.md |
Adds Julia-specific run notes and style guidance. |
prompts/workflow-prompts/impl-similarity-claude.md |
Extends {language}/{ext} mapping text to include Julia/Makie. |
prompts/README.md |
Updates library-rules count to 11. |
docs/concepts/library-expansion.md |
Updates current-state table and marks Phase 5 (Julia/Makie) as shipped. |
docs/concepts/vision.md |
Updates “current stack” narrative to 11 libraries / 3 languages. |
docs/reference/repository.md |
Documents implementations layout including implementations/julia/ and .jl. |
docs/reference/style-guide.md |
Updates narrative counts to include Julia/Makie. |
docs/reference/plausible.md |
Updates language slug list to include julia. |
agentic/docs/project-guide.md |
Updates catalog overview/docs to include Makie + PNG-only list and counts. |
Comment on lines
+48
to
+57
| julia --project=. -e ' | ||
| using Pkg | ||
| if isfile("Manifest.toml") | ||
| Pkg.instantiate() | ||
| else | ||
| Pkg.add([ | ||
| "CairoMakie", "Makie", "DataFrames", "CSV", | ||
| "Colors", "ColorSchemes", "RDatasets", | ||
| "PalmerPenguins", "Random", "Statistics" | ||
| ]) |
Comment on lines
+20
to
+25
| Out of native CairoMakie scope: | ||
| - True interactivity (hover, zoom, brush, animation) — needs `GLMakie` / | ||
| `WGLMakie` | ||
| - WebGL-only effects | ||
| - Embedded D3-style network layouts (NetworkLayout.jl is allowed; use it | ||
| judiciously) |
| # Match a leading run of `#`-prefixed lines (the existing header). | ||
| # Anchored to start of file. If no header exists we fall back to | ||
| # prepending one. We must NOT match `#=` block-comment openers as | ||
| # part of the header — restrict to lines starting with `# ` or `#$`. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Three Copilot findings: 1. setup-julia fallback: drop Julia stdlibs (Random, Statistics) from the `Pkg.add([...])` list — they ship with Julia and aren't in the General registry, so `Pkg.add(\"Random\")` would error before precompile on the exact first-run case this fallback is for. They remain in Project.toml `[deps]` for the post-Manifest path. 2. makie.md: NetworkLayout.jl is not installed in the CI runtime. Replace the \"allowed; use judiciously\" wording with a hard \"not installed → return NOT_FEASIBLE\" so the generator doesn't emit `using NetworkLayout` and fail at runtime. 3. impl-review.yml: align the header-regex comment with what the pattern actually matches (`# ` + body, or bare `#` + EOL) and call out the excluded sequences explicitly (`#=` block-comment openers and `#!` shebangs).
2 tasks
MarkusNeusinger
added a commit
that referenced
this pull request
May 22, 2026
…nly (#7614) ## Summary - First impl-generate run for `makie/skewt-logp-atmospheric` ([run 26311670534](https://github.com/MarkusNeusinger/anyplot/actions/runs/26311670534)) failed at the **Setup Julia + Makie** step. All 311 transitive deps precompiled cleanly, then Julia tried to precompile the project itself and bailed: ``` ERROR: The following 1 direct dependency failed to precompile: anyplot Error: Missing source file for Base.PkgId(UUID("5f9c7e1d-…"), "anyplot") ``` - Root cause: `Project.toml` declared `name = "anyplot"` + `uuid = …` + `version = …`, which makes Julia treat the repo as a *package* and look for `src/anyplot.jl`. anyplot isn't a Julia package; it just consumes packages. - Fix: remove `name`/`uuid`/`authors`/`version`. Turns `Project.toml` into an *environment-only* project (the standard pattern used by Julia's own docs/benchmark environments). `[deps]` and `[compat]` stay untouched, so dep resolution and reproducibility are unchanged. This was hidden during PR #7613 because the `Setup Julia + Makie` action's smoke test only runs `using CairoMakie` and `save(...)` — Julia only attempts to precompile the active project itself when there are dependents being added to it, which happened on the first real impl-generate run. ## Test plan - [ ] CI green - [ ] After merge: re-trigger `gh workflow run impl-generate.yml -f specification_id=skewt-logp-atmospheric -f library=makie -f issue_number=3802` and verify `Setup Julia + Makie` completes past precompile. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Closes #7612.
Adds Julia as anyplot's third language with Makie.jl (CairoMakie backend) as its first library entry. Generalizes the multi-language plumbing introduced for R/ggplot2 in #6944 + follow-ups (#6947, #6961, #7066) so every
python | rdispatch now handlespython | r | juliauniformly.Phase ordering — heads-up
This ships Phase 5 (Julia) before Phases 1+2 (JavaScript family), which the issue called out explicitly. The multi-language pipeline is already proven on R; shipping Julia next provides a cheap second non-Python validation that surfaces multi-language gaps the JS work would otherwise hit cold. The JavaScript phases remain planned in unchanged order. See
docs/concepts/library-expansion.md§9.Why Makie over Plots.jl
Distinct scientific stack (not a wrapper), ~45 % share within Julia, MIT-licensed. CairoMakie is the right backend for CI — pure-Cairo, headless, no GPU / GLFW window.
PlotlyJS.jlis a plotly.js wrapper (already covered via Python Plotly). Plots.jl is the alternative; revisit only if Plausible data flips.GLMakie/WGLMakieinteractive backends are out of scope;INTERACTIVE_LIBRARIESintentionally excludes Makie.What's in the PR
Constants + registry
core/constants.py: addjulialanguage,makielibrarytests/unit/core/test_constants.py: assertjulia+makieCI runtime
.github/actions/setup-julia/action.yml: install Julia 1.11, restore fromProject.toml/Manifest.toml, smoke-test a CairoMakie renderProject.toml: pin CairoMakie + Makie + dataset packages (CSV, Colors, ColorSchemes, DataFrames, PalmerPenguins, RDatasets, Random, Statistics)Manifest.tomlis intentionally not committed — it gets resolved by the first CI run; the action falls back toPkg.add(...)whenManifest.tomlis absent so first-run doesn't hard-fail. (Same model asrenv.lockhad pre-bump on the R rollout.)Workflows
Each workflow derives
LANGUAGE+EXTfromLIBRARYvia a case statement. Every case now hasmatplotlib→python,ggplot2→r,makie→julia:impl-generate.yml,impl-repair.yml,impl-review.yml,impl-merge.yml: add themakie→juliaarm; installsetup-juliawhenlanguage==julia; detect Julia version viajulia -e 'print(VERSION)'; detect Makie version viaPkg.dependencies()impl-review.yml:Figure(resolution=(1600,900)) + px_per_unit=2→ 3200×1800;resolution=(1200,1200)→ 2400×2400)#-prefixed Julia comment blocks, with prepend fallback when missing (same fix as chore(ggplot2): follow-up Copilot review fixes after #6944 merge #6947 did for Python / R)bulk-generate.yml: addmakietolibrarychoices andALL_LIBRARIESimpl-merge.yml: completion total now derives from the actual library list rather than hardcoding 9Prompts
prompts/library/makie.md(new): no-workarounds policy, NOT_FEASIBLE for primary-interactivity specs, canvas hard rule,ANYPLOT_THEMEmapping, forbidden patterns (noPlots.jl, nodisplay(fig), noGLMakie/WGLMakie),#-comment header styleplot-generator.md: extend lead, available environment, forbidden patterns with Julia/Makie sectionquality-evaluator.md,workflow-prompts/ai-quality-review.md: extend the AR-08 static-libraries list withmakie; extend the language allow-list withjuliaworkflow-prompts/impl-generate-claude.md,impl-repair-claude.md: add thejulia | .jl | julia --project=.row to the (language, ext, runner) table; add Julia run + format sectionsworkflow-prompts/impl-similarity-claude.md: third arm forjuliain the{language}mappingFrontend (avoids the two-follow-up-PR pattern from #6961 / #7066)
app/src/constants/index.ts: addmakietoLIBRARIES,LIB_ABBREV: 'mk',LIB_TO_LANG: 'julia',LANG_DISPLAY: 'Julia',LANG_EXT: 'jl'app/src/components/CodeHighlighter.tsx: registerjuliaPrism grammarapp/src/types/react-syntax-highlighter.d.ts: declare theprism/juliamodule locally — TS7016 fix in same PR, not deferred (the issue specifically called this out as a gap not to repeat)app/src/components/LibraryCard.tsx: description for makieapp/src/components/PlotOfTheDay.tsx,PlotOfTheDayTerminal.tsx:julia --project=.runner token +.jlextension when language is juliaapp/src/pages/LibrariesPage.tsx,AboutPage.tsx,PlotsPage.tsx: meta-description copy bumped to "Eleven libraries across Python, R, and Julia"app/src/pages/DebugPage.tsx:makiecolumn inSpecStatusinterface (the grid template usesLIBRARIES.lengthso the matrix grows automatically)Backend
api/routers/debug.py:SpecStatusItemandlibrary_namesentries for makieapi/routers/specs.py: doc comment updated to notemakie is JuliaTests
app/src/components/CodeHighlighter.test.tsx: julia-grammar caseapp/src/hooks/useCodeFetch.test.ts: julia?language=case + three-language cache-key testapp/src/pages/DebugPage.test.tsx:makiefield on fixtureDocs
docs/concepts/library-expansion.md: §1 current-state table grows to 11 entries; §8 Phase 5 marked shipped; §9 records the phase-skip rationale, Makie-over-Plots.jl decision, and CairoMakie-only scopedocs/reference/repository.md:implementations/layout showspython/+r/+julia/siblingsdocs/concepts/vision.md,docs/reference/style-guide.md: pipeline-story copy ("eleven libraries in three languages")docs/reference/plausible.md: language slug list now includesjuliaprompts/README.md,agentic/docs/project-guide.md: Makie addedVerified
core/constants.pyloads:len(SUPPORTED_LIBRARIES)=11,SUPPORTED_LANGUAGES={'python','r','julia'}pytest tests/unit/core tests/unit/api/test_routers.py tests/unit/api/test_debug.py tests/unit/api/test_schemas.py— 213 passed, no regressionsProject.tomlvalid TOML, deps loadyarn testin this environment (no node_modules). Code follows the existing patterns from the R rollout.Post-merge follow-ups (called out in the issue)
uv run python -m automation.scripts.label_manager synconce solibrary:makie,generate:makie,impl:makie:{pending,done,failed}labels appear.setup-juliawill resolveManifest.toml— commit that lockfile in a tiny follow-up so subsequent runs usePkg.instantiate()instead of thePkg.addfallback.bulk-generate.yml -f library=makieto fill the catalog (separate from this infra PR — the issue called this out as "Out of scope" / handled by the regular flow).julia.anyplot.aimarketing subdomain (mentioned in the issue's "Out of scope" section; small follow-up modeled onpython.anyplot.ai).Generated by Claude Code