The Terminal Is Real

javascriptterminalfrontend

The Terminal Is Real

When people open the terminal on my portfolio, most of them type help and browse for a bit. Some try ls and cat. A few try rm -rf / because of course they do. But the terminal is doing more than it looks like at first glance.

Two Modes

The terminal starts in what I call restricted mode. You type a command, it sends a POST request to the server, and the response comes back. Simple and stateless. No session, no history, no working directory. Every command stands on its own.

This is fine for casual browsing. You can read about projects, check the blog, run neofetch, get a response. Most visitors never need more than this, and keeping it simple means the terminal works immediately — no connection setup, no handshake, no loading state.

But there's a second mode. A persistent mode with a real session, a working directory you can navigate, command history you can arrow through, and environment variables you can set. It runs over a WebSocket connection and the server tracks your state between commands.

The jump between modes isn't automatic. You have to find it.

The Frontend

The terminal is vanilla JavaScript. No library, no framework, no terminal emulator package. It's an input field, a div for output, and event handlers for key presses.

Arrow up and down cycle through command history. The prompt updates to show your current directory. Output gets appended as HTML divs — green for success, red for errors, grey for secondary info. It scrolls to the bottom after each response.

Tab completion would be the obvious next step, but I haven't added it yet. The command set is small enough that help covers it.

The whole rendering function is about ten lines. It returns a template string with an output container and an input line. Everything else happens in the event handlers.

The Upgrade

When you find your way to the persistent session, the terminal puts on a show. There's a progress bar that fills up character by character. Boot messages scroll by — mounting the virtual filesystem, loading projects and blog posts, establishing the session. The terminal background flashes briefly. Then your prompt changes to show you're connected.

It's theatrical and completely unnecessary from a technical standpoint. The WebSocket connection takes milliseconds. But terminals are theatrical by nature. The boot sequence makes it feel like something real just happened, because something real did just happen — you went from a stateless HTTP endpoint to a persistent server session.

If the WebSocket drops, you fall back to restricted mode. If you close the window, the session cleans up. The whole thing is designed to degrade gracefully. You always have a working terminal, the question is just how much of one.

Why Bother

A portfolio could just be a list of projects and a contact form. But I wanted visitors to interact with something that demonstrates what I can build. The terminal is a working client-server application embedded in a webpage. It handles input, manages state, communicates over two different protocols, and renders output in real time.

Most people will type a few commands and move on. That's fine. But for the ones who dig a little deeper, there's more to find. The restricted mode message isn't just flavor text. It's an invitation.