diff --git a/.gitignore b/.gitignore
index f254b5b..2f79ea2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,8 +38,8 @@ node_modules/
.npm/
package-lock.json
!speech_to_speech/package-lock.json
-!frontend-s2s/package-lock.json
-frontend-s2s/.eslintcache
+!s2s-frontend/package-lock.json
+s2s-frontend/.eslintcache
yarn-error.log
npm-debug.log*
yarn-debug.log*
diff --git a/README.md b/README.md
index b27f90d..de06c9e 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ documentation, source identifiers, comments, and internal instructions use Engli
| Component | Purpose |
|---|---|
-| [frontend-s2s](frontend-s2s) | React, TypeScript, and Tailwind browser UI, served by Vite with hot reload |
+| [s2s-frontend](s2s-frontend) | React, TypeScript, and Tailwind browser UI, served by Vite with hot reload |
| [s2s-client](s2s-client) | FastAPI backend, realtime WebSocket proxy, search and ApiPilot bridges; retained static client |
| [speech_to_speech](speech_to_speech) | Queue-driven VAD, speech recognition, language model, and speech synthesis pipeline |
| [s2s-reasoning-engine](s2s-reasoning-engine) | Optional Node-RED HTTP reasoning and conversation logging flows |
@@ -34,7 +34,7 @@ Leave `SPEECH_TO_SPEECH_URL` unset to use the same-origin speech proxy.
The launcher requires Python 3 with venv support, Node.js 22.18+ on the 22.x
line or Node.js 24+, npm, Bash 4.4+, `setsid`, and `curl`. For staging hostnames,
set `S2S_DEV_ALLOWED_HOSTS` and forward the Vite HMR WebSocket through the existing
-HTTPS reverse proxy. See [development setup](frontend-s2s/README.md).
+HTTPS reverse proxy. See [development setup](s2s-frontend/README.md).
The existing Docker image still serves the retained static client. To build it,
use the repository root as the Docker build context so documentation is included:
diff --git a/docs/client/architecture.md b/docs/client/architecture.md
index 9d319ad..a5e9463 100644
--- a/docs/client/architecture.md
+++ b/docs/client/architecture.md
@@ -1,6 +1,6 @@
# Client architecture
-The [React browser client](../../frontend-s2s) uses the
+The [React browser client](../../s2s-frontend) uses the
[FastAPI backend](../../s2s-client) for HTTP APIs and a speech WebSocket relay.
`start_ui.sh` serves Vite on the existing public port `8420` and FastAPI on
loopback port `8421`. Vite forwards backend routes and provides hot reload;
@@ -44,13 +44,13 @@ audio. It is not an unconditional byte-for-byte tunnel.
|---|---|
| [server.py](../../s2s-client/server.py) | Configuration, static serving, WebSocket relay, context loading, ApiPilot, reasoning, search, queue and usage routes |
| [start_ui.sh](../../start_ui.sh) | Dependency setup, ports, readiness, reload processes, and shutdown |
-| [vite.config.ts](../../frontend-s2s/vite.config.ts) | Public development endpoint, HMR, allowed hosts, and backend routing |
-| [App.tsx](../../frontend-s2s/src/App.tsx) | React layout, voice controls, dialogs, profile and reports sidebar |
-| [controller.ts](../../frontend-s2s/src/realtime/controller.ts) | Application state, settings, context, queue, tools and external reasoning |
-| [client.ts](../../frontend-s2s/src/realtime/client.ts) | Realtime protocol, session lifecycle, audio and transcript events |
-| [components](../../frontend-s2s/src/components) | Chat, account, settings and voice components |
-| [audio](../../frontend-s2s/src/audio) | TypeScript capture/playback worklets, PCM codec, and visualizer |
-| [legacy-theme.css](../../frontend-s2s/src/styles/legacy-theme.css) | Retained themes and responsive visual styles alongside Tailwind |
+| [vite.config.ts](../../s2s-frontend/vite.config.ts) | Public development endpoint, HMR, allowed hosts, and backend routing |
+| [App.tsx](../../s2s-frontend/src/App.tsx) | React layout, voice controls, dialogs, profile and reports sidebar |
+| [controller.ts](../../s2s-frontend/src/realtime/controller.ts) | Application state, settings, context, queue, tools and external reasoning |
+| [client.ts](../../s2s-frontend/src/realtime/client.ts) | Realtime protocol, session lifecycle, audio and transcript events |
+| [components](../../s2s-frontend/src/components) | Chat, account, settings and voice components |
+| [audio](../../s2s-frontend/src/audio) | TypeScript capture/playback worklets, PCM codec, and visualizer |
+| [legacy-theme.css](../../s2s-frontend/src/styles/legacy-theme.css) | Retained themes and responsive visual styles alongside Tailwind |
| [auth.py](../../s2s-client/auth.py) | Hugging Face OAuth and caller identity/tier |
| [limiter.py](../../s2s-client/limiter.py) | SQLite daily talk-time reservations and reconciliation |
| [flows.json](../../s2s-reasoning-engine/flows.json) | Node-RED reasoning and assistant-response logging |
@@ -82,11 +82,11 @@ usage; its static responses retain the existing no-cache headers.
1. The browser captures microphone audio with echo cancellation, noise
suppression and automatic gain-control settings.
-2. [mic-capture.worklet.ts](../../frontend-s2s/src/audio/mic-capture.worklet.ts) resamples to 16 kHz
+2. [mic-capture.worklet.ts](../../s2s-frontend/src/audio/mic-capture.worklet.ts) resamples to 16 kHz
mono PCM16. The browser sends base64 `input_audio_buffer.append` frames.
3. The backend processes VAD → STT → LLM → TTS and emits realtime events.
4. Assistant PCM16 audio at the current 16 kHz protocol rate is decoded and sent to
- [audio-playback.worklet.ts](../../frontend-s2s/src/audio/audio-playback.worklet.ts), which buffers,
+ [audio-playback.worklet.ts](../../s2s-frontend/src/audio/audio-playback.worklet.ts), which buffers,
resamples and fades playback edges. Input speech can clear playback for barge-in.
Audio worklets are loaded through `AudioWorklet.addModule`; keep their processor
diff --git a/docs/client/usage.md b/docs/client/usage.md
index cb72387..d533aa6 100644
--- a/docs/client/usage.md
+++ b/docs/client/usage.md
@@ -24,7 +24,7 @@ the script, values in that file can replace variables supplied on the command li
Use Node.js 22.18+ on the 22.x line or Node.js 24+, npm, Python 3 with venv,
Bash 4.4+, `setsid`, and `curl`. Remote staging access also needs the exact
hostname in `S2S_DEV_ALLOWED_HOSTS`, HTTPS, and WebSocket forwarding for speech
-and Vite HMR. See [frontend development setup](../../frontend-s2s/README.md).
+and Vite HMR. See [frontend development setup](../../s2s-frontend/README.md).
To install and start the backend manually:
@@ -36,7 +36,7 @@ S2S_PROXY_TARGET=ws://localhost:8765/v1/realtime \
--host 127.0.0.1 --port 8421 --reload --reload-dir s2s-client
```
-Then, in a second terminal, run `cd frontend-s2s`, `npm ci`, and `npm run dev`.
+Then, in a second terminal, run `cd s2s-frontend`, `npm ci`, and `npm run dev`.
Open , tap the orb/microphone control, grant microphone
access, and speak. Microphone access requires HTTPS or a local browser origin;
diff --git a/s2s-client/README.md b/s2s-client/README.md
index 81053b3..eff930a 100644
--- a/s2s-client/README.md
+++ b/s2s-client/README.md
@@ -16,7 +16,7 @@ FastAPI server and retained static voice-chat UI for an OpenAI Realtime-compatib
speech-to-speech backend. The browser streams microphone audio over WebSocket,
plays assistant audio, displays transcripts, and offers Spanish controls.
-The root `start_ui.sh` now serves the [React frontend](../frontend-s2s) with
+The root `start_ui.sh` now serves the [React frontend](../s2s-frontend) with
Vite on public port `8420`, proxying backend requests here on loopback port
`8421`. This directory's static UI remains available when FastAPI is run
directly or through the existing Docker image.
diff --git a/frontend-s2s/.editorconfig b/s2s-frontend/.editorconfig
similarity index 100%
rename from frontend-s2s/.editorconfig
rename to s2s-frontend/.editorconfig
diff --git a/frontend-s2s/.env.example b/s2s-frontend/.env.example
similarity index 100%
rename from frontend-s2s/.env.example
rename to s2s-frontend/.env.example
diff --git a/frontend-s2s/.gitignore b/s2s-frontend/.gitignore
similarity index 100%
rename from frontend-s2s/.gitignore
rename to s2s-frontend/.gitignore
diff --git a/frontend-s2s/.prettierignore b/s2s-frontend/.prettierignore
similarity index 100%
rename from frontend-s2s/.prettierignore
rename to s2s-frontend/.prettierignore
diff --git a/frontend-s2s/README.md b/s2s-frontend/README.md
similarity index 99%
rename from frontend-s2s/README.md
rename to s2s-frontend/README.md
index c02462e..9a7d498 100644
--- a/frontend-s2s/README.md
+++ b/s2s-frontend/README.md
@@ -49,7 +49,7 @@ variables, which are exposed to browser code.
## Staging with hot reload
PM2 can continue running the root `start_ui.sh` as its existing `s2s_ui` process.
-Ensure the Node/npm versions above are on PM2's PATH and deploy `frontend-s2s`
+Ensure the Node/npm versions above are on PM2's PATH and deploy `s2s-frontend`
alongside `s2s-client` and `docs`. The reverse proxy still targets port `8420`.
Set the exact public hostname in the root `.env`, without scheme or port:
@@ -74,7 +74,7 @@ Start FastAPI on `127.0.0.1:8421` as described in the
[client usage guide](../docs/client/usage.md), then run:
```sh
-cd frontend-s2s
+cd s2s-frontend
npm ci
npm run dev
```
diff --git a/frontend-s2s/config/backend-proxy.ts b/s2s-frontend/config/backend-proxy.ts
similarity index 100%
rename from frontend-s2s/config/backend-proxy.ts
rename to s2s-frontend/config/backend-proxy.ts
diff --git a/frontend-s2s/config/launcher.integration.ts b/s2s-frontend/config/launcher.integration.ts
similarity index 99%
rename from frontend-s2s/config/launcher.integration.ts
rename to s2s-frontend/config/launcher.integration.ts
index 2720a82..cce8d11 100644
--- a/frontend-s2s/config/launcher.integration.ts
+++ b/s2s-frontend/config/launcher.integration.ts
@@ -64,7 +64,7 @@ async function waitForFile(filename: string) {
async function launcher(context: TestContext, env: Record = {}) {
const root = await mkdtemp(join(tmpdir(), "s2s-launcher-"));
- const frontend = join(root, "frontend-s2s");
+ const frontend = join(root, "s2s-frontend");
const modules = join(frontend, "node_modules");
await mkdir(join(root, ".venv/bin"), { recursive: true });
await mkdir(join(root, "s2s-client"));
diff --git a/frontend-s2s/eslint.config.ts b/s2s-frontend/eslint.config.ts
similarity index 100%
rename from frontend-s2s/eslint.config.ts
rename to s2s-frontend/eslint.config.ts
diff --git a/frontend-s2s/index.html b/s2s-frontend/index.html
similarity index 100%
rename from frontend-s2s/index.html
rename to s2s-frontend/index.html
diff --git a/frontend-s2s/package-lock.json b/s2s-frontend/package-lock.json
similarity index 99%
rename from frontend-s2s/package-lock.json
rename to s2s-frontend/package-lock.json
index cf16217..e6de408 100644
--- a/frontend-s2s/package-lock.json
+++ b/s2s-frontend/package-lock.json
@@ -1,11 +1,11 @@
{
- "name": "frontend-s2s",
+ "name": "s2s-frontend",
"version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "frontend-s2s",
+ "name": "s2s-frontend",
"version": "0.0.0",
"dependencies": {
"dompurify": "^3.4.16",
diff --git a/frontend-s2s/package.json b/s2s-frontend/package.json
similarity index 98%
rename from frontend-s2s/package.json
rename to s2s-frontend/package.json
index c61a38a..795f737 100644
--- a/frontend-s2s/package.json
+++ b/s2s-frontend/package.json
@@ -1,5 +1,5 @@
{
- "name": "frontend-s2s",
+ "name": "s2s-frontend",
"private": true,
"version": "0.0.0",
"type": "module",
diff --git a/frontend-s2s/prettier.config.ts b/s2s-frontend/prettier.config.ts
similarity index 100%
rename from frontend-s2s/prettier.config.ts
rename to s2s-frontend/prettier.config.ts
diff --git a/frontend-s2s/src/App.test.tsx b/s2s-frontend/src/App.test.tsx
similarity index 100%
rename from frontend-s2s/src/App.test.tsx
rename to s2s-frontend/src/App.test.tsx
diff --git a/frontend-s2s/src/App.tsx b/s2s-frontend/src/App.tsx
similarity index 100%
rename from frontend-s2s/src/App.tsx
rename to s2s-frontend/src/App.tsx
diff --git a/frontend-s2s/src/audio/audio-playback.worklet.ts b/s2s-frontend/src/audio/audio-playback.worklet.ts
similarity index 100%
rename from frontend-s2s/src/audio/audio-playback.worklet.ts
rename to s2s-frontend/src/audio/audio-playback.worklet.ts
diff --git a/frontend-s2s/src/audio/codec.ts b/s2s-frontend/src/audio/codec.ts
similarity index 100%
rename from frontend-s2s/src/audio/codec.ts
rename to s2s-frontend/src/audio/codec.ts
diff --git a/frontend-s2s/src/audio/engine.ts b/s2s-frontend/src/audio/engine.ts
similarity index 100%
rename from frontend-s2s/src/audio/engine.ts
rename to s2s-frontend/src/audio/engine.ts
diff --git a/frontend-s2s/src/audio/mic-capture.worklet.ts b/s2s-frontend/src/audio/mic-capture.worklet.ts
similarity index 100%
rename from frontend-s2s/src/audio/mic-capture.worklet.ts
rename to s2s-frontend/src/audio/mic-capture.worklet.ts
diff --git a/frontend-s2s/src/audio/worklet-globals.d.ts b/s2s-frontend/src/audio/worklet-globals.d.ts
similarity index 100%
rename from frontend-s2s/src/audio/worklet-globals.d.ts
rename to s2s-frontend/src/audio/worklet-globals.d.ts
diff --git a/frontend-s2s/src/components/Account.tsx b/s2s-frontend/src/components/Account.tsx
similarity index 100%
rename from frontend-s2s/src/components/Account.tsx
rename to s2s-frontend/src/components/Account.tsx
diff --git a/frontend-s2s/src/components/Bubbles.tsx b/s2s-frontend/src/components/Bubbles.tsx
similarity index 100%
rename from frontend-s2s/src/components/Bubbles.tsx
rename to s2s-frontend/src/components/Bubbles.tsx
diff --git a/frontend-s2s/src/components/Conversation.tsx b/s2s-frontend/src/components/Conversation.tsx
similarity index 100%
rename from frontend-s2s/src/components/Conversation.tsx
rename to s2s-frontend/src/components/Conversation.tsx
diff --git a/frontend-s2s/src/components/Dialog.tsx b/s2s-frontend/src/components/Dialog.tsx
similarity index 100%
rename from frontend-s2s/src/components/Dialog.tsx
rename to s2s-frontend/src/components/Dialog.tsx
diff --git a/frontend-s2s/src/components/SettingsDialogs.tsx b/s2s-frontend/src/components/SettingsDialogs.tsx
similarity index 100%
rename from frontend-s2s/src/components/SettingsDialogs.tsx
rename to s2s-frontend/src/components/SettingsDialogs.tsx
diff --git a/frontend-s2s/src/components/VoiceStage.tsx b/s2s-frontend/src/components/VoiceStage.tsx
similarity index 100%
rename from frontend-s2s/src/components/VoiceStage.tsx
rename to s2s-frontend/src/components/VoiceStage.tsx
diff --git a/frontend-s2s/src/hooks/use-wake-word.ts b/s2s-frontend/src/hooks/use-wake-word.ts
similarity index 100%
rename from frontend-s2s/src/hooks/use-wake-word.ts
rename to s2s-frontend/src/hooks/use-wake-word.ts
diff --git a/frontend-s2s/src/lib/api.ts b/s2s-frontend/src/lib/api.ts
similarity index 100%
rename from frontend-s2s/src/lib/api.ts
rename to s2s-frontend/src/lib/api.ts
diff --git a/frontend-s2s/src/lib/context.ts b/s2s-frontend/src/lib/context.ts
similarity index 100%
rename from frontend-s2s/src/lib/context.ts
rename to s2s-frontend/src/lib/context.ts
diff --git a/frontend-s2s/src/lib/contracts.ts b/s2s-frontend/src/lib/contracts.ts
similarity index 100%
rename from frontend-s2s/src/lib/contracts.ts
rename to s2s-frontend/src/lib/contracts.ts
diff --git a/frontend-s2s/src/lib/messages.test.ts b/s2s-frontend/src/lib/messages.test.ts
similarity index 100%
rename from frontend-s2s/src/lib/messages.test.ts
rename to s2s-frontend/src/lib/messages.test.ts
diff --git a/frontend-s2s/src/lib/messages.ts b/s2s-frontend/src/lib/messages.ts
similarity index 100%
rename from frontend-s2s/src/lib/messages.ts
rename to s2s-frontend/src/lib/messages.ts
diff --git a/frontend-s2s/src/lib/profile.ts b/s2s-frontend/src/lib/profile.ts
similarity index 100%
rename from frontend-s2s/src/lib/profile.ts
rename to s2s-frontend/src/lib/profile.ts
diff --git a/frontend-s2s/src/lib/reports.ts b/s2s-frontend/src/lib/reports.ts
similarity index 100%
rename from frontend-s2s/src/lib/reports.ts
rename to s2s-frontend/src/lib/reports.ts
diff --git a/frontend-s2s/src/lib/settings.ts b/s2s-frontend/src/lib/settings.ts
similarity index 100%
rename from frontend-s2s/src/lib/settings.ts
rename to s2s-frontend/src/lib/settings.ts
diff --git a/frontend-s2s/src/main.tsx b/s2s-frontend/src/main.tsx
similarity index 100%
rename from frontend-s2s/src/main.tsx
rename to s2s-frontend/src/main.tsx
diff --git a/frontend-s2s/src/realtime/client.test.ts b/s2s-frontend/src/realtime/client.test.ts
similarity index 100%
rename from frontend-s2s/src/realtime/client.test.ts
rename to s2s-frontend/src/realtime/client.test.ts
diff --git a/frontend-s2s/src/realtime/client.ts b/s2s-frontend/src/realtime/client.ts
similarity index 100%
rename from frontend-s2s/src/realtime/client.ts
rename to s2s-frontend/src/realtime/client.ts
diff --git a/frontend-s2s/src/realtime/controller.test.ts b/s2s-frontend/src/realtime/controller.test.ts
similarity index 100%
rename from frontend-s2s/src/realtime/controller.test.ts
rename to s2s-frontend/src/realtime/controller.test.ts
diff --git a/frontend-s2s/src/realtime/controller.ts b/s2s-frontend/src/realtime/controller.ts
similarity index 100%
rename from frontend-s2s/src/realtime/controller.ts
rename to s2s-frontend/src/realtime/controller.ts
diff --git a/frontend-s2s/src/styles.css b/s2s-frontend/src/styles.css
similarity index 100%
rename from frontend-s2s/src/styles.css
rename to s2s-frontend/src/styles.css
diff --git a/frontend-s2s/src/styles/legacy-theme.css b/s2s-frontend/src/styles/legacy-theme.css
similarity index 100%
rename from frontend-s2s/src/styles/legacy-theme.css
rename to s2s-frontend/src/styles/legacy-theme.css
diff --git a/frontend-s2s/src/test/backend-proxy.test.ts b/s2s-frontend/src/test/backend-proxy.test.ts
similarity index 100%
rename from frontend-s2s/src/test/backend-proxy.test.ts
rename to s2s-frontend/src/test/backend-proxy.test.ts
diff --git a/frontend-s2s/src/test/setup.ts b/s2s-frontend/src/test/setup.ts
similarity index 100%
rename from frontend-s2s/src/test/setup.ts
rename to s2s-frontend/src/test/setup.ts
diff --git a/frontend-s2s/tsconfig.app.json b/s2s-frontend/tsconfig.app.json
similarity index 100%
rename from frontend-s2s/tsconfig.app.json
rename to s2s-frontend/tsconfig.app.json
diff --git a/frontend-s2s/tsconfig.json b/s2s-frontend/tsconfig.json
similarity index 100%
rename from frontend-s2s/tsconfig.json
rename to s2s-frontend/tsconfig.json
diff --git a/frontend-s2s/tsconfig.node.json b/s2s-frontend/tsconfig.node.json
similarity index 100%
rename from frontend-s2s/tsconfig.node.json
rename to s2s-frontend/tsconfig.node.json
diff --git a/frontend-s2s/vite.config.ts b/s2s-frontend/vite.config.ts
similarity index 100%
rename from frontend-s2s/vite.config.ts
rename to s2s-frontend/vite.config.ts
diff --git a/frontend-s2s/vitest.config.ts b/s2s-frontend/vitest.config.ts
similarity index 100%
rename from frontend-s2s/vitest.config.ts
rename to s2s-frontend/vitest.config.ts
diff --git a/start_ui.sh b/start_ui.sh
index 8381a5d..d2ea824 100755
--- a/start_ui.sh
+++ b/start_ui.sh
@@ -4,7 +4,7 @@ set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VENV_DIR="$ROOT_DIR/.venv"
REQ_FILE="$ROOT_DIR/s2s-client/requirements.txt"
-FRONTEND_DIR="$ROOT_DIR/frontend-s2s"
+FRONTEND_DIR="$ROOT_DIR/s2s-frontend"
if [ -f "$ROOT_DIR/.env" ]; then
set -a
source "$ROOT_DIR/.env"
@@ -28,7 +28,7 @@ for required_command in python3 node npm setsid curl; do
done
if ! node -e 'const [major, minor] = process.versions.node.split(".").map(Number); process.exit((major === 22 && minor >= 18) || major >= 24 ? 0 : 1)'; then
- echo "Error: frontend-s2s requires Node.js 22.18+ on the 22.x line, or Node.js 24+."
+ echo "Error: s2s-frontend requires Node.js 22.18+ on the 22.x line, or Node.js 24+."
exit 1
fi
@@ -67,7 +67,7 @@ fi
if [ ! -f "$FRONTEND_DIR/node_modules/vite/bin/vite.js" ] || \
! cmp -s "$FRONTEND_DIR/package-lock.json" "$FRONTEND_DIR/node_modules/.s2s-package-lock.json" || \
! cmp -s "$FRONTEND_DIR/package.json" "$FRONTEND_DIR/node_modules/.s2s-package.json"; then
- echo "Installing frontend dependencies from frontend-s2s/package-lock.json..."
+ echo "Installing frontend dependencies from s2s-frontend/package-lock.json..."
npm --prefix "$FRONTEND_DIR" ci --include=dev
cp "$FRONTEND_DIR/package-lock.json" "$FRONTEND_DIR/node_modules/.s2s-package-lock.json"
cp "$FRONTEND_DIR/package.json" "$FRONTEND_DIR/node_modules/.s2s-package.json"