Problem
src/app/debug/office-wasm-poc has grown into a single debug surface that eagerly wires DOCX, XLSX, and PPTX preview logic together. This makes the office preview stack harder to evolve: format-specific work leaks into shared utilities, renderer files keep growing, and adding new fidelity work now increases coupling instead of improving reuse.
Walnut shows a cleaner modular shape for the same problem space: format-scoped preview panels, separately loaded protocol/model bundles, and a narrow shell that only decides which surface to mount.
Context
- Current behavior:
page-client.tsx statically imports WordPreview, SpreadsheetPreview, and PresentationPreview, so the debug entry owns all three preview surfaces at once.
- Dynamic imports are currently used mainly for decoder/runtime loading, not for preview UI boundaries.
- Shared code is concentrated in
office-preview-utils.ts (795 lines) and consumed across document, spreadsheet, and presentation flows.
- Several files are already acting as subsystem roots rather than focused modules:
word-preview.tsx (1634 lines)
spreadsheet-preview.tsx (1594 lines)
spreadsheet-charts.tsx (1569 lines)
spreadsheet-conditional-formula.ts (1423 lines)
presentation-renderer.ts (1356 lines)
spreadsheet-conditional-visuals.ts (1209 lines)
- The current preview layer still leans heavily on
Record<string, unknown> / unknown traversal, which weakens format boundaries and makes shared-vs-format ownership fuzzy.
- Desired behavior:
- Keep a thin office preview shell that selects artifact kind and reader mode.
- Split UI and rendering by format (
document, spreadsheet, presentation) with lazy boundaries.
- Extract explicit shared layers for protocol adapters, rendering primitives, and common UI/utilities.
- Make
office-wasm-poc a composition harness rather than the place where all office behavior lives.
Related History
- Local analysis found after searching
docs/issues/:
docs/issues/2026-05-01-office-document-viewer-wasm-reader.md
docs/issues/2026-05-05-office-wasm-docx-feature-checklist.md
docs/issues/2026-05-05-office-wasm-xlsx-feature-checklist.md
docs/issues/2026-05-05-office-wasm-pptx-feature-checklist.md
- Walnut modularization evidence from
tmp/codex-app-analysis:
- separate bundles for protocol/model layers:
proto-*.js, workbook-*.js, presentation-*.js
- separate format bundles:
document-*.js, spreadsheet-*.js, presentation-*.js
- separate preview/panel bundles such as
docx-preview-panel-*.js, which lazily imports docx-preview-*.js
- Related GitHub issue history: none found after searching repository issues for
office wasm, Walnut, office preview, and office document viewer.
Related PR File Context
None found. The repository search did not return a related GitHub issue with linked pull requests for this refactor theme, so there is no prior PR diff context to summarize.
Proposed Approaches
Approach 1: In-place folderized refactor inside office-wasm-poc
Restructure the current debug surface into explicit subtrees such as:
office-wasm-poc/shell/*
office-wasm-poc/shared/*
office-wasm-poc/document/*
office-wasm-poc/spreadsheet/*
office-wasm-poc/presentation/*
Add lazy loading at the preview-panel boundary so the selected artifact kind loads its own UI/rendering subtree.
Pros:
- Lowest migration risk
- Preserves the current debug route and tests
- Makes ownership boundaries visible immediately
Cons:
- Still leaves the long-term architecture inside a debug-only path
- Shared abstractions may remain too local to
office-wasm-poc
- Risk of stopping halfway after file moves without stabilizing shared contracts
Estimated effort: Medium
Approach 2: Extract a reusable office preview module outside the debug route
Move stable shared behavior into a reusable package/module (for example under src/client/office-document-viewer/), leaving office-wasm-poc as a harness that mounts the shared office preview system.
Pros:
- Best alignment with production reuse
- Clarifies the difference between protocol/model logic and debug/demo scaffolding
- Reduces the chance that future office work lands in the debug route by default
Cons:
- Larger migration and review surface
- Requires API design for cross-format shared contracts up front
- More likely to touch app/runtime boundaries during the refactor
Estimated effort: Large
Approach 3: Hybrid staged refactor (format shells first, extraction second)
Stage 1:
- introduce format-scoped entry modules and lazy preview loading
- split
office-preview-utils.ts into targeted shared modules
- move renderer/domain code under format folders
- keep
office-wasm-poc as the host surface
Stage 2:
- promote stable shared contracts and render primitives into reusable
office-document-viewer modules
- keep the debug route as a thin harness over the extracted system
Pros:
- Captures Walnut's modular benefits quickly
- Limits risk while creating a clear path toward production reuse
- Lets tests and characterization checks move with each format incrementally
Cons:
- Needs discipline to ensure Stage 2 actually happens
- Temporary duplication may exist during the transition
- Requires explicit boundary rules to avoid recreating another shared dumping ground
Estimated effort: Large
Recommendation
Start with Approach 3 (Hybrid staged refactor).
It matches the immediate problem best: the current pain is boundary collapse inside office-wasm-poc, but a full extraction in one step is likely too broad. A staged path lets us first enforce Walnut-like modular seams — format panels, lazy UI boundaries, isolated renderers, and explicit shared primitives — then lift the stable pieces into reusable viewer modules once those seams are proven.
The first stage should preserve these design constraints:
page-client.tsx becomes a thin shell and stops statically owning all preview implementations.
- Format-specific UI/rendering code lives under format folders with clear ownership.
- Shared code is split by concern (
protocol, rendering primitives, common hooks/utils, shared UI) rather than by convenience.
- Spreadsheet worker/canvas infrastructure remains isolated to spreadsheet modules instead of leaking into generic utilities.
- Characterization tests move with the modules so refactoring does not silently change preview behavior.
Out of Scope
- Adding new DOCX/XLSX/PPTX feature fidelity during the refactor unless directly required to preserve behavior
- Replacing the Walnut/Routa WASM reader protocol itself
- Converging the entire office viewer into a final production package in one step
- Redesigning the end-user office viewing UX outside the current debug/refactor scope
Labels
enhancement, refactor, area:frontend, ui, complexity:large
Problem
src/app/debug/office-wasm-pochas grown into a single debug surface that eagerly wires DOCX, XLSX, and PPTX preview logic together. This makes the office preview stack harder to evolve: format-specific work leaks into shared utilities, renderer files keep growing, and adding new fidelity work now increases coupling instead of improving reuse.Walnut shows a cleaner modular shape for the same problem space: format-scoped preview panels, separately loaded protocol/model bundles, and a narrow shell that only decides which surface to mount.
Context
page-client.tsxstatically importsWordPreview,SpreadsheetPreview, andPresentationPreview, so the debug entry owns all three preview surfaces at once.office-preview-utils.ts(795 lines) and consumed across document, spreadsheet, and presentation flows.word-preview.tsx(1634 lines)spreadsheet-preview.tsx(1594 lines)spreadsheet-charts.tsx(1569 lines)spreadsheet-conditional-formula.ts(1423 lines)presentation-renderer.ts(1356 lines)spreadsheet-conditional-visuals.ts(1209 lines)Record<string, unknown>/unknowntraversal, which weakens format boundaries and makes shared-vs-format ownership fuzzy.document,spreadsheet,presentation) with lazy boundaries.office-wasm-poca composition harness rather than the place where all office behavior lives.Related History
docs/issues/:docs/issues/2026-05-01-office-document-viewer-wasm-reader.mddocs/issues/2026-05-05-office-wasm-docx-feature-checklist.mddocs/issues/2026-05-05-office-wasm-xlsx-feature-checklist.mddocs/issues/2026-05-05-office-wasm-pptx-feature-checklist.mdtmp/codex-app-analysis:proto-*.js,workbook-*.js,presentation-*.jsdocument-*.js,spreadsheet-*.js,presentation-*.jsdocx-preview-panel-*.js, which lazily importsdocx-preview-*.jsoffice wasm,Walnut,office preview, andoffice document viewer.Related PR File Context
None found. The repository search did not return a related GitHub issue with linked pull requests for this refactor theme, so there is no prior PR diff context to summarize.
Proposed Approaches
Approach 1: In-place folderized refactor inside
office-wasm-pocRestructure the current debug surface into explicit subtrees such as:
office-wasm-poc/shell/*office-wasm-poc/shared/*office-wasm-poc/document/*office-wasm-poc/spreadsheet/*office-wasm-poc/presentation/*Add lazy loading at the preview-panel boundary so the selected artifact kind loads its own UI/rendering subtree.
Pros:
Cons:
office-wasm-pocEstimated effort: Medium
Approach 2: Extract a reusable office preview module outside the debug route
Move stable shared behavior into a reusable package/module (for example under
src/client/office-document-viewer/), leavingoffice-wasm-pocas a harness that mounts the shared office preview system.Pros:
Cons:
Estimated effort: Large
Approach 3: Hybrid staged refactor (format shells first, extraction second)
Stage 1:
office-preview-utils.tsinto targeted shared modulesoffice-wasm-pocas the host surfaceStage 2:
office-document-viewermodulesPros:
Cons:
Estimated effort: Large
Recommendation
Start with Approach 3 (Hybrid staged refactor).
It matches the immediate problem best: the current pain is boundary collapse inside
office-wasm-poc, but a full extraction in one step is likely too broad. A staged path lets us first enforce Walnut-like modular seams — format panels, lazy UI boundaries, isolated renderers, and explicit shared primitives — then lift the stable pieces into reusable viewer modules once those seams are proven.The first stage should preserve these design constraints:
page-client.tsxbecomes a thin shell and stops statically owning all preview implementations.protocol,rendering primitives,common hooks/utils,shared UI) rather than by convenience.Out of Scope
Labels
enhancement,refactor,area:frontend,ui,complexity:large