SoloMock
I built a mock-interview workspace that connects spoken reasoning with the candidate’s code.
- My role
- Independent developer
- Context
- Independent product · Realtime voice and code · 2025–present
Next.js · TypeScript · OpenAI Realtime API · WebRTC · Monaco · Tailwind CSS

- Problem
- Interview practice needs the candidate’s spoken explanation and changing code in the same context.
- Decision
- Send editor snapshots after a 2.5-second pause, skip unchanged code, and clean up session resources when an interview ends.
- Verified behavior
- A mocked connection failure stopped the audio track, closed the peer, and retained the code and transcript for review.
Give the interviewer the code context
Practicing a coding interview means explaining an approach while writing and revising code. A voice-only interviewer misses those changes; a text-only workflow loses the spoken explanation. SoloMock places a Monaco editor beside the problem and transcript, and sends editor snapshots through the same WebRTC connection used for the conversation.
The example shows a candidate explaining a hash-map solution to Two Sum, including why a lookup happens before insertion. Keeping the solution and transcript together lets the candidate review both the implementation and the reasoning used to explain it.
Send useful changes, not every keystroke
The editor waits for a pause before sending a snapshot and skips unchanged code. The current implementation uses a 2.5-second debounce. This reduces repetitive context updates while still letting a revised solution enter the conversation. The tradeoff is deliberate delay: this mechanism is not a promise that the model sees each keystroke immediately.
Problem content is structured separately from the transport. Interviewer briefs hold solution approaches, hint ladders, follow-ups, and edge cases; the browser receives the candidate-facing problem. That gives the interview a consistent source of context while keeping the editor and WebRTC code focused on interaction.
Treat the session as a lifecycle
The browser requests microphone access before asking the server for a temporary credential. The long-lived provider key remains on the server. Once connected, the client manages the audio tracks, data channel, countdown, and transcript. Explicit stop, timeout, and lost connection all lead into cleanup instead of leaving an apparently active interview behind.
There are important limits to these safeguards. The duration timer runs in the client. Rate limiting uses a shared Redis service when configured, but falls back to per-instance memory when that service is unavailable. These controls reduce exposure; they do not establish an unbypassable session boundary or a hard total spending cap.
Make a lost connection understandable
A connection can fail after the user has already invested time in an answer. The interface ends the session, explains that the connection was lost, and offers a way to start again. It retains the transcript and code so the user can still review the work and request post-session feedback.
In a controlled connection-loss check, changing a mocked WebRTC peer to failed triggered the cleanup path: the audio track stopped, the peer closed, and the error appeared. The feedback component then accepted a simulated response while keeping the interview work available for review.

What the checks establish
Local tests cover the problem-brief structure, rate-limiter behavior, and session-route response. The browser demonstration also exercised editor snapshot delivery and cleanup through substituted dependencies. These checks concentrate on the boundaries that connect the interface, transport, and server.
The next evaluation should focus on the interviewer itself: a declared set of practice sessions, consistent assessment criteria, and observed response behavior. Application correctness and useful coaching are different questions. The session and feedback structure gives that evaluation a repeatable starting point.
Screenshots use the deployed UI with sample code, transcripts, and simulated media and provider responses. Connection cleanup was checked with mocks; no paid session was started. Captured September 5, 2026.