Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
5f1a624
feat: add viewers configuration template
allison-truhlar Feb 2, 2026
d0bf67c
feat: add viewer configuration types and YAML parser
allison-truhlar Feb 2, 2026
6620486
feat: add ViewersContext for dynamic viewer configuration
allison-truhlar Feb 2, 2026
24e030e
refactor: make OpenWithToolUrls dynamic using Record type
allison-truhlar Feb 2, 2026
9f5d1eb
docs: add comment explaining type assertion in parseViewersConfig
allison-truhlar Feb 2, 2026
28173ea
refactor: use ViewersContext in useZarrMetadata for dynamic viewer URLs
allison-truhlar Feb 2, 2026
3fd00d7
refactor: use ViewersContext in DataToolLinks for dynamic viewer icons
allison-truhlar Feb 2, 2026
9160eb4
chore: prettier formatting
allison-truhlar Feb 2, 2026
ecf1b62
chore: update logo names; add fallback logo
allison-truhlar Feb 2, 2026
7698348
docs: add viewers configuration guide
allison-truhlar Feb 2, 2026
69ae1b6
fix: require OME metadata for custom viewers without manifests
allison-truhlar Feb 2, 2026
3e15ae7
fix: update locators to match new defaults
allison-truhlar Feb 2, 2026
4292cdf
efactor: use committed config file instead of template
allison-truhlar Feb 2, 2026
d545e28
docs: add viewers configuration to CLAUDE.md
allison-truhlar Feb 2, 2026
d5c24e9
refactor: remove unused keys from N5OpenWithToolUrls type
allison-truhlar Feb 2, 2026
e6e1cd4
perf: memoize getCompatibleViewers function
allison-truhlar Feb 2, 2026
be8bbd5
feat: improve error handling in viewers initialization
allison-truhlar Feb 2, 2026
58d163d
chore: fix eslint warnings
allison-truhlar Feb 2, 2026
5ae87ae
fix: add validation for ome-zarr verison numbers
allison-truhlar Feb 2, 2026
4b6db2e
tests: unit tests for the viewer config parsing func
allison-truhlar Feb 2, 2026
fef30cd
tests: component tests for DataToolLinks
allison-truhlar Feb 2, 2026
82b9cfb
Merge branch 'main' into viewers-config
allison-truhlar Feb 2, 2026
d2a4e84
fix: add ViewersProvider to unit test setup for zarr tests
allison-truhlar Feb 3, 2026
b0e97a3
fix: change how logos urls are found
allison-truhlar Feb 3, 2026
8b2af82
tests: add unit tests for the getViewerLogo func
allison-truhlar Feb 3, 2026
1ebfb3e
chore: prettier formatting
allison-truhlar Feb 3, 2026
5cacb67
refactor: move valid ome zarr versions to config file
allison-truhlar Feb 3, 2026
7ec34ec
refactor: add zod for viewer config validation
allison-truhlar Feb 3, 2026
30f0853
refactor: update tests for ome zarr version in config; zod error msgs
allison-truhlar Feb 3, 2026
bc867c8
docs: add valid_ome_zarr_versions to viewer config docs
allison-truhlar Feb 3, 2026
83dd34f
refactor: move metadata.multiscale check back to useZarrMetadata hook
allison-truhlar Feb 3, 2026
da8dd86
feat: add capability manifest files for all viewers
allison-truhlar Feb 9, 2026
10bafa7
refactor: simplify viewers config to manifest_url entries
allison-truhlar Feb 9, 2026
cd05c36
refactor: update ViewersContext for new capability-manifest API
allison-truhlar Feb 9, 2026
d892ca1
test: rewrite viewersConfig unit tests for manifest_url API
allison-truhlar Feb 9, 2026
d5261a5
test: rewrite DataToolLinks component tests for manifest_url API
allison-truhlar Feb 9, 2026
05957ba
docs: update viewer configuration docs for manifest-based system
allison-truhlar Feb 9, 2026
0fce05c
chore: prettier formatting
allison-truhlar Feb 9, 2026
4ab4fe6
chore: bump capability-manifest version
allison-truhlar Feb 9, 2026
d7ea968
fix: update capability-manifest in package-lock.json
allison-truhlar Feb 12, 2026
c104803
tests: fix vole to vol-e in expected text
allison-truhlar Feb 12, 2026
0bd1731
test: remove timeout to rely on longer global timeout value
allison-truhlar Feb 12, 2026
2f86cab
chore: bump capability-manifest version
allison-truhlar Feb 12, 2026
9c629d2
fix: use relative paths for viewer manifest URLs to fix CI failures
allison-truhlar Feb 12, 2026
f4e7f51
fix: capitalize viewer names in manifests (validator → Validator, vol…
allison-truhlar Feb 12, 2026
3080e8a
fix: use viewer label for logo alt text and update test locators to m…
allison-truhlar Feb 12, 2026
06c0ab1
chore: prettier formatting
allison-truhlar Feb 12, 2026
7e46003
Merge branch 'main' into viewers-config
allison-truhlar Feb 12, 2026
1a3dff9
refactor: change manifest_urls in viewers config to the GH repo urls …
allison-truhlar Feb 25, 2026
77502ae
fix: decouple DataToolLinks tests from exact manifest_url values in v…
allison-truhlar Feb 25, 2026
f024930
fix: correct templating for avivator/vizarr instance_template_url
allison-truhlar Mar 2, 2026
67ed39a
chore: add spaces back in md file that were removed by prettier plugin
allison-truhlar Mar 4, 2026
69b09d0
fix: remove personal path
allison-truhlar Mar 4, 2026
774a1ac
feat: support local frontend/viewers.config.yaml override at build time
allison-truhlar Mar 4, 2026
6805035
fix: rename validator manifest viewer.name to OME-Zarr Validator
allison-truhlar Mar 4, 2026
e9f9649
docs: update viewers configuration docs to reflect override pattern
allison-truhlar Mar 4, 2026
59d64ac
refactor: log viewer initialization errors once at the top level only
allison-truhlar Mar 4, 2026
a1324c5
chore: add fileglancer domain to devcontainer firewall allowlist
allison-truhlar Mar 4, 2026
a9deb49
chore: prettier formatting
allison-truhlar Mar 4, 2026
27c0d81
refactor: extract resolveViewersConfigPath utility from vite.config.ts
allison-truhlar Mar 6, 2026
d4572bf
test: add unit tests for viewers.config.yaml override path resolution
allison-truhlar Mar 6, 2026
b31e918
chore: add s3.janelia.org to devcontainer firewall allowlist
allison-truhlar Mar 6, 2026
144446e
Merge branch 'main' into viewers-config
allison-truhlar Mar 6, 2026
d5f05dc
chore: update and trim down the frontend/CLAUDE.md file
allison-truhlar Mar 6, 2026
10ab39e
refactor: add getOmeNgffVersion, areZarrMetadataFilesPresent, and get…
allison-truhlar Mar 6, 2026
5b91435
refactor: restructure fetchZarrMetadata to check all metadata sources…
allison-truhlar Mar 6, 2026
da940a1
refactor: use real NGFF version and getEffectiveZarrStorageVersion in…
allison-truhlar Mar 6, 2026
1314821
refactor: update components for new zarr/OME-NGFF version API
allison-truhlar Mar 6, 2026
08a6691
test: update zarr version detection and metadata table tests
allison-truhlar Mar 6, 2026
45cfc05
tests: fix DataToolLinks tests
allison-truhlar Mar 6, 2026
13642a7
chore: move N5MetadataTable test to _tests_ directory
allison-truhlar Mar 6, 2026
032708a
chore: prettier formatting
allison-truhlar Mar 6, 2026
7c1c291
feat: log viewer incompatibility reasons to browser console
allison-truhlar Mar 9, 2026
5210181
chore: prettier formatting
allison-truhlar Mar 9, 2026
44821b9
docs: update viewer compatibility flow in ViewersConfiguration.md
allison-truhlar Mar 9, 2026
4b22473
Merge branch 'main' into viewers-config
allison-truhlar Mar 13, 2026
6c60026
tests, chore: set global expect timeout
allison-truhlar Mar 13, 2026
02de8bc
tests: wait for API calls to complete rather than DOM elements
allison-truhlar Mar 13, 2026
3b9373c
tests, chore: extend timeout for data link operations tests
allison-truhlar Mar 13, 2026
7b3ecbe
tests, chore: make sure DOM elements are visible before interacting w…
allison-truhlar Mar 13, 2026
e6c78f7
Merge branch 'main' into viewers-config
allison-truhlar Apr 8, 2026
a3fdadf
chore: alphabetize package.json and package-lock deps
allison-truhlar Apr 8, 2026
3c99031
fix: set neuroglancer omero_metadata to true
allison-truhlar Apr 8, 2026
0c9494a
refactor: rename vizarr.yaml to avivator.yaml
allison-truhlar Apr 8, 2026
3abd410
refactor: merge viewers config template into default config
allison-truhlar Apr 8, 2026
3c9bdc3
refactor: add gitignored custom-logos directory for viewer logos
allison-truhlar Apr 8, 2026
1c23561
chore: bump capability-manifest version
allison-truhlar Apr 14, 2026
6bf9c9d
fix: update to result.dataCompatible to match new API
allison-truhlar Apr 14, 2026
0c6effb
chore: bump capability-manifest to 0.5.0
allison-truhlar Apr 14, 2026
b9a32b3
refactor: use getLogoUrl from capability-manifest library
allison-truhlar Apr 14, 2026
f4d333f
refactor: remove local viewer logo code and assets
allison-truhlar Apr 14, 2026
36e9f05
refactor: point manifest URLs to capability-manifest repo
allison-truhlar Apr 14, 2026
1979ddf
docs: update ViewersConfiguration for capability-manifest ownership
allison-truhlar Apr 14, 2026
78eca39
docs: remove logo override from CLAUDE.md viewers config description
allison-truhlar Apr 14, 2026
100d403
fix: update DataToolLinks test mocks to match current API
allison-truhlar Apr 14, 2026
ab32fdb
fix: replace as any cast with proper OmeZarrMetadata typing
allison-truhlar Apr 14, 2026
1926883
fix: use hyphens in normalizeViewerName to avoid key collisions
allison-truhlar Apr 14, 2026
29d8782
docs: match default config example to actual viewers.config.yaml
allison-truhlar Apr 14, 2026
1e46b40
fix: add 10s timeout for manifest loading to prevent hanging
allison-truhlar Apr 14, 2026
f8d9ebb
fix: add URL validation for instance_template_url in config schema
allison-truhlar Apr 14, 2026
a6b9926
refactor: rename getCompatibleViewers to getViewersCompatibleWith
allison-truhlar Apr 14, 2026
6c49862
docs: update docs to reflect that viewer manifests are not managed by…
allison-truhlar Apr 15, 2026
2c0d7e1
chore: remove unrelated changes
allison-truhlar Apr 15, 2026
87acbe5
Merge branch 'main' into viewers-config
allison-truhlar Apr 15, 2026
7befac8
fix: update package-lock.json
allison-truhlar Apr 15, 2026
1f3b7e5
feat: add /api/viewers-config endpoint for runtime viewer configuration
allison-truhlar Apr 15, 2026
dccbcf7
refactor: load viewers config via React Query with runtime fallback
allison-truhlar Apr 15, 2026
e8f2951
docs: document runtime viewers configuration
allison-truhlar Apr 15, 2026
be00fdd
fixes: prettier formatting and using logger instead of console.error
allison-truhlar Apr 15, 2026
b441c56
fix: prettier styling
allison-truhlar Apr 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ style/tailwind_converted.css

# Configs
config.yaml
frontend/viewers.config.yaml

# Claude Code
.claude
Expand Down
17 changes: 17 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,23 @@ Key settings:
- `db_url`: Database connection string
- SSL certificates for HTTPS mode

## Viewers Configuration

Fileglancer uses a manifest-based viewer configuration system. Each viewer is defined by a **capability manifest** (a YAML file describing the viewer's name, URL template, and capabilities). The config file lists manifest URLs and optional overrides.

- **Configuration file**: `frontend/src/config/viewers.config.yaml` -- lists viewers by `manifest_url` with optional `instance_template_url` and `label` overrides
- **Manifest files**: `frontend/public/viewers/*.yaml` -- capability manifest YAML files defining each viewer's identity and supported features
- **Compatibility**: Handled by the `@bioimagetools/capability-manifest` library, which checks dataset metadata against manifest capabilities at runtime
- **Documentation**: See `docs/ViewersConfiguration.md`

To customize viewers:

1. Copy `frontend/src/config/viewers.config.yaml` to `frontend/viewers.config.yaml`
2. Edit `frontend/viewers.config.yaml` (add/remove `manifest_url` entries, override URLs or labels)
3. Rebuild application: `pixi run node-build`

`frontend/viewers.config.yaml` is gitignored so customizations do not conflict with upstream updates. When it exists, it takes precedence over the committed default at `frontend/src/config/viewers.config.yaml`. The config file is bundled at build time.

## Pixi Environments

- `default`: Standard development
Expand Down
26 changes: 21 additions & 5 deletions docs/Development.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ By default, Fileglancer provides access to each user's home directory without re

```yaml
file_share_mounts:
- "~/" # User's home directory (default)
- "~/" # User's home directory (default)
```

You can add additional file share paths by editing your `config.yaml`:

```yaml
file_share_mounts:
- "~/" # User's home directory
- "/groups/scicomp/data" # Shared data directory
- "/opt/data" # Another shared directory
- "~/" # User's home directory
- "/groups/scicomp/data" # Shared data directory
- "/opt/data" # Another shared directory
```

**How Home Directories Work:**
Expand All @@ -68,8 +68,24 @@ file_share_mounts:

Instead of using the `file_share_mounts` setting, you can configure file share paths in the database. This is useful for production deployments where you want centralized management of file share paths. To use the paths in the database, set `file_share_mounts: []`. See [fileglancer-janelia](https://github.com/JaneliaSciComp/fileglancer-janelia) for an example of populating the file share paths in the database, using a private wiki source.

### Viewers Configuration

### Testing configuration
Fileglancer supports dynamic configuration of OME-Zarr viewers through `viewers.config.yaml`. This allows you to customize which viewers are available in your deployment and configure custom viewer URLs. No configuration is required to use the default viewers defined in `frontend/src/config/viewers.config.yaml`.

**To customize viewers:**

1. Copy the default config: `cp frontend/src/config/viewers.config.yaml frontend/viewers.config.yaml`

2. Edit `frontend/viewers.config.yaml` to enable/disable viewers or customize URLs

3. Rebuild the application: `pixi run node-build` or use watch mode in development: `pixi run dev-watch`

**Note:** The configuration file is bundled at build time, so changes require rebuilding the application. `frontend/viewers.config.yaml` is gitignored so your customizations will not conflict with upstream updates. The default configuration includes Neuroglancer, Avivator, OME-Zarr Validator, and Vol-E viewers.

For detailed configuration options, examples, and documentation on adding custom viewers, see [ViewersConfiguration.md](ViewersConfiguration.md).


### Testing Configuration

Optionally, to run Playwright tests against a development deployment with OKTA authentication enabled, add the below to the configuration file.
**Note:** Do NOT add this configuration to a production deployment.
Expand Down
173 changes: 173 additions & 0 deletions docs/ViewersConfiguration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Viewers Configuration Guide

Fileglancer supports dynamic configuration of OME-Zarr viewers. This allows administrators to customize which viewers are available in their deployment, override viewer URLs, and control how compatibility is determined.

## Overview

The viewer system is built on capability manifests:

- **`viewers.config.yaml`**: Configuration file listing viewers and their manifest URLs
- **Capability manifest files**: YAML files describing each viewer's name, URL template, and capabilities
- **`@bioimagetools/capability-manifest`**: Library that loads manifests and checks dataset compatibility
- **`ViewersContext`**: React context that provides viewer information to the application

Each viewer is defined by a **capability manifest** hosted at a URL. The configuration file simply lists manifest URLs and optional overrides. At runtime, the manifests are fetched, and the `@bioimagetools/capability-manifest` library determines which viewers are compatible with a given dataset based on the manifest's declared capabilities.

## Customize Viewers

**Note:** No configuration is required to use the default viewers defined in `frontend/src/config/viewers.config.yaml`.

1. Copy the default config: `cp frontend/src/config/viewers.config.yaml frontend/viewers.config.yaml`
2. Edit `frontend/viewers.config.yaml` to customize viewers
3. Rebuild the application: `pixi run node-build`

## Runtime Configuration (System Deployments)

For deployments where Fileglancer is installed from PyPI and the frontend is pre-built, you can override the viewers configuration at runtime without rebuilding.

Set the `FGC_VIEWERS_CONFIG` environment variable (or `viewers_config` in `config.yaml`) to the absolute path of a `viewers.config.yaml` file on disk:

```env
FGC_VIEWERS_CONFIG=/opt/deploy/viewers.config.yaml
```

Or in `config.yaml`:

```yaml
viewers_config: /opt/deploy/viewers.config.yaml
```

When set, the application serves this file via the API and the frontend uses it instead of the bundled config. The file follows the same format as the build-time `viewers.config.yaml`.

### Precedence

The viewers configuration is resolved in the following order (highest priority first):

1. **Runtime API config** — served from the path in `FGC_VIEWERS_CONFIG` (no rebuild required)
2. **Build-time override** — `frontend/viewers.config.yaml` (requires rebuild)
3. **Build-time default** — `frontend/src/config/viewers.config.yaml` (requires rebuild)

## Configuration File

### Location

There are three config locations, resolved in order of precedence:

| Location | Purpose |
| -------- | ------- |
| Path in `FGC_VIEWERS_CONFIG` | **Runtime override** — served via API, no rebuild required; ideal for system deployments |
| `frontend/viewers.config.yaml` | **Build-time 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/src/config/viewers.config.yaml` 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.

**Important:** The build-time configs are bundled at build time and changes require rebuilding the application. Runtime config via `FGC_VIEWERS_CONFIG` does **not** require rebuilding.

### Structure

The configuration file has a single top-level key, `viewers`, containing a list of viewer entries. Each entry requires a `manifest_url` and supports optional overrides.

#### Viewer Entry Fields

| Field | Required | Description |
| ----------------------- | -------- | -------------------------------------------------------------------------------- |
| `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}") |

### Default Configuration

The default `viewers.config.yaml` configures four viewers:

```yaml
viewers:
- manifest_url: "https://raw.githubusercontent.com/BioImageTools/capability-manifest/host-manifests-and-docs/manifests/neuroglancer.yaml"

- manifest_url: "https://raw.githubusercontent.com/BioImageTools/capability-manifest/host-manifests-and-docs/manifests/avivator.yaml"

- manifest_url: "https://raw.githubusercontent.com/BioImageTools/capability-manifest/host-manifests-and-docs/manifests/validator.yaml"

- manifest_url: "https://raw.githubusercontent.com/BioImageTools/capability-manifest/host-manifests-and-docs/manifests/vole.yaml"
```

## Capability Manifest Files
Comment thread
allison-truhlar marked this conversation as resolved.

Manifest files describe a viewer's identity and capabilities. The default manifests are hosted in the [`@bioimagetools/capability-manifest`](https://github.com/BioImageTools/capability-manifest) repository. You can host your own manifest files anywhere accessible via URL. See the [`@bioimagetools/capability-manifest`](https://github.com/BioImageTools/capability-manifest) repository for information on how to format a viewer manifest.

## Configuration Examples

### Minimal: single viewer

```yaml
viewers:
- manifest_url: "https://raw.githubusercontent.com/BioImageTools/capability-manifest/host-manifests-and-docs/manifests/neuroglancer.yaml"
```

### Override a viewer's URL

Use `instance_template_url` to point to a custom deployment of a viewer while still using its manifest for capability matching:

```yaml
viewers:
- manifest_url: "https://raw.githubusercontent.com/BioImageTools/capability-manifest/host-manifests-and-docs/manifests/avivator.yaml"
instance_template_url: "https://my-avivator-instance.example.com/?image_url={dataLink}"

```

### Add a custom viewer

To add a new viewer, create a capability manifest YAML file, host it at a URL, and reference it in the config:

1. Create a manifest file (e.g., `my-viewer.yaml`). Follow the format guidelines in the [`@bioimagetools/capability-manifest`](https://github.com/BioImageTools/capability-manifest) repository.

2. Host the manifest at an accessible URL (e.g., on GitHub or any web server).

3. Reference it in `viewers.config.yaml`:

```yaml
viewers:
- manifest_url: "https://example.com/manifests/my-viewer.yaml"
label: "Open in My Viewer"
```

## How Compatibility Works

The `@bioimagetools/capability-manifest` library handles all compatibility checking. When a user views an OME-Zarr dataset:

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.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

See BioImageTools/capability-manifest@0594032#diff-a54261af011358e447a9f3ef717ee8e5d5bb4258f8d95e246b39cf3666244f1f. For now, ome_zarr_versions and compression_codecs are the only two that result in dataCompatible = false, and therefore the viewer isn't shown. Otherwise, a warning is logged to the console.

I wasn't sure how to implement the check for rfcs_supported. Would I create an image metadata check to correspond to each RFC? For example, RFC 2 => check if the image is Zarr version 3. If so, then supporting this RFC is required to display the viewer.

4. Incompatibility reasons (e.g., "Viewer does not support OME-Zarr v3") are logged to the browser console for debugging

This replaces the previous system where `valid_ome_zarr_versions` was a global config setting and custom viewers used simple version matching. Now all compatibility logic is driven by the detailed capabilities declared in each viewer's manifest.

## Viewer Logos

Viewer logos are managed by the `@bioimagetools/capability-manifest` library. Logo resolution follows this order:

1. **Override**: If the manifest includes a `viewer.logo` field, that URL is used directly
2. **Convention-based**: Otherwise, the logo URL is derived from the viewer name (lowercased, spaces replaced with hyphens, e.g. "OME-Zarr Validator" → `ome-zarr-validator.png`) and hosted alongside the manifests
3. **Fallback**: If the logo fails to load at runtime, a bundled fallback image is shown

## Development

When developing with custom configurations:

1. Copy the default config: `cp frontend/src/config/viewers.config.yaml frontend/viewers.config.yaml`
2. Edit `frontend/viewers.config.yaml`
3. Rebuild frontend: `pixi run node-build` or use watch mode: `pixi run dev-watch`
4. Check the browser console for viewer initialization messages

### Validation

The configuration is validated at build time using Zod schemas (see `frontend/src/config/viewersConfig.ts`). Validation enforces:

- The `viewers` array must contain at least one entry
- Each entry must have a valid `manifest_url` (a properly formed URL)
- Optional fields (`instance_template_url`, `label`) must be strings if present

At runtime, manifests that fail to load are skipped with a warning. If a viewer has no `template_url` (neither from its manifest nor from `instance_template_url` in the config), it is also skipped.

## Copy URL Tool

The "Copy data URL" tool is always available when a data URL exists, regardless of viewer configuration.
16 changes: 16 additions & 0 deletions fileglancer/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,22 @@ async def version_endpoint():
return {"version": APP_VERSION}


@app.get("/api/viewers-config", include_in_schema=False)
async def get_viewers_config():
if not settings.viewers_config:
raise HTTPException(status_code=404, detail="No viewers configuration")

config_path = PathLib(settings.viewers_config)
if not config_path.exists() or not config_path.is_file():
logger.warning(f"Viewers config file not found: {settings.viewers_config}")
raise HTTPException(status_code=404, detail="Viewers configuration file not found")

return PlainTextResponse(
content=config_path.read_text(encoding="utf-8"),
media_type="text/yaml"
)


# Authentication routes
@app.get("/api/auth/login", include_in_schema=settings.enable_okta_auth,
description="Initiate OKTA OAuth login flow")
Expand Down
5 changes: 5 additions & 0 deletions fileglancer/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ class Settings(BaseSettings):
# Username used when creating a session via the test-login endpoint.
test_login_username: str = "jacs"

# Optional path to a viewers configuration YAML file.
# When set, the file is served at GET /api/viewers-config, allowing
# runtime customization of OME-Zarr viewers without rebuilding the frontend.
viewers_config: Optional[str] = None

model_config = SettingsConfigDict(
yaml_file="config.yaml",
env_file='.env',
Expand Down
Loading
Loading