# Phase 10 — Polish + Delete Legacy Design > Companion to the parent plan: `docs/superpowers/plans/2026-06-05-react-ui-redesign.md` (Phase 10 is sketched at high level; this spec locks architecture, file map, deletion targets, and version strategy.) **Date:** 2026-06-06 **Phase:** 10 of 10 (React + shadcn/ui UI redesign) — **FINAL** **Tag (on completion):** `v5.0.0` (the first release tag, all prior phases were `phase-N-*` working tags) --- ## 1. Goal & Non-Goals **Goal:** Finalize the React UI redesign. Decompose the legacy 146KB `src/main.js` into a feature-first modular structure under `src/main/`, remove the legacy vanilla-JS renderer and all dead IPC bridges, then ship **v5.0.0** with a CHANGELOG. **Non-goals (Phase 10):** - Adding new features (Phases 1-9 shipped all of them) - A full main-process test suite (the existing main process is largely untested; adding tests is Phase 11+) - Backwards compat shims for the legacy renderer - Renderer-side refactor (already done) - Migrating the renderer build pipeline further (vite configs are in place) **Success criteria:** - `src/main.js` is gone; `src/main/index.js` is the new entrypoint - `package.json#main` points to `src/main/index.js` - All 12 legacy renderer files are deleted - All 9 dead IPC channels are removed from `preload.js` and `main.js` - `src/index.html` is reduced to ~50 lines (just the Vite bootstrap) - `package.json#version` is `5.0.0` - `CHANGELOG.md` exists in Keep a Changelog 1.1.0 format - `git grep -E "renderer\.js|command-palette|print-preview|welcome\.js|zen-mode|wordTemplate|ascii-generator|table-generator|styles\.css"` returns zero results - All 305 tests still pass - `npx vite build --config vite.renderer.config.ts` succeeds - `npx electron .` launches and main window renders - Tag `v5.0.0` pushed to origin --- ## 2. Target Architecture ### 2.1 `src/main/` (feature-first decomposition) ``` src/main/ ├── index.js # entrypoint: bootstraps store, app, window, ipc ├── store.js # electron-store wrapper (preferences + wordTemplatePath) ├── ipc.js # ipcMain.handle registration (composes from modules) ├── files/ │ ├── index.js # file ops facade (read/write/list/pickFolder/pickFile) │ ├── search.js # recursive regex search (used by find-in-files) │ ├── git.js # git status porcelain parser │ └── binary.js # writeBuffer helper (Uint8Array → file) ├── menu/ │ ├── index.js # buildMenu() — composes the app menu │ └── items.js # individual menu items (File, Edit, View, etc.) ├── window/ │ ├── index.js # createMainWindow ONLY (createAsciiWindow/createTableWindow are DEAD) │ └── state.js # window state persistence ├── word-template/ │ ├── index.js # WordTemplateExporter facade │ ├── parser.js # .dotx parsing │ ├── converter.js # markdown → docx │ └── apply.js # apply template styles to converted docx └── utils/ ├── paths.js # path helpers ├── logger.js # structured logging └── download.js # tool downloader ``` **Module rules:** - Each file has one clear responsibility (no god files; CLAUDE.md says >300 lines is the cap) - `index.js` is the public face of a folder; deeper files are private - `src/main/index.js` (top-level) wires everything together - Cross-folder imports go through `index.js`, not directly to internals ### 2.2 Entry point change **Before:** ```json // package.json "main": "src/main.js" ``` **After:** ```json // package.json "main": "src/main/index.js" ``` The new `src/main/index.js` runs the same `app.whenReady().then(...)` flow that the current `src/main.js` does, but composes the decomposed modules. ### 2.3 What becomes dead code (removed during decomposition) When the legacy renderer files are deleted, these main-process functions become orphaned and are removed too: | Function | File | Why dead | |---|---|---| | `createAsciiWindow()` | `src/main/window/index.js` | Loads deleted `src/ascii-generator.html` | | `createTableWindow()` | `src/main/window/index.js` | Loads deleted `src/table-generator.html` | | `ipcMain.on('open-ascii-generator', ...)` | `src/main/index.js` (after decomposition) | Replaced by React `` | | `ipcMain.on('open-table-generator', ...)` | `src/main/index.js` (after decomposition) | Replaced by React `` | | `webContents.send('print-preview')` | `src/main/menu/items.js` | Replaced by React `` | | `webContents.send('print-preview-styled')` | `src/main/menu/items.js` | Replaced by React `` | | `webContents.send('toggle-command-palette')` | `src/main/menu/items.js` | Replaced by `useCommandStore` | | `require('./wordTemplateExporter')` | `src/main/index.js` (after decomposition) | Replaced by `src/main/word-template/` + renderer-side `lib/docx-export.ts` | --- ## 3. Legacy Deletion Map ### 3.1 Files to delete from `src/` (12 files, ~14,426 lines) | File | Size | Lines | Replaced by | |---|---|---|---| | `src/renderer.js` | 213KB | 5319 | `src/renderer/` (Phases 1-9) | | `src/styles.css` | 74KB | 3723 | `src/renderer/index.css` + Tailwind | | `src/styles-modern.css` | 71KB | 2625 | Tailwind + shadcn/ui | | `src/styles-concreteinfo.css` | 21KB | 969 | Tailwind theme tokens | | `src/styles-sidebar.css` | 9.7KB | 304 | `` component | | `src/styles-zen.css` | 2.1KB | 102 | Zen mode in AppShell | | `src/styles-welcome.css` | 2.2KB | 24 | Welcome dialog | | `src/fonts.css` | 1.8KB | (imported elsewhere) | Tailwind font config | | `src/command-palette.js` | (small) | 109 | `useCommandStore` | | `src/print-preview.js` | (small) | 138 | `` | | `src/welcome.js` | (small) | 78 | `` modal | | `src/zen-mode.js` | (small) | 292 | `use-zen-mode` hook + AppShell | | `src/wordTemplateExporter.js` | (small) | 743 | `src/main/word-template/` + renderer `lib/docx-export.ts` | | `src/ascii-generator.html` | 34KB | (HTML) | `` | | `src/table-generator.html` | 18KB | (HTML) | `` | **Total: 12 JS/CSS/HTML files = 14,426 lines / ~445KB** Note: `src/index.html` is **NOT** deleted — it's rewritten to a minimal Vite bootstrap (~50 lines). See §4. ### 3.2 Dead IPC channels to remove from `src/preload.js` - `toggle-command-palette` (line 238) - `open-ascii-generator` (line 89) - `open-table-generator` (line 92) - `print-preview` (line 173) - `print-preview-styled` (line 174) - `show-table-generator` (line 180) - `show-ascii-generator-window` (line 217) - `show-ascii-generator` (line 218) - `show-table-generator-window` (line 221) And from the exposed API surface: - `openAscii: () => ipcRenderer.send('open-ascii-generator')` (line 445) - `openTable: () => ipcRenderer.send('open-table-generator')` (line 446) **9 channel names + 2 API entries to remove.** ### 3.3 Legacy references in `src/index.html` (16 places) - `` (line ~6) - `` (line ~7) - `