# Lightify Native Shell Parity Plan

> Goal: replace the Tauri/WebView2 shell with a Windows-first native Rust shell
> that preserves the current Lightify UI and feature set, uses devtools/live
> capture as the parity harness, and targets total idle memory under 75 MB.

---

## §0 — Framing

The current Tauri frontend is already close to the visual and interaction target.
That matters because it changes the job from design to reproduction.

The key constraint is not app-level WebGL. The current frontend appears to be a
DOM/CSS interface with ordinary HTML, SVG, and light transitions. The memory
cost comes from the WebView2 process tree itself. Stripping WebGL from the page
does not solve that. Removing the browser engine does.

So the plan is:

1. Freeze the existing Tauri app as the reference UI.
2. Capture every visible state and interaction with devtools/live inspection.
3. Rebuild that exact product surface in a native Rust shell.
4. Keep the existing Rust backend and `lightify-audio` process wherever
   possible.

Devtools/live capture is useful here as a measurement and parity tool, not as a
shipping implementation strategy.

---

## §1 — Budget contract

Primary target:

| Metric | Target | Gate |
| --- | --- | --- |
| Total idle RSS | **< 75 MB** | Block if `>= 90 MB` |
| Shell idle RSS | **as low as possible** | Investigate if `>= 30 MB` |
| Idle GPU usage | **effectively 0 %** | Block on continuous redraw |
| Browser runtime processes | **0** | Block if any WebView2/browser child survives |
| Feature scope | **Exact current parity** | Do not cut features to hit budget |

Secondary goal after parity:

- Profile for a further drop below 60 MB total if the shell lands cleanly and
  `lightify-audio` still leaves enough headroom.

Important constraint:

- Prior repo notes measured `lightify-audio` at roughly 41 MB on its own, so a
  `< 75 MB` target is realistic enough to pursue without pretending the shell
  cost can be zero.

---

## §2 — Why live capture matters now

Live capture is valuable now because the layout, theme, and interaction model
are mostly settled. That gives us a stable reference to reproduce.

Use it to record:

1. Window dimensions and responsive breakpoints.
2. Exact spacing, padding, borders, panel widths, and alignment.
3. Typography, colors, icon sizes, and selected/hover/disabled states.
4. Scroll behavior, paging thresholds, and list density.
5. Context menu behavior, overlays, focus movement, and error states.

Do not confuse that with a browser-to-native conversion shortcut. The capture
ledger removes visual guesswork. It does not remove the need to reimplement the
shell.

---

## §3 — Reference surfaces to capture

The current parity source is the Tauri frontend in:

- `lightify-tauri/src/index.html`
- `lightify-tauri/src/styles.css`
- `lightify-tauri/src/app.js`

Capture every user-facing state for these surfaces:

1. Auth page.
2. Custom title bar and status bar.
3. Library tab: playlist list, track list, sort states, back navigation.
4. Search tab: filters, results, drill-down, empty/loading/error states.
5. Beatport tab: genre picker, results, selection, create-playlist flow.
6. Now playing: artwork, title, artist, progress, elapsed/duration.
7. Playback controls: play/pause, prev/next, shuffle, repeat, volume.
8. Extras: like, station, add-to-queue.
9. Sidebar surfaces: queue, recent, downloads.
10. Settings modal: devices, native audio status, watchdog, audio output.
11. Context menus, row selection, hover states, double-click behavior.
12. Tray/minimize/maximize/close window behavior.

This becomes the parity ledger and the acceptance reference for the native
shell.

---

## §4 — Runtime decision

Chosen direction: **Windows-first native Rust shell**.

Why this direction:

1. Tauri cannot keep its webview and also eliminate WebView2 overhead.
2. The older PySide path removes WebView2 but still misses the lightweight
   target by a wide margin.
3. The existing backend logic and audio engine are already in Rust, so a native
   Rust shell is the shortest route to a browser-free final architecture.

Preferred implementation order:

1. Raw Win32 or a minimal `winit`-based custom shell for the smallest memory
   budget.
2. Only consider a heavier GUI toolkit if the shell work becomes the blocking
   risk, and only after measuring its memory cost.

Non-goals:

- Do not switch to another embedded browser host.
- Do not keep Tauri in the shipping artifact.
- Do not cut existing features just to claim a memory win.

---

## §5 — What gets reused vs replaced

Keep and reuse:

