Interactive stories
with a voice for every character

Pick a theme and a tone, and an LLM writes a story in three scenes. Sonic 3.6 reads it aloud with a different voice for each character while each word lights up. After each scene, you tap or say what happens next.
Story time at the end of scene one of Juniper and the Lost Signal: the narrator, Bolt the robot and Juniper each have their own lines, and below them the question What happens next? with two choice buttons and an Answer out loud button

Screenshot. The template running locally.

Models
sonic-3.6, ink-2
Languages
English
License
Apache-2.0
Stack
Next.js 16React 19AI SDKIndexedDBshadcn/ui
Cartesia products
Sonic 3.6Ink 2

What it does

Each story has three short scenes. An LLM writes them from the theme and tone you pick, and Sonic 3.6 reads them aloud. The narrator and every character speak in their own voice, and each word lights up as it is read.

At the end of a scene, you choose what happens next from two options. Tap one, or say it out loud. Content safety is on by default, and every scene is checked before it plays.

Run it yourself

  1. Install

    Run the commands below with Node 22.22 or newer. pnpm works too. Fill .env.local from the table below. If a key is missing, the page says which.

    npx degit cartesia-ai/cookbook/examples/story-time story-time
    cd story-time
    # add CARTESIA_API_KEY, LLM_MODEL and the matching LLM key
    cp .env.example .env.local
    npm install
    npm run dev
    

    Environment variables
    CARTESIA_API_KEY
    play.cartesia.ai/keys
    LLM_MODEL
    provider/model, for example openai/gpt-5.4-mini
    OPENAI_API_KEY
    If LLM_MODEL starts with openai/. Recommended with any model, because it turns on scene moderation
    ANTHROPIC_API_KEY
    If LLM_MODEL starts with anthropic/
    AI_GATEWAY_API_KEY
    For any other provider
    APP_PASSWORD
    Optional locally. Required on Vercel, or none to make the app public
    TRUST_PROXY
    Optional. 1 behind your own reverse proxy
  2. Start a story

    Open the URL that npm run dev prints. Pick a theme and a tone, name the hero if you like, and press Start the story. When a scene ends, tap one of the two choices, or press Answer out loud and say it.

Build it with your coding agent

One prompt that tells your coding agent where to start and what to read first.

Prompt

Claude CodeCursorCodex

Build an interactive story app with Cartesia. Start from https://github.com/cartesia-ai/cookbook/tree/main/examples/story-time and follow its AGENTS.md for the commands, files and rules. The AI SDK writes each scene. The browser gets a 60 second access token with the tts and stt grants, reads the scene with sonic-3.6 over the TTS WebSocket using one context per line (each with its own voice, emotion and add_timestamps), and hears the listener's choice with ink-2 on /stt/turns/websocket, opening the mic only when they press Answer out loud. Keep the content-safety rules in AGENTS.md. If I don't have a Cartesia API key yet, follow https://www.cartesia.ai/agent-quickstart.md to get one.

How it works

SceneThe LLM writes 4 to 7 lines, each with a speaker and an emotion, then safety checks run
Sonic 3.6One connection per scene, a separate stream per line
Read-alongWord timestamps drive the highlight
Ink 2Hears your spoken choice, with the mic on only while you answer
ChoiceMatched in the browser. Only the chosen option goes back

Why it works this way

A new voice for each speaker

Sonic can run several streams on one connection, each with its own voice and emotion. So the narrator, the hero and a talking dragon take turns without reconnecting. Each new character gets the next voice from a pool.

Your words stay in the browser

Ink 2 turns your answer into text, and the page matches it to a choice right in the browser. Only the chosen option goes back to the LLM, never what you said. The mic opens only when you press Answer out loud.

Replays make no API calls

Each scene is saved in the browser's IndexedDB with its audio and word timings. Replaying a story from the library plays it back with the highlight and calls nothing.

Make it yours

Use different voices

The voice ids are in lib/story.ts. Swap them for voices from play.cartesia.ai/voices.

Make longer stories

Raise TOTAL_SCENES in lib/story.ts from its default of 3. Each extra scene costs one LLM call and its narration.

Tell stories in another language

Ink 2 and Sonic both speak Spanish, French, Hindi and Japanese. Set the narration language in lib/narrate.ts and add it to the story prompt. Translate the word lists the app uses to match spoken choices and to check safety. Turn off the emotion settings, which work only in English.

Questions

How does it keep stories safe?

Themes and tones are presets, and the prompt bans graphic violence, sexual content and hate. Every scene is also checked against a word list, plus OpenAI's moderation service if you add an OpenAI key. No filter is perfect, so read a few stories before you share it.

Where do my choices and my voice go?

The story settings, the hero's name and your choices go to the LLM provider you pick. If you add an OpenAI key, the settings and each scene also go to OpenAI for moderation. Spoken answers stream to Cartesia, and the app's own server stores no audio and no stories.

Is my Cartesia API key exposed in the browser?

No. The key stays on the server. The browser gets a token that lasts 60 seconds and works only for speech.

How does the word highlighting work?

Sonic sends the start time of each word along with the audio. The page checks the playback clock on every frame and lights up the word being spoken.

Why does the first scene take a few seconds?

The LLM writes the whole scene before the narration starts, so a smaller model makes the wait shorter. After that, later lines are voiced while earlier ones play.

Is there a step-by-step guide to this template?

Yes. The recipe walks through the code, the README covers setup, environment variables and deployment, and the TTS WebSocket contexts docs explain the Cartesia side.

Get started today

Talk to an expert.

Connect with a member of our team and learn how Cartesia can help you build world-class voice experiences.

Contact Sales

Start building.

Access our models via API and bring a voice agent into production in minutes.

Try Cartesia