All projects
05OPEN SOURCE2026
African Themes Collection emblem — a circular badge with a flame and geometric pattern motif

VS Code Theme Collections

Twenty-five VS Code palettes across two collections — eleven Zimbabwean cities and seven African countries, dark and light.

Two VS Code theme extensions — 25 palettes anchored to Zimbabwean cities and African countries, dark and light, hand-tuned for readability and dual-published to the Marketplace and Open VSX by GitHub Actions.

JavaScript source rendered in a dark purple Zimbabwe theme, showing comment, keyword, string and function colours

Overview

VS Code Theme Collections is a pair of Visual Studio Code colour theme extensions built on one premise: an editor should feel like somewhere rather than nowhere. Instead of abstract palettes, each theme is anchored to a real place and named for it — basalt and spray at the Victoria Falls gorge, jacaranda haze over Harare, warm Bulawayo sandstone, the Namib desert under moonlight, granite drawn from Great Zimbabwe, the Maasai Mara at dusk. Where a country has national colours those are used as seeds rather than as the finished palette: the boldest hue is assigned to keywords, a secondary to strings, and muted slate tones to comments and line numbers, then every colour is pulled toward the landscape the theme is named for so backgrounds carry sand, granite or dusk instead of flat black and white.

The Zimbabwe Theme Collection ships eleven city palettes — six dark and five light — across Harare, Bulawayo, Chitungwiza, Mutare and Victoria Falls. The African Themes Collection ships fourteen, a matched dark and light variant for each of Rwanda, Kenya, Ghana, South Africa, Zimbabwe, Nigeria and Namibia. Twenty-five themes in total, and none of them contain runtime code: every one is a plain JSON document holding a workbench colour map — between twenty-nine and ninety-five keys covering the activity bar, side bar, tabs, status bar, panels, gutter and cursor — alongside TextMate token rules for comments, keywords, strings, functions and types, so chrome and syntax are tuned as one palette rather than drifting apart. Contrast was worked out by hand against real source files rather than generated from seed colours, because generated accents tend to collapse in practice: comments too loud, strings and types too close together, punctuation invisible.

Both extensions share the same distribution pipeline, and it is fully automated. A push to the manifest or the themes directory on the main branch triggers a GitHub Actions workflow that packages the extension into a VSIX on a clean Node 20 runner, reads the version out of the manifest, cuts a GitHub release tagged from that version with generated notes and the package attached, then publishes to the Visual Studio Marketplace through vsce and to Open VSX through ovsx. The second registry matters in practice: Cursor, VSCodium and Gitpod users resolve extensions from Open VSX, and dual publishing means they get the same build on the same day rather than a stale fork. Each publish step is guarded on its token being present, so a fork without credentials still builds. Both collections are MIT licensed.

Problem

Editor themes tend to be placeless — generated from a few seed colours, or built from raw flag palettes that look recognisable in a screenshot but collapse under real code.

Solution

Two collections of hand-tuned JSON themes anchored to real Zimbabwean cities and African countries, seeded from national colours but reassigned by syntax role, with releases automated end-to-end from a version bump.

Outcome

Twenty-five themes across two MIT-licensed extensions, published to both the Visual Studio Marketplace and Open VSX from a single automated release so VS Code, Cursor and VSCodium users install the same build.

Screenshots

Zimbabwe Theme Collection emblem — a circular badge with a soapstone bird and shield motif
The Zimbabwe collection mark: eleven city palettes across five places, six dark and five light.
African Themes Collection emblem — a circular badge with a flame and geometric pattern motif
The African collection mark: fourteen themes, a matched dark and light pair for each of seven countries.

Architecture & flows

How it fits together

Press play to walk through a flow — each pseudo-code line lights up the parts of the system it touches.

hex by syntax role
Service

Place palettes

cities + countries

Service

Theme JSON

25 x colors + tokens

Service

Extension manifests

contributes.themes

Infra

GitHub Actions

release workflow

External

VS Code Marketplace

vsce publish

External

Open VSX

ovsx publish

External

GitHub Releases

tagged .vsix

Client

VS Code / Cursor

theme picker

  • Service
  • Infra
  • External
  • Client

Palette to two registries

How a colour tweak in one place palette becomes an installable release on both marketplaces without a manual publish step.

A palette is written straight into the theme file as workbench colours and token scopes; seed hues are assigned to syntax roles before any chrome colour is picked.

1 / 6

Decisions

Engineering decisions

One extension per collection, not one per place

Context
Every city and country palette could have shipped as its own extension, giving each theme a dedicated marketplace listing, its own README and independent versioning.
Decision
Ship one extension per collection, registering all eleven Zimbabwe themes and all fourteen African themes through the manifest theme contribution point.
Consequence
Trying a different place is a picker change rather than another install, and each collection reads as one body of work; in exchange, retuning a single palette republishes everything under a new version.

Hand-tuned contrast, with flag colours as seeds rather than the finished palette

Context
Deriving a theme algorithmically from a few seed colours is fast, and dropping national flag hex values straight in is the obvious shortcut — but both produce accents that collapse in real code: comments too loud, strings and types too close together, punctuation invisible.
Decision
Assign seed hues to syntax roles first, then desaturate and shift them for backgrounds, comments and inactive chrome using tones drawn from the landscape each theme is named for, stress-testing every colour against real source files.
Consequence
Themes stay identifiably rooted in a place while surviving a long working session; the cost is that adding a place is slow and manual, reasoned about per palette rather than copied mechanically.

A light variant for every country, not dark only

Context
Dark themes are the default expectation and roughly half the work, so many collections ship dark only and add light later, if ever.
Decision
Treat dark and light as a pair per country in the African collection and hold it to complete pairs before adding the next country.
Consequence
The collection covers bright rooms, projectors and pair-programming as well as night work; each new country costs twice the tuning effort.

Version-driven releases published to both registries from one push

Context
Manual packaging and publishing is the step that gets skipped, and doing it twice — once for the Microsoft marketplace and once for Open VSX — is exactly the kind of chore that leaves a listing behind the repository.
Decision
Drive the whole release from a path-filtered workflow on main that packages the VSIX, tags a GitHub release from the manifest version, and publishes to the Marketplace and Open VSX in the same run, guarding each publish step on its token so a missing credential skips a registry instead of failing the build.
Consequence
Shipping is reduced to bumping a version and pushing, and the two registries never drift apart; the trade-offs are two publisher credentials to maintain and a duplicate-tag failure whenever a version bump is forgotten.

Integrations

Notable integrations

VS Code theming API

Supplies the colour theme contribution point that both extensions are built on.

Each theme JSON file provides a workbench colour map and TextMate token rules; the manifest registers the files with a display label and a light or dark UI base, and the editor loads the selected one at runtime.

vsce (Visual Studio Marketplace)

Packages each collection and publishes it to the official marketplace.

The release workflow runs the packaging command on a Node 20 runner to produce a VSIX, then publishes it with a publisher token held as a repository secret.

ovsx (Open VSX Registry)

Mirrors every release to the open registry that Cursor, VSCodium and Gitpod resolve from.

A second publish step pushes the same packaged version to Open VSX, conditioned on an Open VSX token being present so forks without one still build.

GitHub Actions + Releases

Turns a push into a versioned, downloadable release with no local tooling.

A workflow triggered by changes to the manifest or the themes directory checks out the repository, sets up Node, packages the extension, reads the version from the manifest, and creates a tagged release with generated notes and the VSIX attached before the two publish steps run.

Stack

  • VS Code API
  • JSON
  • TextMate grammars
  • GitHub Actions
  • vsce
  • ovsx
  • Node.js