Back to blog

Building a ⌘K Command Palette (and a Fake Terminal) for My Portfolio

By Amine Amine

reactuxnextjs

Press ⌘K (or Ctrl+K) anywhere on this site and you get a search box that jumps to any page, case study, game, blog post or Dota 2 hero. Press ~ and you get a terminal. Neither is essential. Both are the kind of detail that makes a developer's site feel like it was made by a developer.

Here's how they're built, and the few decisions that kept them simple.

Logic first, UI second

Both features are mostly logic, so I wrote the logic as pure functions with no React involved:

  • buildItems(posts, heroes, work) returns a flat list of { group, label, url, keywords };
  • filterItems(items, query) ranks them;
  • runCommand(input) returns { lines, action } for the terminal, where action is "navigate", "clear" or "exit";
  • complete(input) does tab completion.

The React components only render state and call these. That made them trivial to smoke-test: "typing wraith ranks Wraith King first", "cd blog/ goes to the blog", "c + Tab doesn't complete, because it's ambiguous".

Ranking without a fuzzy-search library

Fuzzy matching libraries are great, but for a hundred or so items a tiny score does the job. For each word you type:

  • a match at the start of the label scores 0 (best);
  • a match at the start of any word in the label scores 1;
  • a match anywhere in the label scores 2;
  • a match in the group or keywords scores 3;
  • no match anywhere, and the item is out.

Then sort by score, keeping the original order for ties. Keywords do the quiet work: "resume" finds the Experience section, and "hire" finds the contact page.

Don't load what nobody asked for

Dota has 120+ heroes, and putting all of them in every page's HTML would be wasteful. The palette fetches hero names the first time someone opens it, from an endpoint that's already cached for an hour. When the palette is empty, heroes stay hidden so the list starts with pages, not a wall of hero names.

The terminal

It's a switch statement with personality. help, whoami, ls projects, cat resume, cd contact and play chess all do something real. sudo tells you that simplicity is not negotiable, and vim reassures you that exit works here. Arrow keys walk your history, Tab completes, and Ctrl+L clears.

It uses the site's dark theme tokens, so it looks right without any one-off colours.

Respecting the person typing

I record anonymous usage events to see whether people actually use this. For the terminal, I only store the command word, and only if it's a command I know. Anything else is recorded as other. If someone types a sentence into a fake shell, it stays in their browser.

Try it

Press ⌘K and type chess, or press ~ and type help. If you find a command I should add, tell me.

Building a ⌘K Command Palette (and a Fake Terminal) for My Portfolio | SimpleCode by Amine Amine