AI Agents Workshop with Yuval KeshtcherLearn about upcoming cohorts →
AI Makers Lab

Build a Loom Clone with Claude Code

0/7
All tutorials
Productivity
Beginner
20 minutes
7 milestones

Build a Loom Clone with Claude Code

What you'll build

A fully working screen recorder with webcam overlay, audio mixing, pause/resume, countdown, and floating PiP controller — in one HTML file.

Milestone 0 of 70% complete

What You're Building

A local Loom alternative. Record your screen, window, or browser tab. Add your webcam as a circular overlay. Mix mic and system audio. Pause and resume. Preview and download as WebM. Everything runs in the browser — no server, no upload, no dependencies. Just one HTML file built in 7 prompts.


Milestone 1: Record Your Screen in 20 Lines

The simplest possible screen recorder. One button. Click, pick a screen, stop, download.

Prompt:

Prompt
Create a single index.html file that records the user's screen. When they click "Start Recording", use getDisplayMedia to capture the screen, record it with MediaRecorder as WebM, and when they click "Stop", download the recording. Dark background, minimal UI. No frameworks.

What Claude Code does: It wires up the core recording pipeline — getDisplayMedia() captures the screen as a MediaStream, MediaRecorder encodes it into WebM chunks, and a Blob assembles the chunks into a downloadable file.

Try it: Open index.html in Chrome. Click Start, pick your screen, record for a few seconds, click Stop. A .webm file downloads. Play it.


Milestone 2: Make It Look Like an App

Working prototype, but it looks like a homework assignment. Time for a real setup screen.

Prompt:

Redesign the setup screen. Add three source options the user can click: Screen, Window, and Browser Tab (use getDisplayMedia's displaySurface option). Add toggle cards for Webcam and Microphone. Style it with a dark theme, purple accent color #625df5, rounded cards, and a prominent Start Recording button. Make the selected options visually highlighted.

What Claude Code does: It builds a selection UI and maps each option to getDisplayMedia() configuration. The displaySurface property hints to the browser whether to prioritize screens, windows, or tabs in the picker. The toggles track state for later milestones.

Try it: Open the file. Polished dark setup screen with clickable cards. Click between Screen/Window/Tab — active state highlights. Start Recording still works.


Milestone 3: Add Microphone + Mix Audio

The recording captures system audio only. Your voice is missing. Screen audio and mic audio are two separate streams — they need to be merged.

Prompt:

When the Microphone toggle is active, capture mic audio using getUserMedia. Mix the mic audio and system audio together using the Web Audio API (AudioContext + createMediaStreamDestination) so both play in the recording. If mic isn't available, gracefully fall back to system audio only.

What Claude Code does: getUserMedia({ audio: true }) captures the mic. An AudioContext acts like a sound mixer board — both audio sources connect to createMediaStreamDestination(), merging into one output stream.

Try it: Toggle Microphone on, start recording, talk while something plays on screen. Stop, play back — you hear both your voice and system audio.


Milestone 4: Recording Controls

Your recorder works but feels blind — no timer, no way to pause.

Prompt:

Prompt
Add a recording control bar at the bottom center of the screen during recording. Include: a pulsing red dot that animates while recording, a live timer showing minutes:seconds, a pause/resume button (use MediaRecorder.pause/resume), and a red stop button. The bar should have a blurred dark background. When paused, the dot turns amber and stops pulsing.

What Claude Code does: A floating control bar connects to MediaRecorder's state API.pause() suspends encoding without losing data, .resume() picks up where it left off. The timer respects paused state.

Try it: Start recording. Control bar appears: pulsing red dot, live timer. Pause — dot turns amber, timer freezes. Resume — picks up. Stop — done.


Milestone 5: Countdown + Completion Screen

Recordings start abruptly. A countdown gives you time to prepare. And you want to preview before downloading.

Prompt:

Prompt
Add a 3-second countdown overlay (3, 2, 1) with a large animated number before recording starts. After recording stops, show a completion screen with a video player to preview the recording and two buttons: Download and New Recording. The download should name the file with a timestamp. New Recording resets back to the setup screen.

What Claude Code does: The countdown uses a Promise-based timer — recording waits for it to finish. The completion screen creates a Blob URL with URL.createObjectURL() for instant in-browser playback. No upload needed.

Try it: Start recording — big 3, 2, 1 animation. Record, stop. Completion screen with video playback. Download gives a timestamped .webm. New Recording resets everything.


Milestone 6: Webcam Overlay

The biggest milestone — the signature Loom feature. Your face in a circle, baked into the recording.

Prompt:

When the Webcam toggle is active, capture the camera with getUserMedia and show a circular preview bubble in the bottom-left corner. Make the bubble draggable. For the actual recording, use canvas compositing: draw the screen and webcam onto a hidden canvas at 20fps, then record the canvas stream instead. When webcam is off, skip the canvas entirely for better performance. Cap resolution at 1080p.

What Claude Code does: Canvas compositing — a hidden <canvas> where screen and webcam are painted every frame with drawImage(). The canvas output is captured with canvas.captureStream() and fed to MediaRecorder. Performance tricks: skip canvas when no webcam, throttle to 20fps, desynchronized GPU mode, 1080p cap.

Try it: Toggle Webcam on, start recording. Circular face-cam bubble appears. Record, stop, play back — your face is baked into the video. Drag the bubble during recording.


Milestone 7: Picture-in-Picture Controller

When recording, the recorder tab is hidden. You need controls that float above everything.

Prompt:

After recording starts, open a Picture-in-Picture floating mini-window using documentPictureInPicture.requestWindow(). The mini-window should show the timer, a pulsing recording dot, and pause/stop buttons. Keep it synced with the main controls. Fall back gracefully if PiP isn't supported.

What Claude Code does: The Document Picture-in-Picture API opens a tiny always-on-top window where you inject custom HTML. It syncs timer and controls with the main page.

Try it: Start recording. Floating mini-window appears with timer and controls. Switch apps — PiP stays on top. Pause/stop from the floating window works. (Chrome 116+ only. Other browsers still record fine without the floating controller.)


What You Built

A complete Loom-like screen recorder in one HTML file:

  • Screen, window, or tab capture
  • Webcam circle overlay (draggable)
  • Mic + system audio mixing
  • Pause/resume
  • 3-second countdown
  • Floating PiP controller
  • Local download as WebM

All browser-native. No server. No upload. No dependencies.

Three APIs did the heavy lifting: getDisplayMedia() for the screen, getUserMedia() for webcam/mic, MediaRecorder to encode it all. The Web Audio API mixed the audio. Canvas compositing merged the video. Seven prompts to Claude Code.

Take It Further

  • Add MP4 export — use FFmpeg.wasm to convert WebM to MP4 in the browser
  • Add a drawing toolbar — annotate your screen during recording
  • Add keyboard shortcuts — start/stop/pause with hotkeys

Ready to build your first AI agent?

Live Zoom workshop + 1 month WhatsApp follow-up with Yuval Keshtcher (Hebrew)

Learn about the Workshop