From 579a2ca49e0731862e4c92df2d87278321ad2428 Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Mon, 16 Feb 2026 12:49:30 +0100 Subject: [PATCH 1/4] Update readme and env examples --- deep-sea-stories/.env.example | 2 +- deep-sea-stories/README.md | 76 ++++++++++++++++++- deep-sea-stories/docker-compose.yml | 3 - .../packages/backend/.env.example | 1 - .../packages/backend/package.json | 1 - .../packages/backend/src/config.ts | 1 - .../packages/backend/tests/config.test.ts | 11 --- deep-sea-stories/yarn.lock | 59 +------------- 8 files changed, 77 insertions(+), 77 deletions(-) diff --git a/deep-sea-stories/.env.example b/deep-sea-stories/.env.example index 8b62bef..fbdbaed 100644 --- a/deep-sea-stories/.env.example +++ b/deep-sea-stories/.env.example @@ -1,3 +1,3 @@ FISHJAM_ID= FISHJAM_MANAGEMENT_TOKEN= -ELEVENLABS_API_KEY= +GEMINI_API_KEY= diff --git a/deep-sea-stories/README.md b/deep-sea-stories/README.md index cf21f1a..1d8f2ca 100644 --- a/deep-sea-stories/README.md +++ b/deep-sea-stories/README.md @@ -1 +1,75 @@ -# Deep Sea Stories Example App +# Deep Sea Stories + +Deep Sea Stories is a real-time, audio-driven game where players solve mysteries with the help of an AI riddle master. + +## Running Locally + +Before running locally, make sure to copy `.env.example` to `.env` and set the following values: + +```bash +FISHJAM_ID=... +FISHJAM_MANAGEMENT_TOKEN=... +GEMINI_API_KEY=... +``` + +- You can get `FISHJAM_ID` and `FISHJAM_MANAGEMENT_TOKEN` for free by logging in at . +- You can generate `GEMINI_API_KEY` for free at . + +### Docker Compose (Recommended) + +The easiest way to run the app is with [Docker Compose](https://docs.docker.com/compose/install/). + +```bash +docker compose up --build +``` + +You can then access the UI at + +### Running Manually + +If you can't use [docker compose](#docker-compose-recommended) to run the project, then you can follow the following steps to run the demo. + +### Requirements +- [Node.js](https://nodejs.org/en/download) `>= 24` +- Yarn `4.9.2` (via [Corepack](https://github.com/nodejs/corepack)) + +1. Install dependencies from the repo root: + ```bash + corepack enable + yarn install + ``` +2. Configure environment variables: + - Backend (`packages/backend/.env`): + ```bash + FISHJAM_ID="your-fishjam-id" + FISHJAM_MANAGEMENT_TOKEN="your-management-token" + GEMINI_API_KEY="your-gemini-api-key" + ``` + - Web (`packages/web/.env` or `packages/web/.env.local`): + ```bash + VITE_FISHJAM_ID="your-fishjam-id" + VITE_BACKEND_URL="http://localhost:8000/api/v1" + ``` +3. Start the backend (from repo root): + ```bash + yarn workspace @deep-sea-stories/backend start + ``` +4. Start the web client in another terminal (from repo root): + ```bash + yarn workspace @deep-sea-stories/web start + ``` +5. Open the UI at . + +## Repo Structure + +- `packages/backend`: Fishjam Agent which talks with Goople Gemini Live API. +- `packages/web`: Web client, which connects to the backend and Fishjam in the browser. +- `packages/common`: Shared TypeScript types and utilities. +- `docker-compose.yml` + `nginx.conf`: Container setup with a reverse proxy. + +### Tech Stack + +- Yarn workspaces monorepo with Fastify + tRPC (backend), React + Vite (frontend). +- [Fishjam](https://fishjam.swmansion.com) for real-time videoconferencing capabilities. +- [Gemini Live API](https://ai.google.dev/gemini-api/docs/live) for AI riddle master backend. + diff --git a/deep-sea-stories/docker-compose.yml b/deep-sea-stories/docker-compose.yml index fcbbbc7..89ec977 100644 --- a/deep-sea-stories/docker-compose.yml +++ b/deep-sea-stories/docker-compose.yml @@ -10,7 +10,6 @@ services: - PORT=8000 - FISHJAM_ID=${FISHJAM_ID} - FISHJAM_MANAGEMENT_TOKEN=${FISHJAM_MANAGEMENT_TOKEN} - - ELEVENLABS_API_KEY=${ELEVENLABS_API_KEY} - GEMINI_API_KEY=${GEMINI_API_KEY} restart: unless-stopped @@ -21,8 +20,6 @@ services: args: - VITE_FISHJAM_ID=${FISHJAM_ID} - VITE_BACKEND_URL=${BACKEND_URL:-/api/v1} - environment: - - VITE_BACKEND_URL=/api/v1 restart: unless-stopped depends_on: - backend diff --git a/deep-sea-stories/packages/backend/.env.example b/deep-sea-stories/packages/backend/.env.example index 124fb5e..3aa6214 100644 --- a/deep-sea-stories/packages/backend/.env.example +++ b/deep-sea-stories/packages/backend/.env.example @@ -1,4 +1,3 @@ FISHJAM_ID="your-fishjam-id" FISHJAM_MANAGEMENT_TOKEN="your-management-token" -ELEVENLABS_API_KEY="your-elevenlabs-api-key" GEMINI_API_KEY="your-gemini-api-key" diff --git a/deep-sea-stories/packages/backend/package.json b/deep-sea-stories/packages/backend/package.json index 99aa485..6524b7f 100644 --- a/deep-sea-stories/packages/backend/package.json +++ b/deep-sea-stories/packages/backend/package.json @@ -12,7 +12,6 @@ "types": "./src/index.ts", "dependencies": { "@deep-sea-stories/common": "workspace:*", - "@elevenlabs/elevenlabs-js": "^2.20.0", "@fastify/cors": "^11.1.0", "@fishjam-cloud/js-server-sdk": "^0.22.0", "@google/genai": "^1.30.0", diff --git a/deep-sea-stories/packages/backend/src/config.ts b/deep-sea-stories/packages/backend/src/config.ts index 6989c51..7482781 100644 --- a/deep-sea-stories/packages/backend/src/config.ts +++ b/deep-sea-stories/packages/backend/src/config.ts @@ -15,7 +15,6 @@ export const configSchema = z.object({ PORT: z.coerce.number().int().default(8000), FISHJAM_ID: z.string(), FISHJAM_MANAGEMENT_TOKEN: z.string(), - ELEVENLABS_API_KEY: z.string(), GEMINI_API_KEY: z.string().optional(), GOOGLE_GENAI_USE_VERTEXAI: z .string() diff --git a/deep-sea-stories/packages/backend/tests/config.test.ts b/deep-sea-stories/packages/backend/tests/config.test.ts index 2c6d05e..fb56cf7 100644 --- a/deep-sea-stories/packages/backend/tests/config.test.ts +++ b/deep-sea-stories/packages/backend/tests/config.test.ts @@ -65,19 +65,10 @@ describe('Configuration', () => { }); }, 'Should throw when required FISHJAM_MANAGEMENT_TOKEN is missing'); - assert.throws(() => { - configSchema.parse({ - FISHJAM_ID: 'test-id', - FISHJAM_MANAGEMENT_TOKEN: 'test-token', - GEMINI_API_KEY: 'test-gemini-key', - }); - }, 'Should throw when required ELEVENLABS_API_KEY is missing'); - assert.doesNotThrow(() => { configSchema.parse({ FISHJAM_ID: 'test-id', FISHJAM_MANAGEMENT_TOKEN: 'test-token', - ELEVENLABS_API_KEY: 'test-api-key', GEMINI_API_KEY: 'test-gemini-key', }); }, 'Should not throw with all required fields'); @@ -87,7 +78,6 @@ describe('Configuration', () => { const config = configSchema.parse({ FISHJAM_ID: 'test-id', FISHJAM_MANAGEMENT_TOKEN: 'test-token', - ELEVENLABS_API_KEY: 'test-api-key', GEMINI_API_KEY: 'test-gemini-key', }); @@ -98,7 +88,6 @@ describe('Configuration', () => { const config = configSchema.parse({ FISHJAM_ID: 'test-id', FISHJAM_MANAGEMENT_TOKEN: 'test-token', - ELEVENLABS_API_KEY: 'test-api-key', GEMINI_API_KEY: 'test-gemini-key', PORT: '3000', }); diff --git a/deep-sea-stories/yarn.lock b/deep-sea-stories/yarn.lock index 4605328..3e963fd 100644 --- a/deep-sea-stories/yarn.lock +++ b/deep-sea-stories/yarn.lock @@ -319,7 +319,6 @@ __metadata: resolution: "@deep-sea-stories/backend@workspace:packages/backend" dependencies: "@deep-sea-stories/common": "workspace:*" - "@elevenlabs/elevenlabs-js": "npm:^2.20.0" "@fastify/cors": "npm:^11.1.0" "@fishjam-cloud/js-server-sdk": "npm:^0.22.0" "@google/genai": "npm:^1.30.0" @@ -385,17 +384,6 @@ __metadata: languageName: unknown linkType: soft -"@elevenlabs/elevenlabs-js@npm:^2.20.0": - version: 2.22.0 - resolution: "@elevenlabs/elevenlabs-js@npm:2.22.0" - dependencies: - command-exists: "npm:^1.2.9" - node-fetch: "npm:^2.7.0" - ws: "npm:^8.18.3" - checksum: 10c0/398fcc850b8d9b1735d090fc0579138b54923ac945ec11941d3375c3733857ed37e126db289010f2de039b55f82cbff8f7596f36d049ffa728e86b85b6eb6a6b - languageName: node - linkType: hard - "@emnapi/core@npm:^1.5.0": version: 1.5.0 resolution: "@emnapi/core@npm:1.5.0" @@ -2215,13 +2203,6 @@ __metadata: languageName: node linkType: hard -"command-exists@npm:^1.2.9": - version: 1.2.9 - resolution: "command-exists@npm:1.2.9" - checksum: 10c0/75040240062de46cd6cd43e6b3032a8b0494525c89d3962e280dde665103f8cc304a8b313a5aa541b91da2f5a9af75c5959dc3a77893a2726407a5e9a0234c16 - languageName: node - linkType: hard - "commander@npm:^5.1.0": version: 5.1.0 resolution: "commander@npm:5.1.0" @@ -3521,20 +3502,6 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.7.0": - version: 2.7.0 - resolution: "node-fetch@npm:2.7.0" - dependencies: - whatwg-url: "npm:^5.0.0" - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 - languageName: node - linkType: hard - "node-fetch@npm:^3.3.2": version: 3.3.2 resolution: "node-fetch@npm:3.3.2" @@ -4312,13 +4279,6 @@ __metadata: languageName: node linkType: hard -"tr46@npm:~0.0.3": - version: 0.0.3 - resolution: "tr46@npm:0.0.3" - checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 - languageName: node - linkType: hard - "tslib@npm:^2.0.0, tslib@npm:^2.1.0, tslib@npm:^2.4.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" @@ -4529,23 +4489,6 @@ __metadata: languageName: node linkType: hard -"webidl-conversions@npm:^3.0.0": - version: 3.0.1 - resolution: "webidl-conversions@npm:3.0.1" - checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db - languageName: node - linkType: hard - -"whatwg-url@npm:^5.0.0": - version: 5.0.0 - resolution: "whatwg-url@npm:5.0.0" - dependencies: - tr46: "npm:~0.0.3" - webidl-conversions: "npm:^3.0.0" - checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 - languageName: node - linkType: hard - "which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" @@ -4597,7 +4540,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.18.0, ws@npm:^8.18.3": +"ws@npm:^8.18.0": version: 8.18.3 resolution: "ws@npm:8.18.3" peerDependencies: From 9d206b51eebde60fbfc412c22dd9f3736f2dee6d Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Mon, 16 Feb 2026 12:55:25 +0100 Subject: [PATCH 2/4] Update port --- deep-sea-stories/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deep-sea-stories/README.md b/deep-sea-stories/README.md index 1d8f2ca..a243521 100644 --- a/deep-sea-stories/README.md +++ b/deep-sea-stories/README.md @@ -23,7 +23,7 @@ The easiest way to run the app is with [Docker Compose](https://docs.docker.com/ docker compose up --build ``` -You can then access the UI at +You can then access the UI at ### Running Manually From 373cee5b00a536c69813106bc33c8b179548a6a2 Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Mon, 16 Feb 2026 12:55:43 +0100 Subject: [PATCH 3/4] Fix typo --- deep-sea-stories/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deep-sea-stories/README.md b/deep-sea-stories/README.md index a243521..e0cb9d7 100644 --- a/deep-sea-stories/README.md +++ b/deep-sea-stories/README.md @@ -62,7 +62,7 @@ If you can't use [docker compose](#docker-compose-recommended) to run the projec ## Repo Structure -- `packages/backend`: Fishjam Agent which talks with Goople Gemini Live API. +- `packages/backend`: Fishjam Agent which talks with Google Gemini Live API. - `packages/web`: Web client, which connects to the backend and Fishjam in the browser. - `packages/common`: Shared TypeScript types and utilities. - `docker-compose.yml` + `nginx.conf`: Container setup with a reverse proxy. From 1e06e1b5f4c0015bba1365d211b7db6ff0cb56ba Mon Sep 17 00:00:00 2001 From: Tomasz Mazur <47872060+AHGIJMKLKKZNPJKQR@users.noreply.github.com> Date: Mon, 16 Feb 2026 13:00:33 +0100 Subject: [PATCH 4/4] Update README.md --- deep-sea-stories/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deep-sea-stories/README.md b/deep-sea-stories/README.md index e0cb9d7..66b94b4 100644 --- a/deep-sea-stories/README.md +++ b/deep-sea-stories/README.md @@ -2,6 +2,10 @@ Deep Sea Stories is a real-time, audio-driven game where players solve mysteries with the help of an AI riddle master. +https://github.com/user-attachments/assets/a88f872e-f707-4014-8855-0a55375ce998 + +Check out our [blog post](https://fishjam.swmansion.com/blog/voice-ai-how-we-built-a-multi-speaker-ai-agent-using-gemini) to learn more! + ## Running Locally Before running locally, make sure to copy `.env.example` to `.env` and set the following values: