fix(frontend+api): wire R/ggplot2 into code viewer, libraries page, languages count#6961
Merged
Merged
Conversation
…anguages count Three R/ggplot2 rollout gaps reported by users after PR #6951 merged. ## 1. Code viewer 404 on /scatter-basic/r/ggplot2 `ImplRepository.get_code()` accepts a language_id but defaults to "python", and the `/specs/{spec_id}/{library}/code` endpoint never passed one through. R rows were filtered out at the WHERE clause and the endpoint returned 404 → frontend showed an empty code panel. - API: add optional `?language=` query param (defaults to "python" for backwards compat). Include language in the cache key so Python and R impls under the same library_id can't collide. - Frontend: `useCodeFetch` accepts an optional `language` arg, includes it in the cache key, and only appends `?language=` when it diverges from python so Python URLs and tests remain unchanged. - `SpecPage` passes `urlLanguage` (from the route) to fetchCode/getCode and `impl.language` to the copy-to-clipboard path. ## 2. "languages: 1" on the landing strip `NumbersStrip.tsx` hardcoded `'1'` for the languages tile. - API: add `languages` to `StatsResponse`, computed from the distinct set of `lib.language_id` (falls back to `len(LANGUAGES_METADATA)` when libraries are unavailable). - Frontend: bind to `stats.languages` with a "—" fallback during load. ## 3. ggplot2 missing from /libraries `app/src/constants/index.ts:LIBRARIES` was a hardcoded 9-item list (matplotlib, seaborn, ...) without ggplot2, so the LibrariesPage grid silently skipped it. Added ggplot2 to the list (alpha order, between bokeh and highcharts) and to `LIB_ABBREV` as `gg`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Follow-up to PR #6951 fixing three rollout gaps after the first non-Python (R/ggplot2) implementation merged: the code viewer 404'd for R impls, the landing strip hard-coded languages: 1, and ggplot2 was missing from /libraries.
Changes:
- API:
/specs/{spec_id}/{library}/codeaccepts?language=(defaultpython), threaded through_build_impl_codeand the Redis cache key;StatsResponsegains alanguagesfield derived from distinctlibrary.language_ids. - Frontend:
useCodeFetchaccepts an optionallanguage, includes it in cache key, and appends?language=to the URL only for non-Python;SpecPagepasses throughurlLanguage/impl.language;NumbersStripbinds tostats.languages. - Constants:
ggplot2added toLIBRARIES(alpha order) andLIB_ABBREV(gg).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| api/routers/specs.py | Adds language query param to code endpoint and includes it in cache key + repo lookup |
| api/routers/stats.py | Computes distinct-language count from libraries, with LANGUAGES_METADATA fallback |
| api/schemas.py | Adds languages: int = 0 to StatsResponse |
| app/src/hooks/useCodeFetch.ts | Optional language param; cache keyed by specId:language:library; query param only for non-python |
| app/src/hooks/useCodeFetch.test.ts | New tests for ?language=r URL and per-language cache separation |
| app/src/pages/SpecPage.tsx | Passes urlLanguage to fetchCode/getCode, and impl.language to copy-to-clipboard |
| app/src/components/NumbersStrip.tsx | Binds languages value to stats.languages with em-dash fallback |
| app/src/constants/index.ts | Adds ggplot2 to LIBRARIES and gg to LIB_ABBREV |
| tests/unit/api/test_stats.py | Asserts languages == 1 for single mocked library |
| tests/unit/api/test_schemas.py | Updates serialization assertion and adds languages field test |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Ruff format fold the multi-line function signatures back onto single lines after the language/languages additions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
MarkusNeusinger
pushed a commit
that referenced
this pull request
May 17, 2026
PR #6961 deferred a known `tsc` error under "Out of scope" and that deferral broke every subsequent frontend Cloud Build — the language count, ggplot2 card, and R code viewer fixes never reached anyplot.ai even though the PR merged green. Codify the rule so the next latent blocker gets fixed in the same PR instead of parked.
MarkusNeusinger
added a commit
that referenced
this pull request
May 17, 2026
## Why The frontend changes from [PR #6961](#6961) — `languages` count on the landing strip, ggplot2 card on `/libraries`, R code viewer on `/scatter-basic/r/ggplot2` — are merged on `main`, but production still shows the pre-#6961 state: ```bash $ curl -s https://anyplot.ai/assets/constants-Cv1rI8LA.js | head -c 200 …LIBRARIES=['altair','bokeh','highcharts',…] # no ggplot2 $ curl -s https://anyplot.ai/assets/LandingPage-Bluw1eOY.js | grep -oE '.{20}languages.{20}' …children:[{value:`1`,label:`languages`}… # hardcoded '1' ``` All served assets carry `last-modified: Sat, 16 May 2026 20:04:15 GMT` — about 2.5 h **before** #6961 merged. The API was redeployed (`/stats` now returns `"languages":2,"libraries":10`), but the frontend Cloud Run revision is stale. ## Root cause The frontend Cloud Build (`app/cloudbuild.yaml` → `yarn build` = `tsc && vite build`) fails at the `tsc` step: ``` src/components/CodeHighlighter.tsx(3,15): error TS7016: Could not find a declaration file for module 'react-syntax-highlighter/dist/esm/languages/prism/r'. '…/react-syntax-highlighter/dist/esm/languages/prism/r.js' implicitly has an 'any' type. ``` `@types/react-syntax-highlighter` actually does ship an ambient declaration for this exact path (line 2768 of its `index.d.ts`), but with `moduleResolution: "bundler"` tsc resolves the import to the sibling `.js` file first and never reaches the @types index — only `r` trips, `python` from the line above happens to resolve through the cached package types. Net effect: `tsc` exits non-zero, `vite build` never runs, no new Docker layer, Cloud Run keeps serving the previous revision. Docker build log confirmed this: ``` ERROR: build step 0 "gcr.io/cloud-builders/docker" failed: step exited with non-zero status: 2 The command '/bin/sh -c yarn build' returned a non-zero code: 2 ``` PR #6961 listed this exact TS error under "Out of scope" — it had been latent since #6944 added the R import, and only became a deploy blocker because #6961 was the first frontend-touching PR after the lib bumps that affect tsc behavior. ## Fix Add `app/src/types/react-syntax-highlighter.d.ts` declaring the missing module locally. A project-local shim wins over `@types`, which is enough to unblock `tsc`. The runtime import is unchanged — Prism still registers the real R grammar via `registerLanguage('r', r)`, and a grep over the rebuilt `CodeHighlighter-*.js` confirms the R keyword set is bundled: ``` break|else|for|function|if|in|next|repeat|while ``` So R syntax highlighting on `/scatter-basic/r/ggplot2` works as intended. ## Test plan - [x] `cd app && yarn build` — green (was failing on TS7016 before) - [x] `cd app && yarn test` — 459/459 green - [x] New bundle hash differs from the deployed one (`LandingPage-e58y3raq.js` vs prod `LandingPage-Bluw1eOY.js`), confirming the redeploy will publish fresh assets - [ ] After merge: Cloud Build for `anyplot-app` finishes green; `https://anyplot.ai/assets/LandingPage-*.js` no longer contains the hardcoded `{value:'1',label:'languages'}` - [ ] After deploy: landing strip shows `languages: 2`, `/libraries` shows the ggplot2 card, `/scatter-basic/r/ggplot2` code panel renders R code with highlighting ## Notes - This PR does **not** re-introduce the language count / ggplot2 / R-code-viewer logic — those landed in #6961 and are already on main. This only removes the build blocker so the existing fixes can actually reach production. - The Cloud Build "deploy-app (anyplot) ✅ Passed" check that appeared on #6961's merge commit was from `.github/workflows/notify-deployment.yml`, which is a no-op `echo` step that records a GitHub Deployment object — it does not actually report the GCP Cloud Build outcome. Worth a follow-up to either wire the real Cloud Build status back to the commit or rename the workflow so the green check doesn't mislead. --- _Generated by [Claude Code](https://claude.ai/code/session_01DdvT6aZxMm5QKU4jd8afUr)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
MarkusNeusinger
added a commit
that referenced
this pull request
May 18, 2026
Version bump for the v2.4.0 release. Release notes will be attached to the tag once this lands. ## Highlights since v2.3.0 - **R / ggplot2 added as the 10th library** + multi-language pipeline (#6944, #6961, #7052). 30 ggplot2 implementations landed across foundational plot types. - **In-app feedback widget** (#7143). - **Stats page** with Plausible visitors chart + daily-impl timeline (#6608). - **Language across the site**: `/plots?lang=` filtering, cross-language carousel, language in URLs and titles (#7141, #7142, #7144). - **UI polish**: pseudo-function styling for 404 / footer / empty state / library card (#6436); mobile fixes for `/stats`, `/mcp`, breadcrumb + FAB (#6902, #7283). - **Pipeline**: review-retry listener + stuck-jobs watchdog (#6084); daily-regen 2h → hourly (#6943). - **Dependencies**: mypy 1.20→2.1, urllib3 2.6→2.7, authlib bump, react/mui/python-minor groups. - ~1200 implementation regenerations across all 10 libraries. No SemVer-breaking changes. **Full Changelog:** v2.3.0...main 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 22, 2026
MarkusNeusinger
added a commit
that referenced
this pull request
May 22, 2026
) 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 | r` dispatch now handles `python | r | julia` uniformly. ## 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.jl` is a plotly.js wrapper (already covered via Python Plotly). Plots.jl is the alternative; revisit only if Plausible data flips. `GLMakie` / `WGLMakie` interactive backends are out of scope; `INTERACTIVE_LIBRARIES` intentionally excludes Makie. ## What's in the PR ### 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 (CSV, Colors, ColorSchemes, DataFrames, PalmerPenguins, RDatasets, Random, Statistics) **`Manifest.toml` is intentionally not committed** — it gets resolved by the first CI run; the action falls back to `Pkg.add(...)` when `Manifest.toml` is absent so first-run doesn't hard-fail. (Same model as `renv.lock` had pre-bump on the R rollout.) ### Workflows Each workflow 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 (`Figure(resolution=(1600,900)) + px_per_unit=2` → 3200×1800; `resolution=(1200,1200)` → 2400×2400) - extend header-rewrite step to handle `#`-prefixed Julia comment blocks, with prepend fallback when missing (same fix as #6947 did for Python / R) - `bulk-generate.yml`: add `makie` to `library` choices and `ALL_LIBRARIES` - `impl-merge.yml`: completion total now derives 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, `ANYPLOT_THEME` mapping, forbidden patterns (no `Plots.jl`, no `display(fig)`, no `GLMakie`/`WGLMakie`), `# `-comment header style - `plot-generator.md`: extend lead, available environment, forbidden patterns with Julia/Makie section - `quality-evaluator.md`, `workflow-prompts/ai-quality-review.md`: extend the AR-08 static-libraries list with `makie`; extend the language allow-list with `julia` - `workflow-prompts/impl-generate-claude.md`, `impl-repair-claude.md`: add the `julia | .jl | julia --project=.` row to the (language, ext, runner) table; add Julia run + format sections - `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** (the issue specifically called this out as a gap not to repeat) - `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 copy bumped to "Eleven libraries across Python, R, and Julia" - `app/src/pages/DebugPage.tsx`: `makie` column in `SpecStatus` interface (the grid template uses `LIBRARIES.length` so the matrix grows automatically) ### Backend - `api/routers/debug.py`: `SpecStatusItem` and `library_names` entries for makie - `api/routers/specs.py`: doc comment updated to note `makie is Julia` ### 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 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 ## Verified - ✅ `core/constants.py` loads: `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 regressions - ✅ `Project.toml` valid TOML, deps load - Frontend tests are wired but I couldn't run `yarn test` in this environment (no node_modules). Code follows the existing patterns from the R rollout. ## Post-merge follow-ups (called out in the issue) 1. Run `uv run python -m automation.scripts.label_manager sync` once so `library:makie`, `generate:makie`, `impl:makie:{pending,done,failed}` labels appear. 2. First CI run of `setup-julia` will resolve `Manifest.toml` — commit that lockfile in a tiny follow-up so subsequent runs use `Pkg.instantiate()` instead of the `Pkg.add` fallback. 3. Trigger `bulk-generate.yml -f library=makie` to fill the catalog (separate from this infra PR — the issue called this out as "Out of scope" / handled by the regular flow). 4. Optional `julia.anyplot.ai` marketing subdomain (mentioned in the issue's "Out of scope" section; small follow-up modeled on `python.anyplot.ai`). --- _Generated by [Claude Code](https://claude.ai/code/session_01AzjPDEE5aY2LYR5tcK3faj)_ --------- Co-authored-by: Claude <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.
Three R/ggplot2 rollout gaps surfaced after PR #6951 merged. All show wrong data despite the DB row being correct — they were always going to need a follow-up after the first non-Python impl landed.
1. Code viewer empty on
/scatter-basic/r/ggplot2`ImplRepository.get_code()` has signature `get_code(spec_id, library_id, language_id="python")`. The `/specs/{spec_id}/{library}/code` endpoint never accepted a language and never passed one through — so R rows (`language_id="r"`) failed the WHERE clause, the endpoint returned 404, and the frontend showed a blank code panel.
```bash
$ curl -s -o /dev/null -w "%{http_code}\n" https://anyplot.ai/api/specs/scatter-basic/matplotlib/code
200
$ curl -s -o /dev/null -w "%{http_code}\n" https://anyplot.ai/api/specs/scatter-basic/ggplot2/code
404
```
Fix:
2. Landing strip shows "languages: 1"
`NumbersStrip.tsx` line 16 was `{ value: '1', label: 'languages' }` — literally hardcoded, never wired to any stat.
Fix:
3. ggplot2 missing from
/libraries`app/src/constants/index.ts` had:
```ts
export const LIBRARIES = ['altair', 'bokeh', 'highcharts', 'letsplot', 'matplotlib', 'plotly', 'plotnine', 'pygal', 'seaborn'];
```
LibrariesPage iterates this list to render cards, so ggplot2 was silently skipped even though `/api/libraries` already returned it.
Fix: add `'ggplot2'` to `LIBRARIES` (alpha order, between bokeh and highcharts) and `'gg'` to `LIB_ABBREV` for compact display.
Test plan
Out of scope (separate issues)
🤖 Generated with Claude Code