/building · 2025
TypeScript Coach
next.js · in-browser compiler
ts.coach embeds the real TypeScript compiler in every page, so each code block type-checks, autocompletes, and runs without leaving the browser.

TypeScript tutorials tend to ask you to read a paragraph, write some code on your computer, and come back once it compiles. That round trip is where most beginners quit.
Thanks to TypeScript VFS, I could embed the TypeScript compiler directly in the page, so every code block on
ts.coach gets the same instant type-checking that you would get from an IDE. It uses the same tsc diagnostics to provide autocompletion and highlight compilation errors.
TypeScript compiler in the browser#
The @typescript/vfs package was my favorite discovery while building this project. I started before LLMs were very good, so the core of the site is old-fashioned artisanal hand-crafted code. I'd recommend building it yourself to anyone who wants to understand the TypeScript compiler and how to integrate it into a full development environment.
TypeScript's VFS provides an in-memory filesystem that the TypeScript compiler can operate on in place of a local disk. The language service comes along for free, so you can hover over a variable and get the same quick information as an IDE, with inline errors from the same semantic diagnostics.

The one thing you have to supply is the standard library. A build script
pre-generates the lib.*.d.ts and @types files into static JSON bundles the
page fetches on demand, so the browser gets the type definitions without
downloading a node_modules directory.
I chose CodeMirror 6 because I knew it well and admire Marijn Haverbeke's work, and it held up.
Having the real compiler in the page also changes what a lesson can be. The chapters on mapped and conditional types build a type up a line at a time, and because the checker is live you can break each step yourself and see the diagnostic move.


Executing arbitrary JavaScript in a sandbox#
The JavaScript code generated by the TypeScript compiler is technically considered "unsafe code", i.e. code that a stranger typed into my website. My original plan was to execute that code in a sandboxed cloud environment with a clever containerization strategy, but I realized I could just execute the code directly on the page inside a Web Worker.
The difficulty comes up with managing input and output to the standard functions. In a server-side environment, you can simply pipe stdin and stdout to the process, and build whatever glue is necessary to pipe output to and from the client side. In the browser, I settled on the MessageChannel API to send input and receive output from the Web Worker, with SuperJSON to serialize data types beyond the primitives.
The worker evaluates the code in a scoped function rather than at global scope, and
stdout and stderr are virtual streams piped back to the output panel under
the editor. When something throws, in-memory source maps translate the stack trace back to the line of TypeScript you actually wrote.
The part I didn't expect to build#
Teaching Node in a browser has an obvious problem.
What happens when a lesson about the filesystem runs somewhere with no filesystem?show me →
You write one. node/ in the repo is a set of browser reimplementations of the
Node standard library (fs, path, process, buffer, console, url,
querystring, and a few others), backed by a shared mutable context object that
plays the role of the machine. Reads and writes hit an in-memory tree seeded with
a small sandbox directory, and a change callback lets the page re-render the
filesystem live as your code mutates it. There's a hand-rolled require that
resolves node: prefixes and relative paths against that same virtual tree.

It is the strangest part of the project and the part I'd defend most. Reading
that fs.writeFileSync is synchronous is fine. Watching a file appear in a
directory tree next to the code that created it is a different kind of
understanding, and it costs the reader nothing to get there.
My current roadmap#
I've been working on this project since the early pandemic months, and it will be unfinished for a while longer. That seems like the right shape for a reference.
links