src/ ├── shared/ ← shared between web + extension │ ├── lib/ ← google-auth, sheets, drive helpers │ └── hooks/ ← useAppData, etc. ├── web/ ← React app (popup + web dashboard) └── extension/ ← manifest, content_script app/ ← Next.js routes + API CODE_BLOCK: src/ ├── shared/ ← shared between web + extension │ ├── lib/ ← google-auth, sheets, drive helpers │ └── hooks/ ← useAppData, etc. ├── web/ ← React app (popup + web dashboard) └── extension/ ← manifest, content_script app/ ← Next.js routes + API CODE_BLOCK: src/ ├── shared/ ← shared between web + extension │ ├── lib/ ← google-auth, sheets, drive helpers │ └── hooks/ ← useAppData, etc. ├── web/ ← React app (popup + web dashboard) └── extension/ ← manifest, content_script app/ ← Next.js routes + API CODE_BLOCK: // After successful login saveTokenToExtStorage(token, profile.email); // On every popup reopen — no server roundtrip needed const stored = await loadTokenFromExtStorage(); if (stored?.token) { const profile = await getUserInfo(stored.token); if (profile) { /* restore state instantly */ } } CODE_BLOCK: // After successful login saveTokenToExtStorage(token, profile.email); // On every popup reopen — no server roundtrip needed const stored = await loadTokenFromExtStorage(); if (stored?.token) { const profile = await getUserInfo(stored.token); if (profile) { /* restore state instantly */ } } CODE_BLOCK: // After successful login saveTokenToExtStorage(token, profile.email); // On every popup reopen — no server roundtrip needed const stored = await loadTokenFromExtStorage(); if (stored?.token) { const profile = await getUserInfo(stored.token); if (profile) { /* restore state instantly */ } }
- Find a product image you want
- Right-click → Save As
- Rename the file so it makes sense later
- Navigate to the right folder
- Open your spreadsheet
- Manually type in the product name, price, URL, supplier, notes...
- Repeat. 50 times. Every session.
- They break every time the site updates its HTML
- They pull hundreds of irrelevant images — icons, banners, ads, lazy-loaded placeholders
- You get a dump of raw data with no context about why you saved anything
- Running them requires technical setup most researchers don't want to deal with
- Web dashboard → Next.js 15 + React 19 + Tailwind CSS 4
- Chrome extension → Vite + TypeScript, Manifest V3