# HLS Player Alignment v2 Implementation Plan

> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

**Goal:** Align the existing HLS player with the prompt’s network/orchestration requirements (ports, scripts, proxy), and the URL/embed schema requirements.

**Architecture:** Keep the React/Vite frontend on port 7594 and add an Express backend on port 2738 with an optional HLS proxy endpoint. Update config parsing to accept `?src=...&auto=1&muted=1` and emit a responsive embed snippet. Dev/prod scripts should orchestrate both services with env injection and production logging.

**Tech Stack:** React 19 + Vite + Tailwind, hls.js + Plyr, Node.js + Express, Vitest, Node built‑in test runner, shell scripts.

---

### Task 1: Update URL parameter schema (src/auto + numeric flags)

**Files:**
- Modify: `hls-player/src/lib/configCodec.ts`
- Modify: `hls-player/src/lib/configCodec.test.ts`
- Modify: `hls-player/src/components/EmbedSnippet.tsx`

**Step 1: Write failing tests**
Update `hls-player/src/lib/configCodec.test.ts` to add:
- `src` alias for `url`
- `auto=1`, `muted=1`, `controls=0`, `loop=1` numeric parsing
- Backward compatibility with `url` + `autoplay`

Run: `cd hls-player && npm run test -- src/lib/configCodec.test.ts`
Expected: FAIL with missing parsing logic

**Step 2: Implement codec support**
Update `decodeConfig` to:
- Use `src` when `url` is missing
- Accept `auto` as alias for `autoplay`
- Parse boolean values from `true|false|1|0`

Update `encodeConfig` to emit canonical params:
- `src`, `auto`, `muted`, `controls`, `loop` as `1/0`
- `preload`, `poster` remain string

**Step 3: Update embed snippet to emit canonical params**
Update `EmbedSnippet` to use the canonical param keys.

**Step 4: Re-run tests**
Run: `cd hls-player && npm run test -- src/lib/configCodec.test.ts`
Expected: PASS

**Step 5: Commit**
```bash
git add hls-player/src/lib/configCodec.ts hls-player/src/lib/configCodec.test.ts hls-player/src/components/EmbedSnippet.tsx
git commit -m "feat: support src/auto param schema"
```

---

### Task 2: Responsive embed snippet (16:9 container)

**Files:**
- Modify: `hls-player/src/components/EmbedSnippet.tsx`

**Step 1: Write failing test (optional)**
If adding a test, create `hls-player/src/components/EmbedSnippet.test.tsx` to assert the snippet includes a 16:9 wrapper style.
Run: `cd hls-player && npm run test -- src/components/EmbedSnippet.test.tsx`
Expected: FAIL

**Step 2: Implement responsive snippet**
Update the snippet string to include:
- Wrapper div with `position: relative; width: 100%; padding-top: 56.25%`
- iframe absolutely positioned to fill container

**Step 3: Run tests (if added)**
Run: `cd hls-player && npm run test -- src/components/EmbedSnippet.test.tsx`
Expected: PASS

**Step 4: Commit**
```bash
git add hls-player/src/components/EmbedSnippet.tsx hls-player/src/components/EmbedSnippet.test.tsx
# (omit test file if not created)
git commit -m "feat: add responsive embed snippet"
```

---

### Task 3: Express backend + optional CORS proxy

**Files:**
- Create: `backend/package.json`
- Create: `backend/index.js`
- Create: `backend/proxy.js`
- Create: `backend/tests/proxy.test.js`
- Create: `backend/README.md`

**Step 1: Add backend package.json**
Include dependencies: `express`, `cors`, `undici` (for proxy), and `nodemon` (dev).
Scripts:
- `dev`: `nodemon index.js`
- `start`: `node index.js`
- `test`: `node --test tests/proxy.test.js`

**Step 2: Write failing tests for proxy validation**
Create `backend/tests/proxy.test.js` to assert:
- Rejects non-http(s) URLs
- Rejects localhost / private IPs
- Accepts https public URL

Run: `cd backend && npm run test`
Expected: FAIL (validation function missing)

**Step 3: Implement proxy helper**
Create `backend/proxy.js` with:
- `validateProxyUrl(rawUrl)` returning `{ ok: boolean, reason?: string }`
- Uses `new URL()` parsing
- Blocks `localhost`, `127.0.0.0/8`, `::1`, `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`
- Only allows `http:` and `https:`

**Step 4: Implement Express server**
Create `backend/index.js`:
- Port `2738` (env override `BACKEND_PORT`)
- `GET /health` → `{ status: "ok" }`
- `GET /proxy?url=` uses `validateProxyUrl`, then `undici.fetch` and streams response, sets `Access-Control-Allow-Origin: *`
- Serve `../hls-player/dist` as static if exists

**Step 5: Run tests**
Run: `cd backend && npm run test`
Expected: PASS

**Step 6: Commit**
```bash
git add backend/package.json backend/index.js backend/proxy.js backend/tests/proxy.test.js backend/README.md
git commit -m "feat: add express backend with hls proxy"
```

---

### Task 4: Orchestration scripts alignment (dev/prod + logging)

**Files:**
- Modify: `dev.sh`
- Modify: `prod.sh`
- Create: `logs/.gitkeep`

**Step 1: Update dev.sh**
- Ensure frontend runs on 7594
- Backend runs on 2738 with hot reload (`cd backend && npm run dev`)
- Inject env vars: `FRONTEND_URL`, `BACKEND_URL`, `VITE_BACKEND_URL`
- Check/install deps in `hls-player` and `backend`

**Step 2: Update prod.sh**
- Build frontend
- Serve frontend on 7594 using `npx serve` (add `serve` as devDependency in `hls-player` or use `npx`)
- Start backend on 2738
- Ensure logs directory exists and redirect output to `logs/prod.log`

**Step 3: Commit**
```bash
git add dev.sh prod.sh logs/.gitkeep hls-player/package.json hls-player/package-lock.json
# (include package changes if adding serve)
git commit -m "chore: align dev/prod orchestration"
```

---

### Task 5: Documentation alignment

**Files:**
- Modify: `hls-player/README.md`

**Step 1: Update README**
Add sections:
- Port mapping (7594 frontend, 2738 backend)
- Query param schema (`src`, `auto`, `muted`, `controls`, `loop`, `poster`, `preload`)
- Proxy usage (`/proxy?url=...`)
- Responsive embed snippet example

**Step 2: Commit**
```bash
git add hls-player/README.md
git commit -m "docs: update ports and embed params"
```

---

### Task 6: Verification

**Step 1: Run frontend tests**
Run: `cd hls-player && npm run test`
Expected: PASS

**Step 2: Build frontend**
Run: `cd hls-player && npm run build`
Expected: PASS

**Step 3: Run backend tests**
Run: `cd backend && npm run test`
Expected: PASS

**Step 4: Smoke check (optional)**
Run: `./dev.sh`
Verify:
- Frontend on `http://127.0.0.1:7594`
- Backend on `http://127.0.0.1:2738/health`
- Proxy responds: `http://127.0.0.1:2738/proxy?url=https://example.com/stream.m3u8`

**Step 5: Commit (if fixes required)**
Commit any fixes uncovered during verification.
