TIFF Viewer (react-tiff) Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.
Goal: Add native TIFF viewing to the TiffViewerPage using react-tiff, shown when server-side PNG conversion hasn’t run yet (conversionStatus === 'none' or 'failed').
Architecture: react-tiff and its entire CJS dependency tree (utif, react-i18next, i18next, axios) are isolated in a dedicated vendor-tiff Rollup manualChunk and excluded from Vite pre-bundling. TiffViewerPage stays lazy-imported in App.tsx so vendor-tiff never touches the eager boot path. The existing PNG preview path (conversionStatus === 'done') is unchanged.
Tech Stack: react-tiff 0.0.17, Vite 6 manualChunks, React lazy/Suspense
Task 1: Install react-tiff
Files:-
Modify:
ui/package.json(dependency added by pnpm) -
Modify:
pnpm-lock.yaml(updated by pnpm) - Step 1: Install the package
+ react-tiff 0.0.17 (or similar) with no errors.
- Step 2: Verify the dependency tree installed correctly
Task 2: Isolate react-tiff in its own Rollup chunk
Files:-
Modify:
ui/vite.config.ts -
Step 1: Add
vendor-tiffto manualChunks and exclude deps from pre-bundling
ui/vite.config.ts. Make two edits:
Edit 1 — add exclude to optimizeDeps (currently only has include):
vendor-tiff line inside manualChunks, after the existing vendor-three line:
- Step 2: Verify the config change looks correct
exclude array contains all four packages; vendor-tiff line is present in manualChunks.
Task 3: Revert TiffViewerPage to lazy import in App.tsx
Files:- Modify:
ui/src/App.tsxline ~45
- Step 1: Change the import back to lazy
ui/src/App.tsx:
- Step 2: Verify the change
const TiffViewerPage = lazy(() => import('./pages/TiffViewerPage')); — NOT a bare import.
Task 4: Update TiffViewerPage to use TIFFViewer for raw TIFF files
Files:- Modify:
ui/src/pages/TiffViewerPage.tsx
conversionStatus === 'done'→ download PNG blob →<img>conversionStatus === 'pending'→ spinner + messageconversionStatus === 'failed'→ error screen (dead end)conversionStatus === 'none'→ downloads raw TIFF blob but renders with<img>(broken in Chrome/Firefox)
-
'done'→ unchanged (PNG<img>) -
'pending'→ unchanged (spinner) -
'none'or'failed'→ download raw TIFF blob → blob URL →<TIFFViewer> - Step 1: Rewrite TiffViewerPage.tsx
ui/src/pages/TiffViewerPage.tsx with:
- Step 2: Check TypeScript compiles cleanly
react-tiff has no bundled types, the error will be Could not find a declaration file for module 'react-tiff' — add // @ts-ignore above the import and continue.
Task 5: Build and verify no TDZ crash
- Step 1: Run the production build
vendor-tiff chunk visible in the output. No errors.
- Step 2: Confirm vendor-tiff chunk exists in dist
- Step 3: Start preview and check for TDZ crash
http://localhost:4173/ and check for console errors. Zero errors = success.
Expected console errors: 0. If there’s a Cannot set properties of undefined (setting 'Activity') or Cannot read createContext error, the vendor-tiff chunk isolation isn’t working — stop and diagnose before continuing.
Task 6: Commit and deploy
- Step 1: Stage all changes
- Step 2: Append release notes to RELEASES.md
RELEASES.md (before existing entries):
- Step 3: Commit
- Step 4: Build and deploy to Cloudflare Pages
- Step 5: Force-promote canonical deployment
- Step 6: Verify all domains serve the new build

