# Wavefunction interface (frontend)

React, TypeScript (strict, no `any`), Vite, zustand and Tailwind. Read the root [AGENTS.md](../AGENTS.md) first.

## Where things are (`src/`)

| Area                                                              | Files                                                                                                                                                          |
| ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| App shell: window, sidebar, page routing, onboarding              | `coding/app.tsx` (`CodingApp`, `Shell`), `coding/sidebar.tsx`, `coding/onboarding.tsx`, `coding/navigation-header.tsx`                                         |
| A chat: transcript, messages, approval and question cards, search | `coding/app.tsx` (`Chat`, `RunMessage`, `UserMessage`, `PauseCard`, `SearchDialog`), `coding/questions.tsx`, `coding/run-transcript.ts`, `coding/markdown.tsx` |
| Chat state, streams, captured ownership                           | `coding/store.ts`, `coding/thread-activity.ts`, `coding/api.ts`                                                                                                |
| Composer: input, slash skills, file references, drafts            | `coding/composer.tsx`, `coding/composer-context.tsx`, `coding/context-draft.ts`                                                                                |
| Workbench: files, changes, diffs, terminals, previews             | `coding/workbench.tsx`, `coding/changes.tsx`, `coding/diff.tsx`, `coding/terminal.tsx`, `coding/file-preview.tsx`                                              |
| Settings pages                                                    | `coding/settings.tsx`, `views/*-settings.tsx`, `views/connectors-view.tsx`, `views/skills-view.tsx`                                                            |
| Shared settings and connector state                               | `store/settings.ts`                                                                                                                                            |
| Requests and native bridges                                       | `lib/api.ts`, `lib/transport.ts`, `lib/titlebar.ts`, `lib/zoom.ts`, `lib/notifications.ts`                                                                     |
| API response types                                                | `lib/api.gen.ts`, generated by `npm run generate:api`; `lib/types.ts` and `coding/api.ts` alias its schemas                                                    |
| Styling                                                           | `coding/*.css`, `components/ui/`, `index.css`                                                                                                                  |

## Testing

- Tests sit beside the code they cover (`x.test.tsx`). `src/test/setup.ts` installs DOM matchers and cleanup; `src/test/fixtures.ts` builds complete typed responses (`makeProject`, `makeThread`, `makeOpenChat`, `makeRun`, `makeEvent`).
- One file: `npm --prefix frontend test -- src/coding/composer.test.tsx`. The tests related to files you changed: `npm --prefix frontend exec -- vitest related --run src/coding/x.tsx`.
- Test what the user does and sees, and where requests go; not markup, CSS strings, or that removed UI stays absent.
- See a change in a browser with `npm run dev:fixture` ([driving the fixture](../.agents/skills/drive-fixture/SKILL.md)). Native-only behavior needs the desktop shell.

## Rules here

- Route late responses, streams, approvals, context and drafts to the chat that captured them.
- Preserve unrelated file edits and recovered drafts.
- Give controls accessible names, so people and browser automation use the same controls.
