> For the complete documentation index, see [llms.txt](https://docs.wellcomecollection.org/request-for-comments-rfcs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.wellcomecollection.org/request-for-comments-rfcs/086-item-viewer-refactor/01-overview.md).

# Overview

[← Back to Index](/request-for-comments-rfcs/086-item-viewer-refactor.md)

## Problem Statement

The IIIF Viewer component tree has significant duplication of logic and calculations across multiple components. Values like `currentCanvas`, download options, image services, and derived state are computed independently in different files, leading to:

* Code duplication (\~60% of calculations repeated)
* Harder maintenance (changes needed in multiple places)
* Potential inconsistencies between components
* Missed optimisation opportunities (no memoisation)
* Verbose component code

## Current Architecture

### ItemViewerContext (Already Exists)

**Location:** `content/webapp/contexts/ItemViewerContext/index.tsx`

Currently provides:

* UI state (sidebar visibility, zoom, grid, fullscreen)
* Basic data (work, transformedManifest, query params)
* Refs (viewerRef, mainAreaRef)
* Missing: Derived/computed values used across components

### Components with Duplication

| Component           | Duplicated Logic                                                                                                        |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `IIIFViewer.tsx`    | `currentCanvas`, `canvasIndexById`, `hasOnlyRenderableImages`, `hasMultipleCanvases`, `mainImageService`, `urlTemplate` |
| `ViewerTopBar.tsx`  | `currentCanvas`, `imageServices` extraction, download options (50+ lines), `isRestricted`                               |
| `ZoomedImage.tsx`   | `currentCanvas`, `mainImageService`                                                                                     |
| `MainViewer.tsx`    | `currentCanvas` access, rotation calculations                                                                           |
| `Thumbnails.tsx`    | `queryParamToArrayIndex` calls                                                                                          |
| `NoScriptImage.tsx` | `queryParamToArrayIndex` calls                                                                                          |

### Specific Duplication Examples

**`currentCanvas` - calculated in 4+ files:**

```typescript
// IIIFViewer.tsx line 257
const currentCanvas = transformedManifest?.canvases[queryParamToArrayIndex(canvas)];

// ViewerTopBar.tsx line 224  
const currentCanvas = canvases?.[queryParamToArrayIndex(query.canvas)];

// ZoomedImage.tsx line 55-56
const currentCanvas = transformedManifest?.canvases[queryParamToArrayIndex(query.canvas)];
```

**Download options logic - only in `ViewerTopBar.tsx` (lines 245-291):**

* Calculate `iiifImageDownloadOptions`
* Extract `canvasImageDownloads` from `imageServices`
* Get `canvasDownloadOptions` from current canvas
* Get `manifestDownloadOptions` from rendering
* Get `videoAudioDownloadOptions`
* Combine all options
* Deduplicate by download URL (added in `restricted-images` merge)

**Note:** Download logic is only in one file, but it's \~65 lines of complex business logic (now \~80 with deduplication). **This will go into a custom hook** (not context) for testability and potential reuse.

**Image services extraction - `ViewerTopBar.tsx` (lines 226-238):** Complex mapping with `ChoiceBody` handling, only done once but could be reusable.

## What Goes Where?

### Context (`ItemViewerContextV2`)

**Use for:** Values needed by **2+ components** OR likely to be needed by multiple components soon.

Moving to context:

* `currentCanvas` - used in 4 files
* `currentCanvasIndex` - used in 3+ files
* `mainImageService` - used in 2 files
* `hasMultipleCanvases` - affects layout across components
* Navigation booleans - used by navigation UI across components
* `isCurrentCanvasRestricted` - only in `ViewerTopBar` now, but likely needed for download restrictions, visibility rules, etc.

### Custom Hook

**Use for:** Complex logic that's **reusable or needs testing**, even if only used in one place.

Moving to hook:

* Download options logic - 65 lines, complex business logic, only in `ViewerTopBar` but worth extracting for testability

### Local Component State

**Use for:** Simple logic only used in **one component** with no reuse potential.

Staying local:

* Component-specific UI state
* Simple calculations not shared
* One-off transformations

***

**Next:** [02 - Normalisation Strategy](/request-for-comments-rfcs/086-item-viewer-refactor/02-normalisation-strategy.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.wellcomecollection.org/request-for-comments-rfcs/086-item-viewer-refactor/01-overview.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
