Skip to content

chore(app): frontend tooling baseline — Prettier, import sorting, CI lint/type-check gates#8519

Merged
MarkusNeusinger merged 5 commits into
mainfrom
chore/frontend-tooling-baseline
Jun 9, 2026
Merged

chore(app): frontend tooling baseline — Prettier, import sorting, CI lint/type-check gates#8519
MarkusNeusinger merged 5 commits into
mainfrom
chore/frontend-tooling-baseline

Conversation

@MarkusNeusinger

Copy link
Copy Markdown
Owner

Summary

Part 1 of the frontend modernization roadmap (structure patterns inspired by a commercial template the owner licenses — patterns only, no template code, since this repo is public).

  • Prettier (run separately from ESLint, fm:check/fm:fix/fix:all scripts) + one-time mechanical reformat as its own commit
  • ESLint: eslint-plugin-perfectionist sorted imports with semantic groups (react → external → @muisrc/ internal → relative), eslint-plugin-unused-imports, eslint-config-prettier; the ~60 hand-maintained browser globals replaced by the globals package (no-undef off for TS — tsc covers it)
  • Test files are now type-checked via new tsconfig.test.json (yarn type-check covers app + tests). Fixed the 63 pre-existing type errors that surfaced (mocks missing the language field, globalglobalThis, untyped vi.fn()s, …) — no assertions weakened
  • CI hardening: test-frontend job now runs yarn lint, yarn fm:check, and yarn type-check before tests. Until now no frontend lint/type-check ran anywhere in CI; type errors only surfaced at Cloud Build deploy time (cf. the fix(frontend+api): wire R/ggplot2 into code viewer, libraries page, languages count #6961/feat(ggplot2): add R/ggplot2 library + multi-language pipeline #6944 incident)
  • vite-plugin-checker: TS + ESLint feedback as a browser overlay during yarn dev (build-time check unchanged)

Fixes broken main

#8499 (MUI 9.1.0 bump) was merged with the Run Frontend Tests check red — MUI 9.1's internal/Transition.mjs does a directory import of react-transition-group that Node's ESM loader rejects, breaking 11 test files. Fixed by inlining @mui/* in vitest (server.deps.inline). Consider making Run Frontend Tests a required check so this can't auto-merge red again.

Commits (review individually — the reformat is huge but pure)

  1. chore(app): tooling configs + CI
  2. style(app): mechanical reformat (138 files, no logic)
  3. fix(app): vitest MUI inline (unbreaks main)
  4. fix(app): test-file type fixes for the new gate

Verification

yarn lint (0 errors, 4 pre-existing react-refresh warnings) · yarn fm:check ✓ · yarn type-check (app + tests) ✓ · yarn test 536/536 ✓ · yarn build

🤖 Generated with Claude Code

MarkusNeusinger and others added 4 commits June 9, 2026 22:32
- Add prettier + eslint-config-prettier (formatting, run separately from ESLint)
- Add eslint-plugin-perfectionist (sorted imports with semantic groups) and
  eslint-plugin-unused-imports
- Replace ~60 hand-maintained browser globals in eslint.config.js with the
  globals package; disable no-undef for TS files (tsc covers it)
- Add tsconfig.test.json so test files are finally type-checked
- Add vite-plugin-checker: TS + ESLint overlay during yarn dev (addresses the
  latent-tsc-error-breaks-Cloud-Build failure mode)
- New scripts: lint:fix, fm:check, fm:fix, fix:all; type-check now covers tests
- CI: test-frontend job now runs lint, fm:check, and type-check before tests

Part 1 of the frontend modernization roadmap (Minimal-template-inspired
structure; patterns only, no template code).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pure formatting commit, no logic changes: sorted imports (perfectionist
groups) and Prettier formatting across app/ sources.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PR #8499 (MUI 9.1.0) was merged with the frontend test check red: MUI's
internal/Transition.mjs imports react-transition-group/TransitionGroupContext
as a directory import, which Node's native ESM loader rejects, failing 11
test files on main. Inlining @mui/* lets Vite's resolver handle it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Test files were never type-checked and had drifted from the real types
(63 errors across 12 files): mocks missing the required language property
(added with the JS-libraries expansion), global.fetch instead of
globalThis.fetch, untyped vi.fn() mocks, a never-returning throw component,
and Array.prototype.at not in the lib target. All fixed without weakening
any test assertions; 536 tests still pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 9, 2026 20:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 143 out of 146 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

app/src/hooks/useFilterFetch.test.ts:17

  • vi.stubGlobal('fetch', ...) is not reverted by vi.restoreAllMocks(). Without an explicit unstub, the global fetch can leak into other test files and make the suite order-dependent/flaky. Add vi.unstubAllGlobals() (or vi.unstubGlobal('fetch')) in afterEach.

Comment on lines +81 to 84
} finally {
pendingRef.current.delete(key);
setIsLoading(false);
}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid finding, but pre-existing logic (this PR is tooling + mechanical reformat only, no behavior changes). Deferred to the upcoming API-client PR, which rewrites useCodeFetch anyway — the loading state will become a pending-counter there.

Comment on lines 8 to 13
vi.mock('../hooks/useCodeFetch', () => ({
useCodeFetch: () => ({ fetchCode: vi.fn().mockResolvedValue('print("hello")'), cache: new Map() }),
useCodeFetch: () => ({
fetchCode: vi.fn().mockResolvedValue('print("hello")'),
cache: new Map(),
}),
}));

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied — the mock now mirrors the real hook contract (fetchCode, getCode, isLoading) and the bogus cache field is gone. See latest commit.

Copilot review finding: the mock exposed a nonexistent cache field and
omitted getCode/isLoading, hiding contract drift from the test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MarkusNeusinger

Copy link
Copy Markdown
Owner Author

Note on the red codecov/patch/frontend check: patch coverage (67% vs 80% target) is an artifact of the mechanical reformat — all 138 reformatted files count as "changed lines", so every pre-existing uncovered line in them now counts against the patch. Project coverage is unchanged (within the 1% threshold; codecov/project is green). No actual code became less tested in this PR.

@MarkusNeusinger MarkusNeusinger merged commit c6fbc3d into main Jun 9, 2026
12 of 13 checks passed
@MarkusNeusinger MarkusNeusinger deleted the chore/frontend-tooling-baseline branch June 9, 2026 22:01
MarkusNeusinger added a commit that referenced this pull request Jun 9, 2026
## Summary

Part 2 of the frontend modernization roadmap — **stacked on #8519**
(base = `chore/frontend-tooling-baseline`; GitHub will auto-retarget
this PR to `main` once #8519 merges and its branch is deleted).

- `tsconfig.json`: `paths: { "src/*": ["./src/*"] }` — no `baseUrl`
(deprecated in TS 6; paths resolve relative to the tsconfig since TS
4.1)
- `vite.config.ts` **and** `vitest.config.ts`: matching `resolve.alias`
(vitest does not inherit vite's)
- All **429 relative specifiers across 118 files** rewritten to absolute
`src/…` imports — covers `import … from`, side-effect imports, dynamic
`import()` (lazy routes), and `vi.mock()` specifiers. Purely mechanical,
no logic changes.

Template-style `src/` prefix chosen over `@/`: unambiguous (no npm-scope
confusion) and groups cleanly under the perfectionist `internal` import
group introduced in #8519.

## Verification

`yarn lint` (0 errors) · `yarn fm:check` ✓ · `yarn type-check` (app +
tests) ✓ · `yarn test` 536/536 ✓ · `yarn build` ✓ · `grep` confirms 0
remaining relative imports in `app/src`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
MarkusNeusinger added a commit that referenced this pull request Jun 9, 2026
## Summary

Part 5 of the frontend modernization roadmap.

- `src/lib/api.ts`: `apiGet`/`apiPost` typed fetch wrappers that throw
`ApiError` on non-2xx, plus an `endpoints` registry building every
backend path from `CONFIG.api.baseUrl` (code, plots/filter, specs,
insights, feedback, download, …)
- `fetchWithAuth` (debug API: CF Access cookie + `X-Admin-Token`) moves
out of `DebugPage` into `lib/api` as a named export
- All **14 raw `fetch()` call sites** across hooks/pages/components
migrated; every non-2xx and abort code path preserved per call site
(silent-skip stays silent, user-visible error strings unchanged)
- `useCodeFetch`: `isLoading` is now a pending-request **counter** — a
completing request no longer clears the loading state while another
request is in flight. This resolves the deferred Copilot finding from
#8519.
- Tests keep mocking `globalThis.fetch`, so they still assert the real
constructed URLs end-to-end

## Verification

`yarn lint` ✓ · `yarn fm:check` ✓ · `yarn type-check` (app + tests) ✓ ·
`yarn test` ✓ · `yarn build` ✓ · grep: no raw `fetch(` outside
`lib/api.ts`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
MarkusNeusinger added a commit that referenced this pull request Jun 10, 2026
…tion (#8596)

## Summary

Part 11 (final) of the frontend modernization roadmap.

- **`app/ARCHITECTURE.md`**: directory layout
(routes/layouts/pages/sections/components/hooks/lib/theme), conventions
(`src/` alias imports, `paths.*` URL registry, `lib/api` client, theme
tokens, feature folders), data flow, testing pattern, quality gates, and
how-to-add recipes for pages/sections/hooks/endpoints
- **`agentic/docs/project-guide.md`**: frontend section now lists the
full gate (`lint`, `fm:check`, `type-check` incl. tests, `test`),
mentions the dev-time checker overlay, and links the new architecture
doc

With this, the roadmap is complete: tooling baseline (#8519), src/
aliases (#8520), theme split (#8525), global-config (#8529), API client
(#8531), routes registry (#8546), structure split (#8547), FilterBar
(#8559), SpecTabs (#8564), MapPage hook (#8581).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
MarkusNeusinger added a commit that referenced this pull request Jun 10, 2026
Version bump for the v3.0.0 release. Full release notes will be attached
to the tag once this lands (draft release already prepared).

## Why a major version

- **Highcharts Python → JavaScript was a clean break** (#8516): all 322
legacy `highcharts.py` implementations were removed and replaced by
native `highcharts.js` 12.6.0.
- The catalog scope changed fundamentally: **2 → 4 languages, 10 → 15
libraries**.
- The **Imprint palette** replaced Okabe-Ito in every implementation — a
complete visual identity change.

## Highlights since v2.4.0

- **Julia / Makie.jl added as the 3rd language** (#7613) — 74
implementations.
- **JavaScript added as the 4th language** with Chart.js, D3.js, Apache
ECharts and a Node 22 + Playwright browser render harness emitting PNG +
interactive HTML (#8244, #8251).
- **MUI X Charts** as the first React/TSX library (#8517).
- **Highcharts migrated to native JavaScript** (clean break, #8516).
- **Imprint palette**: 8 colorblind-safe hues + 3 semantic anchors;
~1,300 implementations migrated in one wave (#7692, #7776#7798);
`/palette` page rebuilt with OKLCH wheel + ΔE matrices (#8125).
- **Frontend modernization**: 11-PR restructure of `app/` + CI
lint/format/type-check gates + `ARCHITECTURE.md` (#8519#8596).
- **Render quality**: canvas halved to 3200×1800 / 2400×2400 (#7387),
hard canvas-size gate (#7517), AR-09 edge-clipping auto-reject (#7528).
- **Pipeline**: watchdog rescues 3 more stuck-PR failure modes (#7687),
daily-regen 10×/day on Sonnet (#7717, #7286), alembic dual-head fix for
Postgres sync (#7285).
- 885 regenerations + 310 new implementations; 21 dependency updates.

Known follow-up (not in this PR): `highcharts-core` is still listed in
`pyproject.toml` although the Python wrapper is no longer used (deferred
in #8516).

**Full Changelog:**
v2.4.0...main

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants