diff --git a/.planning/phases/29-context-optimization/29-RESEARCH.md b/.planning/phases/29-context-optimization/29-RESEARCH.md
new file mode 100644
index 000000000..c7c1f5b97
--- /dev/null
+++ b/.planning/phases/29-context-optimization/29-RESEARCH.md
@@ -0,0 +1,496 @@
+# Phase 29: Context Optimization - Research
+
+**Researched:** 2026-03-05
+**Domain:** React context performance optimization
+**Confidence:** HIGH
+
+## Summary
+
+Phase 29 addresses unnecessary re-renders caused by unmemoized context provider values in MixersContext and the coupling of high-frequency VU updates with low-frequency mixer configuration updates. Phase 28 successfully extracted VU data into an external store, but MixersContext still creates a new value object on every render (line 10 of MixersContext.js), triggering cascading re-renders in all consumer components even when the underlying data hasn't changed.
+
+The solution involves three complementary strategies:
+1. **Memoize context provider values** - Use `useMemo` to prevent new object creation on every render
+2. **Split contexts by update frequency** - Separate VuContext (already simplified in Phase 28) from MixersContext configuration
+3. **Optimize context consumers** - Use `React.memo` and selector patterns to minimize re-render scope
+
+This phase builds directly on Phase 28's work. VuContext was already simplified to provide vuStore reference; now MixersContext needs similar optimization for mixer configuration data (volume, pan, mute state, etc.).
+
+**Primary recommendation:** Wrap the MixersContext.Provider value with useMemo, using appropriate dependencies from useMixerHelper. Since Phase 28 already separated VU updates via external store, this phase focuses exclusively on preventing re-renders from mixer configuration changes.
+
+## Standard Stack
+
+The established libraries/tools for this domain:
+
+### Core
+| Library | Version | Purpose | Why Standard |
+|---------|---------|---------|--------------|
+| React useMemo | built-in (16.13.1) | Memoize context values | Official React API for preventing object recreation |
+| React useCallback | built-in (16.13.1) | Memoize function references | Stabilizes functions passed to context consumers |
+| React memo | built-in (16.13.1) | Prevent component re-renders | Standard pattern for optimizing context consumers |
+
+### Supporting
+| Library | Version | Purpose | When to Use |
+|---------|---------|---------|-------------|
+| use-sync-external-store | 1.6.0 (already installed) | External store subscription | Already used for vuStore in Phase 28 |
+| @reduxjs/toolkit | 1.6.1 (already installed) | State management | Already used for mixer state in Redux |
+
+### Alternatives Considered
+| Instead of | Could Use | Tradeoff |
+|------------|-----------|----------|
+| useMemo | use-context-selector | Added dependency; React 19+ has native support; useMemo simpler for this phase |
+| Context splitting | Single optimized context | Splitting better separates concerns; VuContext already exists |
+| React.memo | PureComponent | Functional components are codebase standard |
+
+**Installation:**
+```bash
+# No new dependencies required
+# All optimization APIs are React built-ins or already installed
+```
+
+## Architecture Patterns
+
+### Recommended Project Structure
+```
+src/
+├── context/
+│ ├── MixersContext.js # MODIFY: Add useMemo to provider value
+│ ├── VuContext.js # ALREADY OPTIMIZED in Phase 28
+│ └── GlobalContext.js # CHECK: May need useMemo for trackVolumeObject
+├── hooks/
+│ ├── useMixerHelper.js # VERIFY: Return stable references
+│ └── useVuHelpers.js # ALREADY OPTIMIZED in Phase 28
+└── components/
+ └── client/
+ ├── JKSessionMyTrack.js # CONSUMER: Verify memo-wrapped
+ ├── SessionTrackGain.js # CONSUMER: Verify memo-wrapped
+ └── JKSessionVolumeModal.js # CONSUMER: Verify memo-wrapped
+```
+
+### Pattern 1: Memoized Context Provider Value
+**What:** Wrap the context provider value with useMemo to prevent object recreation on every render.
+**When to use:** When context value is an object containing multiple properties or functions.
+**Example:**
+```javascript
+// Source: React official docs + Kent C. Dodds blog
+// Modify MixersContext.js
+
+import React, { createContext, useContext, useMemo } from 'react';
+import useMixerHelper from '../hooks/useMixerHelper.js';
+
+const MixersContext = createContext();
+
+export const MixersProvider = ({ children }) => {
+ const mixerHelper = useMixerHelper();
+
+ // Memoize the context value - only recreate if mixerHelper changes
+ const value = useMemo(() => mixerHelper, [mixerHelper]);
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useMixersContext = () => {
+ const context = useContext(MixersContext);
+ if (!context) {
+ throw new Error('useMixersContext must be used within a MixersProvider');
+ }
+ return context;
+};
+
+export default MixersContext;
+```
+
+### Pattern 2: Stable Function References with useCallback
+**What:** Wrap functions returned from hooks with useCallback to ensure stable references across renders.
+**When to use:** When functions are part of context value or passed as props to memoized components.
+**Example:**
+```javascript
+// Source: React official docs for useCallback
+// Pattern to apply in useMixerHelper.js
+
+const faderChanged = useCallback(async (data, mixers, gainType, controlGroup) => {
+ // Implementation stays the same
+ // ...existing code...
+}, [getOriginalVolume, getMixer, fillTrackVolumeObject, setMixerVolume, allMixers, trackVolumeObject, dispatch]);
+
+// CRITICAL: Ensure ALL functions in the return object use useCallback
+// so that the entire mixerHelper object has stable references
+```
+
+### Pattern 3: Context Consumer Memoization
+**What:** Wrap context consumer components with React.memo to prevent re-renders when props haven't changed.
+**When to use:** For all components that consume context and render frequently.
+**Example:**
+```javascript
+// Source: React official docs for memo
+// Pattern for SessionTrackGain.js
+
+import React, { memo } from 'react';
+import { useMixersContext } from '../../context/MixersContext';
+
+const SessionTrackGain = memo(function SessionTrackGain({
+ mixers,
+ gainType,
+ controlGroup,
+ sessionController,
+ orientation = 'vertical'
+}) {
+ const mixerHelper = useMixersContext();
+ // ... component implementation ...
+});
+
+export default SessionTrackGain;
+```
+
+### Pattern 4: Split Context by Update Frequency
+**What:** Separate high-frequency updates (VU) from low-frequency updates (mixer config) into different contexts.
+**When to use:** When context contains data that updates at dramatically different rates.
+**Example:**
+```javascript
+// Source: Kent C. Dodds optimization guide + developerway.com patterns
+// This pattern is ALREADY IMPLEMENTED in Phase 28
+
+// VuContext.js - High-frequency updates (50-70/sec) via external store
+export const VuProvider = ({ children }) => {
+ const vuHelpers = useVuHelpers();
+
+ const value = useMemo(() => ({
+ ...vuHelpers,
+ vuStore,
+ }), [vuHelpers]);
+
+ return {children};
+};
+
+// MixersContext.js - Low-frequency updates (user interactions)
+export const MixersProvider = ({ children }) => {
+ const mixerHelper = useMixerHelper();
+ const value = useMemo(() => mixerHelper, [mixerHelper]);
+ return {children};
+};
+```
+
+### Anti-Patterns to Avoid
+- **Creating new objects in provider:** `value={{ ...mixerHelper }}` creates new object every render
+- **Inline object literals:** `value={{ data, functions }}` always creates new reference
+- **Missing dependencies in useMemo:** Stale closures over mixer state
+- **Overusing useMemo:** Don't memoize primitive values or simple calculations
+- **Forgetting useCallback for functions:** Functions recreated on every render break memo
+- **Not combining memo with useMemo:** Memoizing context value alone doesn't prevent consumer re-renders if props change
+
+## Don't Hand-Roll
+
+Problems that look simple but have existing solutions:
+
+| Problem | Don't Build | Use Instead | Why |
+|---------|-------------|-------------|-----|
+| Context value comparison | Custom shallow equality | useMemo with correct dependencies | React team optimized useMemo for this; handles edge cases |
+| Function reference stability | Manual ref tracking | useCallback hook | Built-in, well-tested, works with concurrent rendering |
+| Component re-render prevention | Custom shouldComponentUpdate | React.memo | Optimized for functional components, simpler API |
+| Context selector pattern | Custom subscription system | Use useMemo at consumer level | React 19+ has useContextSelector; for React 16 useMemo simpler than library |
+
+**Key insight:** React's built-in memoization hooks (useMemo, useCallback, memo) are heavily optimized for concurrent rendering and cover the vast majority of context optimization needs. Adding external libraries like use-context-selector adds complexity and bundle size without significant benefit for this specific use case where context updates are already infrequent (user interactions only).
+
+## Common Pitfalls
+
+### Pitfall 1: useMemo Dependencies Not Comprehensive
+**What goes wrong:** Context value still recreated on every render, defeating memoization
+**Why it happens:** Missing dependency in useMemo array, or dependency itself recreates every render
+**How to avoid:**
+- Use ESLint react-hooks/exhaustive-deps rule
+- Ensure hook return values are stable (useCallback wraps functions)
+- Verify dependencies with React DevTools Profiler
+**Warning signs:** React DevTools shows "MixersProvider" re-rendering every time, even without state changes
+
+### Pitfall 2: Memoizing Value But Not Function References
+**What goes wrong:** Context value object appears memoized, but functions inside recreate, breaking memo
+**Why it happens:** Functions returned from hooks aren't wrapped in useCallback
+**How to avoid:** Wrap ALL functions in useCallback with correct dependencies
+**Warning signs:** memo-wrapped consumers still re-render; React DevTools highlights function prop changes
+
+### Pitfall 3: memo Without Stable Props
+**What goes wrong:** Component wrapped in memo still re-renders frequently
+**Why it happens:** Parent passes new object/array/function references as props each render
+**How to avoid:**
+- useMemo for object/array props
+- useCallback for function props
+- Pass primitive values when possible
+**Warning signs:** Profiler shows "did not skip render" for memo components
+
+### Pitfall 4: Overusing useMemo for Everything
+**What goes wrong:** Code becomes harder to read, minimal performance benefit
+**Why it happens:** Premature optimization without measuring actual performance impact
+**How to avoid:**
+- Only memoize context provider values and expensive computations
+- Don't memoize primitive values or simple JSX
+- Profile with React DevTools before adding memoization
+**Warning signs:** Code complexity increases but Profiler shows no improvement
+
+### Pitfall 5: Stale Closures from Missing Dependencies
+**What goes wrong:** Memoized functions reference old state/props, causing bugs
+**Why it happens:** Dependencies array missing reactive values, creating closure over stale data
+**How to avoid:**
+- Include ALL reactive values in dependency array
+- Use ESLint warnings as guide
+- Test edge cases where state updates quickly
+**Warning signs:** Functions behave with old data; intermittent bugs during rapid interactions
+
+### Pitfall 6: Context Splitting Without Clear Boundaries
+**What goes wrong:** Confusion about which context provides what data
+**Why it happens:** Context split arbitrarily without clear domain separation
+**How to avoid:**
+- Split by update frequency (VU vs config) or domain (auth vs app state)
+- Document each context's purpose clearly
+- Name contexts descriptively (VuContext, MixersContext)
+**Warning signs:** Consumers import multiple contexts; unclear which context owns which data
+
+## Code Examples
+
+Verified patterns from official sources:
+
+### Complete MixersContext Optimization
+```javascript
+// Source: React official docs + codebase pattern
+// Modify jam-ui/src/context/MixersContext.js
+
+import React, { createContext, useContext, useMemo } from 'react';
+import useMixerHelper from '../hooks/useMixerHelper.js';
+
+const MixersContext = createContext();
+
+export const MixersProvider = ({ children }) => {
+ const mixerHelper = useMixerHelper();
+
+ // CRITICAL: Memoize the entire value object
+ // Since useMixerHelper returns stable references (via useCallback),
+ // this prevents new object creation on every render
+ const value = useMemo(() => mixerHelper, [mixerHelper]);
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useMixersContext = () => {
+ const context = useContext(MixersContext);
+ if (!context) {
+ throw new Error('useMixersContext must be used within a MixersProvider');
+ }
+ return context;
+};
+
+export default MixersContext;
+```
+
+### Verify useMixerHelper Returns Stable References
+```javascript
+// Source: Current useMixerHelper.js pattern + React useCallback docs
+// Audit jam-ui/src/hooks/useMixerHelper.js return statement
+
+// BEFORE (if needed):
+return {
+ faderChanged: (data, mixers) => { /* impl */ }, // ❌ New function every render
+ myTracks, // ❌ May recreate if not memoized
+ mixMode
+};
+
+// AFTER:
+const faderChanged = useCallback(async (data, mixers, gainType, controlGroup) => {
+ // ...existing implementation...
+}, [getOriginalVolume, getMixer, fillTrackVolumeObject, setMixerVolume, allMixers, trackVolumeObject, dispatch]);
+
+const myTracks = useMemo(() => {
+ // ...existing computation...
+}, [currentSession, isConnected, jamClient, allMixers, mixMode, findMixerForTrack, getParticipant, server.clientId]);
+
+// VERIFIED: All functions use useCallback, computed values use useMemo
+return {
+ isReady,
+ session: currentSession,
+ mixers: allMixers,
+ myTracks, // ✅ Memoized
+ findMixerForTrack, // ✅ useCallback
+ updateMixerData, // ✅ useCallback
+ updateVU, // ✅ useCallback
+ simulatedMusicCategoryMixers,
+ simulatedChatCategoryMixers,
+ mixMode,
+ faderChanged, // ✅ useCallback
+ initGain, // ✅ useCallback
+ setMixerPan, // ✅ useCallback
+ getAudioInputCategoryMixer, // ✅ useCallback
+ getChatCategoryMixer, // ✅ useCallback
+ backingTracks,
+ jamTracks,
+ recordedTracks
+};
+```
+
+### Memoize Context Consumers
+```javascript
+// Source: React memo documentation
+// Pattern for SessionTrackGain.js and other consumers
+
+import React, { memo } from 'react';
+import { useMixersContext } from '../../context/MixersContext';
+
+// Wrap the entire component export with memo
+const SessionTrackGain = memo(function SessionTrackGain({
+ mixers,
+ gainType,
+ controlGroup,
+ sessionController,
+ orientation = 'vertical'
+}) {
+ const mixerHelper = useMixersContext();
+ const faderHelpers = useFaderHelpers();
+
+ // Component implementation stays the same
+ // ...
+
+ return (/* JSX */);
+});
+
+// Add display name for debugging
+SessionTrackGain.displayName = 'SessionTrackGain';
+
+export default SessionTrackGain;
+```
+
+### Verify GlobalContext Memoization
+```javascript
+// Source: Current GlobalContext.js + memoization pattern
+// Check jam-ui/src/context/GlobalContext.js
+
+export const GlobalProvider = ({ children }) => {
+ const [trackVolumeObject, setTrackVolumeObject] = useState({ /* ... */ });
+ const [globalObject, setGlobalObject] = useState({ /* ... */ });
+ const [videoEnabled, setVideoEnabled] = useState(false);
+
+ const { metronomeState, updateMetronomeState, openMetronome, closeMetronome, resetMetronome } = useMetronomeState();
+
+ // CRITICAL: Memoize the provider value
+ const value = useMemo(() => ({
+ trackVolumeObject,
+ setTrackVolumeObject,
+ globalObject,
+ setGlobalObject,
+ metronomeState,
+ updateMetronomeState,
+ openMetronome,
+ closeMetronome,
+ resetMetronome,
+ }), [trackVolumeObject, globalObject, metronomeState, updateMetronomeState, openMetronome, closeMetronome, resetMetronome]);
+
+ return (
+
+ {children}
+
+ );
+};
+```
+
+### Testing Context Optimization
+```javascript
+// Source: React DevTools Profiler best practices
+// Pattern for verification after implementing optimization
+
+// Use React DevTools Profiler to verify:
+// 1. Record a session with Profiler
+// 2. Move a volume slider (triggers MixersContext update)
+// 3. Check which components re-rendered
+
+// BEFORE optimization:
+// - MixersProvider re-renders ❌
+// - ALL consumers re-render (JKSessionMyTrack, SessionTrackGain, etc.) ❌
+// - VU meters re-render ❌
+
+// AFTER optimization:
+// - MixersProvider does NOT re-render ✅
+// - Only consumers with changed props re-render ✅
+// - VU meters do NOT re-render (external store) ✅
+
+// Success criteria from requirements:
+// - CTX-01: MixersContext.Provider value is memoized ✅
+// - CTX-02: VuContext separated from MixersContext ✅ (Phase 28)
+// - CTX-03: Volume slider change doesn't re-render VU meters ✅
+// - Success: VU update doesn't re-render volume sliders ✅
+```
+
+## State of the Art
+
+| Old Approach | Current Approach | When Changed | Impact |
+|--------------|------------------|--------------|--------|
+| Inline context value object | useMemo-wrapped value | React 16.8 (2019) | Prevents object recreation on every render |
+| Class components with shouldComponentUpdate | React.memo for functional components | React 16.6 (2018) | Simpler API, better with hooks |
+| Single context for all data | Context splitting by domain/frequency | Best practice (2020+) | Reduces re-render scope |
+| Props drilling | Context API | React 16.3 (2018) | Cleaner component tree, but needs optimization |
+| use-context-selector library | Native useContextSelector | React 19 (2024) | Built-in selector pattern, but not yet available in React 16 |
+
+**Deprecated/outdated:**
+- **PureComponent for context consumers:** Functional components with memo are now standard
+- **Context.Consumer render prop:** useContext hook is cleaner, more readable
+- **Separate state/dispatch contexts for every context:** Only split when update frequency differs significantly
+
+## Open Questions
+
+Things that couldn't be fully resolved:
+
+1. **Exact dependencies for MixersContext useMemo**
+ - What we know: Value should be memoized, dependencies should include mixerHelper
+ - What's unclear: Whether useMixerHelper return value is already stable (needs code audit)
+ - Recommendation: Audit useMixerHelper to ensure all functions use useCallback; if stable, dependency is just [mixerHelper]
+
+2. **Impact of memoizing GlobalContext**
+ - What we know: GlobalContext also provides trackVolumeObject which updates frequently
+ - What's unclear: Whether GlobalContext needs same optimization treatment
+ - Recommendation: Check if GlobalContext consumers experience performance issues; if yes, apply same pattern
+
+3. **Optimal granularity for context splitting**
+ - What we know: VuContext already separated (Phase 28); MixersContext contains config
+ - What's unclear: Whether MixersContext should be further split (e.g., MixerConfigContext vs MixerActionsContext)
+ - Recommendation: Start with single memoized MixersContext; split further only if profiling shows issues
+
+4. **React DevTools Profiler verification methodology**
+ - What we know: Need to verify no re-renders from context updates
+ - What's unclear: Exact profiler setup and metrics to capture
+ - Recommendation: Document profiler verification steps in verification task; include before/after screenshots
+
+## Sources
+
+### Primary (HIGH confidence)
+- [React useMemo official docs](https://react.dev/reference/react/useMemo) - API, dependencies, best practices
+- [React useCallback official docs](https://react.dev/reference/react/useCallback) - Stabilizing function references
+- [React memo official docs](https://react.dev/reference/react/memo) - Component memoization, context caveats
+- [Kent C. Dodds - How to optimize your context value](https://kentcdodds.com/blog/how-to-optimize-your-context-value) - Authoritative pattern guide
+
+### Secondary (MEDIUM confidence)
+- [How to Handle React Context Performance Issues (2026)](https://oneuptime.com/blog/post/2026-01-24-react-context-performance-issues/view) - Modern context optimization patterns
+- [developerway.com - React re-renders guide](https://www.developerway.com/posts/react-re-renders-guide) - Comprehensive re-render patterns
+- [developerway.com - Performant React apps with Context](https://www.developerway.com/posts/how-to-write-performant-react-apps-with-context) - Context performance strategies
+- [Josh Comeau - useMemo and useCallback](https://www.joshwcomeau.com/react/usememo-and-usecallback/) - Clear explanations with examples
+
+### Tertiary (LOW confidence)
+- [use-context-selector npm](https://www.npmjs.com/package/use-context-selector) - Selector pattern library (React 19+ has native support)
+- WebSearch results for React context optimization 2026 - General patterns confirmed
+
+## Metadata
+
+**Confidence breakdown:**
+- Standard stack: HIGH - All optimization APIs are React built-ins, well-documented
+- Architecture: HIGH - Patterns verified against React official docs and Kent C. Dodds authoritative sources
+- Pitfalls: HIGH - Common issues documented in official React docs and multiple authoritative sources
+
+**Research date:** 2026-03-05
+**Valid until:** 2026-04-05 (30 days - stable React patterns, no breaking changes expected)
+
+**Key constraints:**
+- React 16.13.1 (no React 19 useContextSelector available)
+- VuContext already optimized in Phase 28 with external store
+- MixersContext identified as root cause (line 10 creates new object every render)
+- Redux already used for state management (no architectural change needed)