← All experiments

This site · Live

How this site learned to talk.

The voice assistant on this page is the smallest complete version of the thing I keep building: a system that answers from a governed set of facts, refuses what it should refuse, and keeps a human in charge of what it knows. Seven files do the whole job. Here they are.

Stack
Vanilla JS, PHP, WebRTC
Model
OpenAI Realtime
Build step
None
Try it

The seven files

Pick one to read it. Snippets are trimmed to the part that matters, and nothing here is secret: the API key never appears in anything the browser can reach.

What to notice

    What happens when you tap the character

    1. It asks before it listens

      The first time in a tab, a speech bubble says it will use your microphone and that transcripts may be saved. Nothing starts until you say yes, and then the browser asks for the microphone itself. If that is refused, the bubble says so plainly rather than failing silently.

    2. It requests a short-lived token

      The page posts to a small PHP endpoint, which mints a Realtime client secret that expires in ten minutes.

    3. The real key stays on the server

      It lives in a file above the web root and is never sent to the browser. The browser only ever holds the temporary secret.

    4. A WebRTC call opens directly to OpenAI

      Audio streams both ways while Realtime events update the visible transcript.

    Where the answers come from

    1. Raw notes stay out of the public folder

      Messy source material goes in a gitignored directory. Nothing loads from it.

    2. Curated files hold short, public-safe facts

      Identity, opinions, resume, boundaries. Written by hand, in third person so the assistant cannot slip into speaking as me.

    3. PHP composes them into one prompt

      A single context string, kept short because spoken answers get long fast.

    4. The assistant answers from that, and refuses the rest

      Nine written rules cover impersonation, family, location precision, client work, and high-stakes topics.

    Why this is here rather than in a case study. It is small, it is entirely mine, and you can test every claim on this page by talking to it. Most of what I build has to be described at arm's length because it belongs to a client. This one does not.

    ← All experiments