---
estimated_steps: 17
estimated_files: 8
skills_used: []
---

# T01: Add engine CORS, scaffold Vite+React+TS app, build typed API client

This task unblocks all frontend work by: (1) adding CORSMiddleware to engine/main.py so browser requests succeed, (2) scaffolding the app/ directory as a Vite + React + TypeScript project with dev proxy to the engine, and (3) building a typed API client with TypeScript interfaces matching the engine's request/response shapes.

## Steps

1. Add `CORSMiddleware` to `engine/main.py` — import from `fastapi.middleware.cors`, allow all origins for dev (restrict in production later). Place it before the router include.
2. Scaffold `app/` using `npm create vite@latest app -- --template react-ts`. Run `cd app && npm install`.
3. Configure `app/vite.config.ts` with a dev proxy: requests to `/engine/*` forward to `http://localhost:8000`.
4. Create `app/src/types/engine.ts` with TypeScript interfaces:
   - `PresetConfig` — matches the JSON structure in `engine/presets/*.json` (name, description, preprocessing, vectorization, postprocessing sections)
   - `TraceResponse` — `{ output: string, format: string, metadata: TraceMetadata }`
   - `TraceMetadata` — `{ format: string, path_count: number, node_count_total: number, open_paths: number, island_count: number, warnings: string[], processing_ms: number }`
   - `PresetsResponse` — `{ presets: Record<string, PresetConfig> }`
5. Create `app/src/api/engine.ts` with typed functions:
   - `getPresets(): Promise<PresetsResponse>` — calls `GET /engine/presets`
   - `traceImage(file: File, preset: string, params: Record<string, unknown>, signal?: AbortSignal): Promise<TraceResponse>` — builds `FormData` with file, mode, output_format='svg', preset, and params (JSON.stringify), calls `POST /engine/trace`
   - `simplifyVector(file: File, epsilon: number, signal?: AbortSignal): Promise<TraceResponse>` — calls `POST /engine/simplify`
6. Remove Vite boilerplate: delete `app/src/App.css`, the counter component content from `App.tsx`, and the Vite/React logos.
7. Add Vitest as dev dependency: `cd app && npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom`. Configure in `vite.config.ts` with `test: { environment: 'jsdom', globals: true }`.
8. Write `app/src/api/__tests__/engine.test.ts` — unit tests for the API client using `vi.fn()` to mock fetch. Test that `traceImage()` builds correct FormData, `getPresets()` calls the right URL, and AbortSignal is passed through.

## Inputs

- `engine/main.py`
- `engine/api/routes.py`
- `engine/presets/sign.json`

## Expected Output

- `engine/main.py`
- `app/package.json`
- `app/vite.config.ts`
- `app/tsconfig.json`
- `app/src/types/engine.ts`
- `app/src/api/engine.ts`
- `app/src/api/__tests__/engine.test.ts`
- `app/src/App.tsx`
- `app/src/main.tsx`

## Verification

cd app && npx vitest run --reporter=verbose 2>&1 | tail -20
