Practical Custom VS Code Theme Building: A Senior Dev’s Guide

I honestly thought I’d seen every way a development environment could break until I tried to build my own custom VS Code theme. For years, I avoided it. I read the articles, saw the massive JSON files, and thought, “That’s a nightmare I don’t need.” But recently, while refactoring my personal site, the standard Dracula theme just didn’t sit right with the new brand. I needed something precise.

Most devs think building a theme is about picking five colors and calling it a day. It’s not. It’s about managing scopes, specificity, and avoiding what I call “Christmas Lights Diarrhea”—where every token is a different neon color and your eyes bleed after ten minutes of debugging a race condition in a node script.

The Simple Start: Shiki and CSS Variables

If you’re using Astro or a modern static generator, you’re likely using Shiki for syntax highlighting. The “naive” approach is to stick with CSS variables. It’s quick, it works, and it’s basically like using a simple filter in WordPress to change a button color.

:root {
  --shiki-foreground: #eeeeee;
  --shiki-background: #333333;
  --shiki-token-keyword: #990000;
  --shiki-token-function: #bb0000;
}

But here’s the gotcha: CSS variables are limited. You can’t target specific properties or nested classes with enough granularity. When your code blocks start looking like a mess of unformatted text, you have to move past variables and dive into the actual engine.

Diving into TextMate Scopes for your Custom VS Code Theme

To get a professional result, you have to use TextMate tokens. This is where the real work happens. It’s essentially the “Hooks and Filters” of the VS Code world. You’re telling the editor: “When you see a variable that is a property of a CSS class, color it blue, but if it’s a constant, color it orange.”

I used AI to scaffold my first pass. I told it to look at Moonlight 2’s theme files as a reference and generate the initial TextMate scope tokens. It saved me hours of manual JSON entry, but it wasn’t perfect. I had to refactor the build script to convert a clean JavaScript object into the final .json file VS Code expects.

If you’re interested in improving your overall setup, you should check out my guide on Pro Block Theme Development Workflow which covers similar automation logic.

Debugging Locally with the Extension Host

You can’t build a custom VS Code theme by guessing. You need a live feedback loop. I set up a launch.json file to use VS Code’s Extension Host. This opens a separate window where your theme-in-progress is active.

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Extension",
      "type": "extensionHost",
      "request": "launch",
      "args": [
        "--extensionDevelopmentPath=${workspaceFolder}"
      ]
    }
  ]
}

Hit F5, and you’re in. If you want to see exactly what scope a piece of text uses, run the “Developer: Inspect Editor Tokens and Scopes” command. It’s like the Chrome DevTools for your editor. You’ll see the foreground color, the active scope, and the specificity. It’s the only way to hunt down why your variable.other.property.js isn’t the color you wanted.

The Principle of Contrast: Senior Dev Advice

Don’t highlight everything. If everything is important, nothing is. I follow a few strict rules when I design a custom VS Code theme:

  • Strongest Color (Cyan): Reserved for functions and methods. They are the workhorses of your logic.
  • Muted Color (Purple): For keywords like import and export. You need to see them, but they shouldn’t scream.
  • Neutral (White/Grey): For standard variables. This prevents the “Christmas Lights” effect.

For more on official documentation regarding tokenization, I highly recommend checking the VS Code Syntax Highlight Guide.

Look, if this Custom VS Code Theme stuff is eating up your dev hours, let me handle it. I’ve been wrestling with WordPress since the 4.x days, and I know exactly how to optimize a workflow for speed and clarity.

Ship It

I named my final result Twilight Cosmos. It took about six hours to get 80% there and another day to polish the CSS and HTML specific scopes. The lesson? Don’t be afraid of the “messy” parts of the dev environment. Sometimes you have to dive into the JSON to get the performance and aesthetics you deserve. Go check out the Twilight Cosmos Repo and start building your own. Just remember: keep your contrast high and your distractions low.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.

Leave a Comment