# ChicoryTV SPA Typed API Client Auth Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Build issue #81: generate typed API types from the ErsatzTV OpenAPI document, add API-key aware fetch/data helpers, and render a live channel-list smoke screen.

**Architecture:** Generate TypeScript schema types from `ErsatzTV/wwwroot/openapi/v1.json` into `web/src/api/generated/`. Keep hand-written runtime behavior in small files under `web/src/api/`: API-key storage, typed fetch/error handling, and a channel query hook. `App.tsx` consumes the hook and renders loading, error, empty, and data states without changing the ASP.NET API surface.

**Tech Stack:** Vite, React 19, TypeScript, Vitest, Testing Library, local OpenAPI JSON generator script, browser `fetch`, `localStorage`.

---

### Task 1: API Generation Wiring

**Files:**
- Modify: `web/package.json`
- Modify: `.gitea/workflows/docker-build.yml`
- Create: `web/scripts/generate-openapi-types.mjs`
- Create: `web/src/api/generated/v1.d.ts`

- [x] Add a local OpenAPI generator script and package scripts:
  - `generate:api`: `node scripts/generate-openapi-types.mjs`
  - `check:api`: `npm run generate:api && git diff --exit-code -- src/api/generated/v1.d.ts`
- [x] Add `npm run check:api` to the existing SPA CI workflow.
- [x] Run `cd web && npm run generate:api`.
- [x] Run `cd web && npm run check:api`.

### Task 2: API Runtime and Auth Tests

**Files:**
- Create: `web/src/api/client.test.ts`
- Create: `web/src/api/auth.test.ts`

- [x] Write failing tests proving:
  - API key storage reads/writes/clears `ctv-api-key`.
  - Mutating requests include `X-Api-Key`.
  - Read requests do not include `X-Api-Key`.
  - Non-OK API responses throw an `ApiError` with status and problem details.
- [x] Run `cd web && npm test -- --run src/api/client.test.ts src/api/auth.test.ts` and confirm the tests fail because the modules do not exist.

### Task 3: API Runtime and Auth Implementation

**Files:**
- Create: `web/src/api/auth.ts`
- Create: `web/src/api/client.ts`
- Create: `web/src/api/channels.ts`
- Create: `web/src/api/index.ts`

- [x] Implement `getStoredApiKey`, `setStoredApiKey`, and `clearStoredApiKey`.
- [x] Implement `ApiError`, typed `request`, and `getChannels`.
- [x] Run `cd web && npm test -- --run src/api/client.test.ts src/api/auth.test.ts` and confirm the new tests pass.

### Task 4: Data-Fetching Hook and Smoke Screen

**Files:**
- Create: `web/src/api/useChannelsQuery.ts`
- Modify: `web/src/App.test.tsx`
- Modify: `web/src/App.tsx`
- Modify: `web/src/shell.css`

- [x] Write failing tests for loading, error, empty, and live channel-list states.
- [x] Run `cd web && npm test -- --run src/App.test.tsx` and confirm the smoke-screen tests fail before implementation.
- [x] Implement `useChannelsQuery` and render the channel smoke panel in `App.tsx`.
- [x] Run `cd web && npm test -- --run src/App.test.tsx` and confirm the tests pass.

### Task 5: Verification and Completion

**Files:**
- Modify as needed from previous tasks.

- [x] Run `cd web && npm test -- --run`.
- [x] Run `cd web && npm run lint`.
- [x] Run `cd web && npm run typecheck`.
- [x] Run `cd web && npm run build`.
- [x] Run `git status --short`.
- [ ] Commit and push with a message referencing `#81`.
- [ ] Use the `done` skill for issue `#81`.
