Vercel’s wterm is a sophisticated "back-to-basics" pivot that uses Zig and WebAssembly to restore native browser accessibility through DOM-based rendering. It elegantly proves that modern low-level tools can make the web's original strengths feel revolutionary again.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
wterm: The Ghostty-Powered Web Terminal from VercelAdded:
This is WTerm, a web-based terminal emulator by Vercel that renders directly to the DOM instead of on a canvas. So, text selection, browser find, and screen readers all just work with it. It's written in Zig, compiles to a 12 kilobyte WASM binary, and there's also an optional back end powered by lib ghosty, the same engine that powers the ghosty terminal, which gives you full terminal compatibility in the browser.
But, is a 12 kilobyte WASM binary really enough to replace a native terminal emulator? Probably not, but hit subscribe and let's find out.
So, web terminals are pretty much everywhere in cloud IDEs like GitHub CodeSpaces, infrastructure tools like Portainer or Qualify, and even desktop IDEs like VS Code or Cursor. But, they all use xterm.js to do it because it's been around for a long time, and it's basically the default. xterm has a big problem though. It renders to a canvas element. So, doing something like selecting text or finding words in a page all have to be re-implemented from scratch, which doesn't always work that well. WTerm takes a completely different approach by rendering to the DOM, which means the terminal output is just HTML, and the browser basically handles that for free. But, WTerm can also do some really cool things with this HTML rendering like only re-render the row that has updated instead of re-rendering the whole terminal on each frame. It can also be written in different frameworks like React or Vue. You can change the theme, and there's also a separate WTerm ghosty package which swaps out the Zig core with lib ghosty and works surprisingly better than the other web ghosty project, which we'll talk more about later on in the video. But, for now, let's try out WTerm with a simple demo project. So, after installing WTerm with React, I've imported the component as well as the CSS, and I'm rendering the component over here. So, now if I run the app and then go to the browser, I can see that there is a terminal. But, if I press the command like ls, we can see nothing happens. And this is because it's not connected to another computer to read information from. Let me explain. So, right now the client isn't connected to a back end, so there's no way for it to get information from. But, what we have to do is connect it to another machine, so it could be my local machine or a machine on the cloud, and then render a fake terminal or a pseudo terminal inside that machine with the same dimensions as the one from the client. So, if we do some keystrokes, that keystroke information gets sent to the other machine, which executes those keystrokes, renders the results, and sends all that information back to the client. And that back and forth needs to happen very quickly with minimal delay.
So, the best way to connect the client and the other machine together is to use WebSockets. So, let's go ahead and do that. So, we can use a headless server with Ubuntu I already have set up with Node installed. And I also already have a W term server with a server script.
So, if we look into that, we can see we're creating a WebSocket server on the /api/terminal path. This will make more sense a bit later. And down here, we're spawning a pseudo terminal with a name that matches our terminal type. Here's how you can find yours if you're curious. And down here, we're getting any keystroke from the client, processing it on the server, so inside our fake terminal, and then returning that information to the client over here. So, the server returns everything and not just a specific row that's been updated. Now, over on the client in the app.tsx file, we're making a WebSocket connection to our server on the /api/terminal port. Then we're using the WebSocket transform from W term to connect to that URL with automatic reconnects. Then this is what sends keystroke information from here to the server. We handle the browser resize here. And then down here, and the handle data function handles all the information that comes from the server. And the cool thing about the Zig core is that it will pass this information, figures out what's been changed, and only re-renders that part of the HTML. Down here, the column and row size need to match what we had on the server. And everything else is pretty self-explanatory. So, now with the client and server running, back in the browser, if I press ls, we can see it lists the files we have available.
So, I could press ls with the L flag to see more information about the files. I can CD into a file, take a look at the information inside it, and also do things like see the list of containers I have running. I can even open a file with vim and navigate through it, but even though all of that works, it doesn't do it amazingly well. I mean, if we try to highlight some text, we can see some characters are completely unreadable. So, to fix that, we can set up WTerm with Ghosty by loading Ghosty core and adding it as a prop in React.
You can see now that if we open the server profile and highlight some text, everything is much more readable. It can even do things like render open code correctly, allowing us to change models, and give it a prompt with emoji supports. We can even see that Ghosty renders colors slightly better than with the default WTerm core renderer. But, the Zig core is only 12 kilobytes compared to the 400 kilobytes from Ghosty. So, if you care about size, then maybe stick to the Zig core. Anyway, that's a quick overview of WTerm from Vercel. Of course, there are so many more features I didn't go through, like being able to convert markdown to a nice terminal output, using just Bash to navigate through fake files if you don't have access to a backend, and there are even examples of how to set up an SSH client through a terminal in the browser. But, I didn't find WTerm to be perfect. There were some rendering issues when using the Ghosty version, going back and forth between Neovim or even Open Code. And, to get the Ghosty renderer to work with my Bun frontend, I had to import the WASM file because Bun wouldn't copy any non-JS files from the node_modules folder. But, I do like the DOM rendering approach, which means you do get accessibility and native browser features without doing any extra work, which Xterm has struggled to do, even though it's been around for more than 10 years. But, Xterm.js does have a massive ecosystem and is the battle-tested solution, so you won't go wrong if you do end up choosing it. There's also Ghosty Web by Coda, which takes a different approach. It uses the same lib Ghosty engine used by the actual Ghosty terminal, but it's a drop-in replacement for Xterm. So, it still uses the canvas rendering approach and uses the same API, but you do get a better terminal.
Related Videos
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 views•2026-05-28
How agent o11y differs from traditional o11y — Phil Hetzel, Braintrust
aiDotEngineer
450 views•2026-05-28
Re: 🗣️📍theprophedu📍2026 GST 103 CLASS (E-EXAM REVISION)
theprophedu
636 views•2026-06-04
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanation💯✅
LearnwithSahera
1K views•2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 views•2026-05-29
Search Algorithms Explained in 60 Seconds! 🤖💨
samarthtuliofficial
218 views•2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 views•2026-05-30
Instagram accounts got PWNed
EricParker
13K views•2026-06-03











