ohif-viewer/platform/app
Bill Wallace f1cc2ee13a
feat: Update to use pnpm (#6031)
* Initial pnpm change

* Install/update in pnpm sort of works

* Attempt to fix install

* fix pnpm

* Refactor build process to use RSPack instead of Webpack across multiple extensions and modes. Update package.json scripts for development and production builds, and adjust webpack configuration files to accommodate new plugin imports and settings.

* Update RSPack dependencies to version 2.0.0 across the project, enhancing compatibility and performance. Refactor webpack configuration in multiple extensions and modes to utilize the new library structure for UMD output. Adjust package.json scripts and settings for improved build processes.

* Implement migration guide for OHIF 3.13, detailing the transition from Webpack to Rspack v2, the shift to pnpm workspaces, and the increase in minimum Node.js version to 24. Include new build commands, plugin replacements, and updates to package configurations across the monorepo.

* Fix some dev:fast bugs

* Move netlify to top level and remove webpack builds

* Update version script to deal with lerna missing

* chore(tests): Update multiple screenshot test images for various specs

* feat(screenshot-reviewer): Add screenshot review tool and update package.json scripts

* fix(DICOMSRDisplayTool): Improve actor presence check in viewport

* chore(tests): Update multiple screenshot assets for various specs

* chore(tests): Integrate waitForPaintToSettle and waitForViewportsRendered in multiple specs for improved rendering stability

* chore(tests): Update screenshot assets for SEGHydration and SEGNoHydration specs

* test: update progressive loading screenshots

* jest 30 test fixes for compatibility with pnpm cs3d

* Use correct setDisplaySets instead of setDataId

* fix: Naming change for LegacyVolumeViewport3D

* Update to allow tolerance for contour tests

* update

* fix

* refactor: Replace instanceof checks with utility functions for viewport type validation

* fix: Update createSegmentationForViewport to handle undefined displaySetInstanceUID gracefully

* bun lock

* chore(pnpm): align workspace setup to cornerstone3D and address PR review

- .npmrc / pnpm-workspace.yaml: mirror cs3d (node-linker hoisted,
  strict-peer-dependencies=false, link/prefer workspace packages,
  minimumReleaseAge, frozenLockfile); sync axios 1.17.0 + tmp override
- root: packageManager pnpm@11.4.0, engines pnpm >=11, wire preinstall.js
- restore preinstall.js (token/private-repo + CLAUDE->AGENTS symlink)
- playwright.yml: keep base CS3D-integration workflow, switch only the
  package manager (bun/yarn -> pnpm) and node 20 -> 24
- webpack.base.js: revert prod devtool to source-map (drop hidden-source-map)
- remove @percy/cypress; .netlify + cli templates engines pnpm >=11
- Dockerfile pin pnpm@11; document tests/globalSetup.ts warmup
- drop dicom-sr -> measurement-tracking edge (breaks pnpm cyclic dep)

* chore(pnpm): regenerate lockfile and restore cs3d:* dev scripts

- Regenerate pnpm-lock.yaml against the resolved workspace (cycle removed,
  cs3d 4.22.10, workspace:* internal deps).
- Restore cs3d:checkout/check/build/watch/install/link/unlink helper scripts
  (dropped when taking the PR's root scripts), converted yarn -> pnpm since
  the local cornerstone3D checkout is now pnpm too.

* Merge base branch issues

* Link ohif app

* ci: pin pnpm to 11.4.0 in action-setup (was version: latest)

version: latest floats across runs and breaks reproducibility. Pin to the repo's packageManager version (pnpm@11.4.0) in both playwright and build-docs workflows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: Accidental commit of .npmrc config

* Fix build issues

* build fix

* Dependency fixes

* fix: Dependency bug in app on extensions/modes

* Fix output configuration

* Replace percy screenshots with native cypress

* Remove percy screenshot entirely

* fix: Build issues

* force click to prevent canvas cover issues

* Enable swiftshader

* Update launch of electron

* fix: Broken size calculation

* Empty change to force a re-build

* fix(cypress): generate ui-next tailwind classes; drop unsupported electron arg

Tailwind only scanned @ohif/ui-next via ../../node_modules/@ohif/ui-next, which no longer resolves under the pnpm layout, so ui-next-unique classes (e.g. toolbar split-button sizing) were never generated. Those buttons' hit-boxes collapsed, producing Cypress 'covered by element' failures on toolbar interactions. Scan ui-next by direct filesystem path like ui/extensions/modes.

Also stop pushing --enable-unsafe-swiftshader into Electron's launchOptions.args (Electron ignores it and warns); it is supplied via ELECTRON_EXTRA_LAUNCH_ARGS in CI. The arg is still pushed for non-electron chromium (local chrome).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(e2e): disable dev-server overlay during coverage runs

The rspack dev-server client overlay injects an iframe (id=rspack-dev-server-client-overlay) that intercepts pointer events, causing Playwright/Cypress clicks on toolbar buttons to time out (e.g. MicroscopyPanel). Disable the overlay when COVERAGE=true (e2e/Playwright webServer) while keeping it for normal local dev.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(microscopy): provide dicom-microscopy-viewer runtime assets

The microscopy viewer is loaded at runtime via peerImport('dicom-microscopy-viewer'), which fetches the copied asset served at /dicom-microscopy-viewer/. Two issues prevented those assets from reaching dist, so the viewer never initialized and drawing produced no measurement row:

1) dicom-microscopy-viewer was declared in no workspace package.json (only under libs/@cornerstonejs), so it was not installed at root node_modules and the pluginConfig copy source did not exist. Declare it (0.48.6, matching libs) in the microscopy extension.

2) createCopyPluginToDist appended the public/dist folder name to entries that specify an explicit directory, breaking the dicom-microscopy-viewer public entry (looked for .../dynamic-import/public). Use an explicit directory as-is; only append the folder name for package-derived entries.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Update to pnpm 11.5.2 and cs3d 5.0.2

