# Project context — Playlist Butler

## What it does
Local-first indexing + browsing of the YouTube playlist you are currently viewing.

## Architecture (MV3)
- **Popup** (`src/popup/*`) triggers indexing and renders indexed videos.
- **Service worker** (`src/background/service_worker.js`) orchestrates indexing and DB writes (and progress to popup).
- **Content script** (`src/content/content_bridge.js`) runs in the YouTube playlist tab:
  - extracts initial page data (ytcfg + initialData)
  - fetches playlist continuation pages via `youtubei/v1/browse`
  - normalizes playlist video items
  - sends items/progress back to service worker

## Data model (IndexedDB)
- playlists: playlistId, title, lastIndexedAt, counts
- videos: keyed by (playlistId, videoId) or similar
- pagination uses offset/limit in popup (limit configurable 25/50/100)

## Known issues (as of v0.3.9 debug build)
- Continuation (>100) fetch returns HTTP 200 but parsing yields 0 items.
- Debug logs show continuation response keys include `onResponseReceivedActions`, but no `playlistVideoRenderer` is found by current parser.

## Design constraints
- Local-first: no server calls besides YouTube itself.
- Must handle very large playlists (1,000–5,000).
- Must remain compatible with other YouTube extensions (avoid DOM scraping; prefer Innertube JSON).

## Debugging approach
Use the popup **Debug** panel.
- It persists logs in `chrome.storage.local` key: `pb_debug`.
- “Copy report” is the artifact to share between humans/agents.
