This is your starting point for upgrading the HeySalad AI Shopper extension to Claude-style UX while preserving the mobile-to-extension QR flow.
Goal: Migrate from popup to side panel (3-5 hours)
What stays the same:
- ✅ Mobile QR code generation
- ✅ Session polling (checks API every 2 seconds)
- ✅ Progress updates to mobile
- ✅ All existing shopping functionality
What changes:
- 📦 Popup → Side Panel (persistent, doesn't close)
- 🎨 New Chrome Material Design 3 styling
- 📁 Better file organization
-
Chrome Canary (for Side Panel API testing)
- Download: https://www.google.com/chrome/canary/
- Side Panel API requires Chrome 114+
-
Current extension working
- Test mobile QR flow works in current version
- Note: You'll preserve this exact functionality
-
Sally Mobile app (for testing)
- Staging environment ready
- Can scan QR codes
cd heysalad-payme/heysalad-ai-shopper
# Create new directories
mkdir -p sidepanel/components
# You'll create these files:
# sidepanel/sidepanel.html
# sidepanel/sidepanel.js
# sidepanel/sidepanel.css
# sidepanel/components/mobile-qr.jsOpen manifest.json and add:
{
"manifest_version": 3,
"version": "2.0.0",
"side_panel": {
"default_path": "sidepanel/sidepanel.html"
},
"action": {
"default_title": "Sally - AI Shopping Assistant"
},
"permissions": [
"sidePanel",
"storage",
"activeTab",
"scripting",
"tabs",
"notifications"
]
}Key changes:
- Added
"side_panel"config - Added
"sidePanel"permission - Removed
"default_popup"(side panel replaces it)
Create sidepanel/components/mobile-qr.js:
# Copy the mobile QR functions from popup.js (lines 1100-1401)
# See PHASE_1_SIDE_PANEL_MIGRATION.md for the complete codeCritical functions to include:
showExtensionQR()- Generates QR with session tokenstartSessionPolling()- Polls API every 2 secondsstartSessionTimer()- 15-minute countdownstartShoppingFromMobile()- Receives list from mobilesendProgressUpdate()- Sends progress to APIgenerateExtensionSessionToken()- Creates unique token
Create sidepanel/sidepanel.html:
<!DOCTYPE html>
<html>
<head>
<title>Sally</title>
<link rel="stylesheet" href="sidepanel.css">
</head>
<body>
<div id="main-section">
<header class="panel-header">
<h1>Sally</h1>
<span class="badge">by HeySalad®</span>
</header>
<!-- ✅ KEEP - Mobile QR Section -->
<section class="mobile-integration">
<h3>Shop from Mobile</h3>
<button class="btn-primary" id="show-qr-code-btn">
📱 Show QR Code
</button>
</section>
<!-- Shopping Form -->
<section id="task-form">
<h3>Or enter manually</h3>
<select id="store-select">
<option value="">Auto-detect</option>
<option value="tesco">Tesco</option>
<option value="sainsburys">Sainsbury's</option>
</select>
<textarea id="items-input" rows="8"></textarea>
<button id="start-btn" class="btn-primary">🛒 Let Sally Shop!</button>
</section>
</div>
<!-- ✅ KEEP - Extension QR Section -->
<div id="extension-qr-section" class="hidden">
<header class="panel-header">
<h2>Scan with Mobile</h2>
<button id="extension-qr-cancel-btn">✕</button>
</header>
<div class="qr-container">
<div id="extension-qr-display"></div>
<p id="extension-qr-status">⏳ Waiting for mobile...</p>
<p id="extension-qr-timer">Expires in 15:00</p>
</div>
</div>
<script src="../popup/qrcode.min.js"></script>
<script src="components/mobile-qr.js"></script>
<script src="sidepanel.js"></script>
</body>
</html>Create sidepanel/sidepanel.js:
// Setup event listeners for mobile QR
document.addEventListener('DOMContentLoaded', () => {
const showQRBtn = document.getElementById('show-qr-code-btn');
const qrCancelBtn = document.getElementById('extension-qr-cancel-btn');
if (showQRBtn) {
showQRBtn.addEventListener('click', () => window.MobileQR.showExtensionQR());
}
if (qrCancelBtn) {
qrCancelBtn.addEventListener('click', () => window.MobileQR.closeExtensionQR());
}
// ... rest of your existing popup.js logic
});Update background/service-worker.js:
// Open side panel when extension icon clicked
chrome.action.onClicked.addListener(async (tab) => {
try {
await chrome.sidePanel.open({ tabId: tab.id });
} catch (error) {
console.error('[Sally] Failed to open side panel:', error);
}
});- Open Chrome Canary
- Go to
chrome://extensions/ - Enable "Developer mode"
- Click "Load unpacked"
- Select
heysalad-ai-shopperdirectory - Click extension icon → Side panel should open!
- Click "📱 Show QR Code" in side panel
- Expected: QR code displays, timer starts at 15:00
- Check console: Should see
[Sally] Extension QR displayed, token: ext_...
- Open Sally Mobile app (staging)
- Navigate to "Shop with Sally"
- Scan the QR code
- Expected: Extension receives list, starts shopping
- Check console: Should see
[Sally] Shopping list received!
- While shopping, check mobile app
- Expected: Real-time progress updates (<2 second delay)
- Check console: Should see
[Sally] Progress update sent: X%
- Generate QR code
- Wait 15 minutes (or modify timer for testing)
- Expected: "Session expired" message, polling stops
Fix: Check Chrome version (need 114+)
if (!chrome.sidePanel) {
console.error('Side Panel API not available');
}Fix: Check if QRCode library loaded
if (typeof QRCode === 'undefined') {
console.error('QRCode library not loaded');
}Fix: Check API endpoint and session ID
console.log('[Sally] Session ID:', sessionId);
console.log('[Sally] API endpoint:', `sally-api.heysalad-o.workers.dev/api/extension/token/${sessionId}/progress`);Fix: Check interval is running
console.log('[Sally] Polling interval:', sessionPollInterval);Once side panel + mobile QR flow is working:
- ✅ Phase 1 Complete - Side panel with mobile integration
- 📋 Phase 2 - Add tab badges (see CLAUDE_STYLE_UX_TASKS.md)
- 🎨 Phase 3 - Add corner indicator
- 💅 Phase 4 - Polish with Chrome Material Design 3
Full implementation details: See PHASE_1_SIDE_PANEL_MIGRATION.md
Mobile integration context: See CLAUDE_STYLE_WITH_MOBILE_INTEGRATION.md
All tasks: See CLAUDE_STYLE_UX_TASKS.md
Architecture overview: See CLAUDE_STYLE_UX_UPGRADE_PLAN.md
# Create directories
mkdir -p sidepanel/components
# Copy QRCode library (if needed)
cp popup/qrcode.min.js sidepanel/
# Test in Chrome Canary
open -a "Google Chrome Canary" --args --load-extension=$(pwd)
# Watch for changes (if using build tool)
npm run watchEstimated Time: 30 minutes to first working version, 3-5 hours for complete Phase 1
Status: Ready to implement
Priority: HIGH - This is the foundation for all other improvements
Let's get started! 🚀