* Lock file

* fix: Update to newer versions of actions to try to fix hang

* Remove unnecessary version

* fix: Tests that are flaky

* PR comments

* Incorrect run name

* docs: Explain pluginConfig tooling

* Updated notes on pluginConfig and PR comments

* fix: resolve plugins in rsbuild build and fix directory-based asset copy

rsbuild.config.ts: merge getPluginResolveAliases() and an @ohif/app$ alias into resolve.alias, and add resolve.modules (root, platform/app, platform/ui node_modules) so extensions resolve their shared @ohif/* imports. Brings the rsbuild (dev:fast) path to parity with webpack.pwa.js / webpack.base.js.

writePluginImportsFile.js: treat a 'directory' on an extension/mode entry as the package root and copy its public/ and dist/ subdirs instead of the whole directory; public-section entries keep copying their directory verbatim via a new literalDirectory flag.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor: share resolve alias/modules between webpack and rsbuild configs

Extract the resolve.alias (@ohif/app, @, @components, ...) and the node_modules search paths into .webpack/resolveConfig.js, the single source of truth consumed by both webpack.base.js (and every per-package webpack.prod/.dev.js that merges it) and rsbuild.config.ts. getModules(srcDir) appends the building package's own source root, preserving the previous per-package behavior. Ends the drift where the rsbuild path kept missing aliases/module paths that webpack.base.js already had.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Add a timeout on git fetch and avoid all the unnecessary mirrros

* PR comments and tests

* Remove cache to prevent corrupting the cache key/setup.

* Fix stale/corrupted pnpm installer

---------

Co-authored-by: Alireza <ar.sedghi@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 16:04:56 -04:00
..
.recipes fix(security): For bun, enforce frozen lockfile. For yarn, strongly suggest using frozen lockfile. (#5508) 2025-10-24 16:48:35 -04:00
.webpack feat: Update to use pnpm (#6031) 2026-06-12 16:04:56 -04:00
assets chore(build): try to build demo and docs (#3434) 2023-06-06 13:34:26 -04:00
cypress feat: Update to use pnpm (#6031) 2026-06-12 16:04:56 -04:00
public feat(WorkList): New Study List (WorkList based on ui-next); old study list renamed to LegacyWorklist (#6005) 2026-05-28 12:26:30 -04:00
src feat(WorkList): New Study List (WorkList based on ui-next); old study list renamed to LegacyWorklist (#6005) 2026-05-28 12:26:30 -04:00
.all-contributorsrc chore(prettier): full repo linting and code reformatting once and for all (#3627) 2023-09-01 16:19:39 -04:00
.browserslistrc chore(build): try to build demo and docs (#3434) 2023-06-06 13:34:26 -04:00
.dockerignore chore(build): try to build demo and docs (#3434) 2023-06-06 13:34:26 -04:00
.env chore(build): try to build demo and docs (#3434) 2023-06-06 13:34:26 -04:00
.env.example chore(build): try to build demo and docs (#3434) 2023-06-06 13:34:26 -04:00
.eslintignore chore(build): try to build demo and docs (#3434) 2023-06-06 13:34:26 -04:00
.gitignore OHIF with Cornerstone3D 2.0 (#4347) 2024-11-06 07:15:27 -05:00
babel.config.js chore(prettier): full repo linting and code reformatting once and for all (#3627) 2023-09-01 16:19:39 -04:00
CHANGELOG.md chore(version): Update package versions to 3.13.0-beta.89 [skip ci] 2026-06-10 00:29:36 +00:00
cypress.config.ts feat: Update to use pnpm (#6031) 2026-06-12 16:04:56 -04:00
jest.config.js feat: customization service append and customize functionality should run once (#4238) 2024-06-19 16:31:59 -04:00
jestBabelTransform.js chore(prettier): full repo linting and code reformatting once and for all (#3627) 2023-09-01 16:19:39 -04:00
LICENSE chore(build): try to build demo and docs (#3434) 2023-06-06 13:34:26 -04:00
package.json feat: Update to use pnpm (#6031) 2026-06-12 16:04:56 -04:00
pluginConfig.json feat: Add inherit from basic/longitudinal modes (#5435) 2025-10-01 14:31:26 -04:00
postcss.config.js chore(prettier): full repo linting and code reformatting once and for all (#3627) 2023-09-01 16:19:39 -04:00
preinstall.js chore(build): try to build demo and docs (#3434) 2023-06-06 13:34:26 -04:00
README.md fix(security): For bun, enforce frozen lockfile. For yarn, strongly suggest using frozen lockfile. (#5508) 2025-10-24 16:48:35 -04:00
tailwind.config.js feat: Update to use pnpm (#6031) 2026-06-12 16:04:56 -04:00
tailwind.css fix(multiframe): metadata handling of NM studies and loading order (#4554) 2024-11-28 13:22:40 -05:00

@ohif/app

@ohif/app is a zero-footprint medical image viewer provided by the Open Health Imaging Foundation (OHIF). It is a configurable and extensible progressive web application with out-of-the-box support for image archives which support DICOMweb.


NPM version NPM downloads Pulls All Contributors MIT License

ATTENTION: If you are looking for Version 1 (the Meteor Version) of this repository, it lives on the v1.x branch

Why?

Building a web based medical imaging viewer from scratch is time intensive, hard to get right, and expensive. Instead of re-inventing the wheel, you can use the OHIF Viewer as a rock solid platform to build on top of. The Viewer is a React Progressive Web Application that can be embedded in existing applications via it's packaged source (ohif-viewer) or hosted stand-alone. The Viewer exposes configuration and extensions to support workflow customization and advanced functionality at common integration points.

If you're interested in using the OHIF Viewer, but you're not sure it supports your use case check out our docs. Still not sure, or you would like to propose new features? Don't hesitate to create an issue or open a pull request.

Getting Started

This readme is specific to testing and developing locally. If you're more interested in production deployment strategies, you can check out our documentation on publishing.

Want to play around before you dig in? Check out our LIVE Demo

Setup

Requirements:

Steps:

  1. Fork this repository
  2. Clone your forked repository (your origin)
  • git clone git@github.com:YOUR_GITHUB_USERNAME/Viewers.git
  1. Add OHIF/Viewers as a remote repository (the upstream)
  • git remote add upstream git@github.com:OHIF/Viewers.git

Developing Locally

In your cloned repository's root folder, run:

// Restore dependencies
yarn install --frozen-lockfile

// Stands up local server to host Viewer.
// Viewer connects to our public cloud PACS by default
yarn start

For more advanced local development scenarios, like using your own locally hosted PACS and test data, check out our Essential: Getting Started guide.

E2E Tests

Using Cypress to create End-to-End tests and check whether the application flow is performing correctly, ensuring that the integrated components are working as expected.

Why Cypress?

Cypress is a next generation front end testing tool built for the modern web. With Cypress is easy to set up, write, run and debug tests

It allow us to write different types of tests:

  • End-to-End tests
  • Integration tests
  • Unit tets

All tests must be in ./cypress/integration folder.

Commands to run the tests:

// Open Cypress Dashboard that provides insight into what happened when your tests ran
yarn run cy

// Run all tests using Electron browser headless
yarn run cy:run

// Run all tests in CI mode
yarn run cy:run:ci

Contributing

Large portions of the Viewer's functionality are maintained in other repositories. To get a better understanding of the Viewer's architecture and "where things live", read our docs on the Viewer's architecture

It is notoriously difficult to setup multiple dependent repositories for end-to-end testing and development. That's why we recommend writing and running unit tests when adding and modifying features. This allows us to program in isolation without a complex setup, and has the added benefit of producing well-tested business logic.

  1. Clone this repository
  2. Navigate to the project directory, and yarn install
  3. To begin making changes, yarn run dev
  4. To commit changes, run yarn run cm

When creating tests, place the test file "next to" the file you're testing. For example:

// File
index.js;

// Test for file
index.test.js;

As you add and modify code, jest will watch for uncommitted changes and run your tests, reporting the results to your terminal. Make a pull request with your changes to master, and a core team member will review your work. If you have any questions, please don't hesitate to reach out via a GitHub issue.

Contributors

Thanks goes to these wonderful people (emoji key):

Erik Ziegler
Erik Ziegler

💻 🚇
Evren Ozkan
Evren Ozkan

💻
Gustavo André Lelis
Gustavo André Lelis

💻
Danny Brown
Danny Brown

💻 🚇
allcontributors[bot]
allcontributors[bot]

📖
Esref Durna
Esref Durna

💬
diego0020
diego0020

💻
David Wire
David Wire

💻
João Felipe de Medeiros Moreira
João Felipe de Medeiros Moreira

⚠️

This project follows the all-contributors specification. Contributions of any kind welcome!

License

MIT © OHIF