1. `lightify-audio/src/main.rs` — native Spotify Connect audio engine.
2. Core host/backend logic in `lightify-tauri/src-tauri/src/main.rs`.
3. Existing auth, token refresh, Spotify API wiring, device selection,
   Beatport logic, downloads/watchdog logic, and binary discovery.
4. Existing visual language from `index.html` and `styles.css`.

Replace:

1. Tauri window shell.
2. WebView2 renderer.
3. DOM mutation/rendering code in `app.js`.
4. Tauri JS event bridge for UI updates.

Refactor before porting:

1. Lift shell-neutral state and command logic out of `app.js`.
2. Convert DOM-driven flows into explicit state transitions and view models.
3. Preserve behavior, not browser-specific implementation details.

---

## §6 — Migration phases

### Phase 0 — Baseline and measurement

Deliverables:

1. Record the current deployed process tree for Lightify, `lightify-audio`, and
   all WebView2 children.
2. Record idle RSS for each process and total idle RSS.
3. Record the active artifact paths so tests never hit the wrong binary.
4. Freeze the parity ledger from live capture.

Exit condition:

- We have a measured baseline and a complete capture list for the current UI.

### Phase 1 — Freeze the backend contract

Deliverables:

1. Inventory every Tauri command and event currently used by the frontend.
2. Separate shell-specific code from product logic in the Rust host.
3. Define the native shell API boundary for playback, library, search,
   Beatport, downloads, settings, and watchdog features.

Exit condition:

- The backend contract is explicit enough that a native shell can bind to it
  without depending on a webview.

### Phase 2 — Build the native shell foundation

Deliverables:

1. Create a new native Rust shell crate.
2. Implement window creation, custom chrome, layout regions, text rendering,
   input handling, scroll handling, context menus, and image presentation.
3. Bind the shell directly to the reused Rust backend and the existing
   `lightify-audio` subprocess protocol.

Exit condition:

- The native shell window exists, launches without WebView2, and can render a
  static Lightify frame.

### Phase 3 — Port the UI in vertical slices

Port in this order:

1. Shell chrome, auth page, status bar, now playing, transport, volume.
2. Library and search, including list paging, selection, drill-down, and
   context menus.
3. Beatport, queue, recent, downloads, settings, watchdog, tray behavior, and
   remaining overlays.

Rule:

- Do not move to the next slice until the current one matches the capture ledger
  closely enough to be mechanically comparable.

Exit condition:

- Every current Tauri surface exists in the native shell.

### Phase 4 — Hardening and memory work

Deliverables:

1. Remove any timer-driven redraws when the UI is static.
2. Keep caching minimal and visible-surface-driven.
3. Measure shell RSS after each slice.
4. If total RSS still misses target after the shell is lean, profile
   `lightify-audio` next rather than pretending the shell is the only problem.

Exit condition:

- Native shell plus `lightify-audio` meets the agreed budget and behaves like
  the captured Tauri reference.

---

## §7 — Verification discipline

Every milestone must be verified with executable evidence, not assumption.

Required checks:

1. Side-by-side parity checks against the capture ledger.
2. Process-tree inspection proving no WebView2/browser runtime is active.
3. Idle RSS measurement for shell, audio process, and total.
4. Idle GPU check proving no repaint loop.
5. Feature smoke tests covering:
   - auth
   - playback
   - seek
   - volume
   - device switching
   - library navigation
   - search drill-down
   - Beatport fetch/create
   - queue/recent/downloads
   - settings/watchdog
   - tray/window controls

---

## §8 — Risks and reality checks

1. Exact parity is compatible with this plan, but it is not a shortcut. The
   shell still has to be rebuilt.
2. `< 75 MB` is a real target. `< 50 MB` was likely too aggressive for a first
   full-parity milestone given the current audio-process floor.
3. If the native shell lands near target but misses it, the next place to look
   is `lightify-audio`, not a second round of browser-shell experimentation.
4. Devtools/live capture should stay in the loop throughout the migration,
   because it turns visual parity from opinion into a measurable acceptance
   test.

---

## §9 — Immediate next moves

1. Build the capture ledger from the current Tauri UI.
2. Enumerate the exact frontend-to-backend command/event surface.
3. Create the native shell crate and prove a browser-free window with custom
   chrome.
4. Port the first slice: auth, shell chrome, now playing, and transport.
