Skip to content

feat: generate viewer links dynamically for Zarr datasets#307

Open
allison-truhlar wants to merge 86 commits intomainfrom
viewers-config
Open

feat: generate viewer links dynamically for Zarr datasets#307
allison-truhlar wants to merge 86 commits intomainfrom
viewers-config

Conversation

@allison-truhlar
Copy link
Copy Markdown
Collaborator

@allison-truhlar allison-truhlar commented Feb 2, 2026

Clickup id: 86advt10e

This PR implements dynamic viewer configuration for Zarr datasets via a build-time viewers.config.yaml file and integration of the @bioimagetools/capability-manifest library for automatic dataset-viewer compatibility detection.

Changes

  • Created viewers.config.yaml with documentation for customizing viewer configuration. This file specifies available viewers for a Fileglancer deployment. The default configuration is our current viewers: Neuroglancer, Avivator, Vol-E, and OME-Zarr Validator. Configuration is bundled at build time.

  • Added ViewersContext for managing viewer configuration. This context:

    • Loads and validates viewer configuration from YAML at initialization
    • Fetches capability manifests using @bioimagetools/capability-manifest library, or load from the /public folder bundled into the application during the build (this is currently the case since the manifests are not present on our main branch, only in this PR branch)
    • Provides getCompatibleViewers() function to determine dataset-viewer compatibility using the capability-manifest library for compatibility detection
  • Refactored useZarrMetadata to dynamically generate openWithToolUrls using ViewersContext. URLs are generated only for compatible viewers based on the getCompatibleViewers function.

  • Updated DataToolLinks to render viewer buttons dynamically by mapping over valid viewers from ViewersContext. The "Copy URL" tool is always available when a data link is available.

  • Added logo management system with convention-based naming ({name}.png), custom logo override support, and fallback logo for missing assets.

  • Added unit tests for config parsing and component tests for DataToolLinks.

  • Updated documentation with a ViewersConfiguration.md guide and updated CLAUDE.md with viewer configuration instructions.

- Custom viewers (validator, vol-e) now check for multiscales
- Ensures viewers only display for OME-Zarr datasets, not plain Zarr arrays
- Update DataToolLinks alt text to use displayName for E2E test compatibility
Add useCallback to memoize the getCompatibleViewers function in
ViewersContext to prevent unnecessary recalculations and improve
performance when filtering compatible viewers based on metadata.
Add more detailed error logging and ensure graceful degradation when:
- Capability manifests fail to load
- Viewer configuration parsing fails
- No valid viewers are configured

The application will continue with an empty viewer list and clear
console messages to help users troubleshoot configuration issues.
Copy link
Copy Markdown
Member

@neomorphic neomorphic left a comment

Choose a reason for hiding this comment

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

Looks good to me. I was able to enable and disable a viewer using the viewers.config.yaml. I added a few comments about some the code I wasn't sure on.

- previously, if a logo path wasn't found, a 404 URL was still created, so it was never falling through to the fallback_logo.
- includes checking that a fallback_logo is used when no logo is found for a viewer
- includes mock viewers.config.yaml file for CI
…EffectiveZarrStorageVersion utilities

- also splits availableVersions in the ZarrMetadataResult type into availableZarrVersions (number[]) and availableOmeZarrVersions (string[])
- copy icon had changed from img to svg
- i saved the vizarr/avivator logo under avivator.png, so needed to update vizarr -> avivator
Use validateViewer() instead of isCompatible() so that when a viewer
is filtered out, the specific reasons are logged (e.g. "Viewer does
not support OME-Zarr v3 (supports: 0.4)").
@allison-truhlar
Copy link
Copy Markdown
Collaborator Author

@krokicki @mkitti This PR is ready for re-review. I have made all the changes requested in the previous review comments (see conversation above).

Copy link
Copy Markdown
Member

@krokicki krokicki left a comment

Choose a reason for hiding this comment

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

This is really coming along!

| `frontend/viewers.config.yaml` | **Local override** — gitignored, safe to customize without merge conflicts |
| `frontend/src/config/viewers.config.yaml` | **Default config** — committed source file, used when no override exists |

Copy `frontend/viewers.config.yaml.template` to `frontend/viewers.config.yaml` to create a local override. This file is listed in `.gitignore` so your customizations will not conflict with upstream updates.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could frontend/viewers.config.yaml.template be merged into frontend/src/config/viewers.config.yaml? Then you could just copy the default config to create a local override. This would have the benefit of not duplicating the viewer URLs in two places.

| `manifest_url` | Yes | URL to a capability manifest YAML file |
| `instance_template_url` | No | Override the viewer's `template_url` from the manifest |
| `label` | No | Custom tooltip text (defaults to "View in {Name}") |
| `logo` | No | Filename of logo in `frontend/src/assets/` (defaults to `{normalized_name}.png`) |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Similar to the config, would it be possible to have a way to add custom viewer logos without triggering git changes? Maybe just adding a subfolder in assets that is already gitignored, and documenting it here? But that assumes you can put slashes in the logo filename, not sure if that's possible.

label: "View in Vol-E"
```

## Capability Manifest Files
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should document the capability manifest schema in the capability-manifest repo. This documentation could just link to a specific version (e.g. git commit) of that schema documentation.


1. The application reads the dataset's metadata (OME-Zarr version, axes, codecs, etc.)
2. For each registered viewer, the library's `validateViewer()` function compares the dataset metadata against the manifest's declared capabilities
3. Only viewers whose capabilities match the dataset are shown to the user
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we need to distinguish at least two different "levels" of capabilities, e.g.:

  • Data compatibility - will this data open in the view (or will it fail to open, or fail to render)
  • Data support - is a particular data feature supported by the viewer (maybe it loads okay, but doesn't show a piece of metadata)

Generally speaking, these capabilities are about compatibility: ome_zarr_versions, compression_codecs, rfcs_supported. The rest are about support.

Another way to think about this is like the NGFF viewer feature matrix. There is an additional dimension of information (color) which describes how the viewer behaves when presented with the data.

Incompatible viewers should not be shown, but viewers which incompletely support the data should be shown, and their warnings logged or made accessible somewhere. For example, if a viewer doesn't support zarrv3, then OME-Zarrs with NGFF version >=0.5 should not be shown. But if a viewer does not support, say, omero_metadata, the viewer should still be shown.

@@ -0,0 +1,41 @@
viewer:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since these YAML files are loaded by URL now, can we host them in the capabilities-manifest repo? That way, other non-Fileglancer consumers can access them.

bioformats2raw_layout: false

# Is the OMERO metadata used to e.g. color the channels?
omero_metadata: false
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think Neuroglancer does use OMERO metadata.

name: "Avivator"
version: "0.16.1"
repo: "https://github.com/hms-dbmi/viv"
template_url: "https://avivator.gehlenborglab.org/?image_url={DATA_URL}"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If this is Avivator, maybe the file should be called avivator.yaml?

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.

4 participants