Beautiful light and dark themes, generated from a shared color palette, for Visual Studio Code, Cursor, and Shiki. Built first for @pierre/diffs, and shared with the community by The Pierre Computer Company.
Install the Pierre theme pack from your editor's extension marketplace:
Then open your editor and select "Pierre Dark" or "Pierre Light" in settings or the command palette.
Create custom syntax highlighting themes for use with @pierre/diffs (plus
Shiki and Visual Studio Code based editors) by forking our open-source
Pierre Theme repository.
The Pierre themes are also bundled with @pierre/diffs as pierre-dark and
pierre-light, so you can use them without any additional setup.
The fastest way to create a custom theme is to fork the Pierre Theme repo and modify the color palette. The repo uses TypeScript to generate theme JSON files, giving you type safety and the ability to generate multiple theme variants from a single color palette.
git clone https://github.com/YOUR_USERNAME/theme.gitnpm installnpm start (watches for changes and rebuilds)The Pierre Theme repo is organized as follows:
1theme/2├── src/3│ ├── palette.ts # Color definitions (edit this!)4│ ├── theme.ts # Token color mappings5│ └── index.ts # Build script entry point6├── themes/ # Generated theme JSON files7│ ├── pierre-dark.json8│ ├── pierre-light.json9│ ├── pierre-dark-vibrant.json10│ └── pierre-light-vibrant.json11├── package.json # Update with your details12├── DISPLAY-P3.md # Info on vibrant theme generation13└── README.mdThe src/palette.ts file is the single source of truth for all colors in your
theme. Modify these values to create your own color scheme:
1// Define your color palette — this is the single source of truth2// for all theme variants (light, dark, vibrant)3
4export const palette = {5 // Background colors6 scale: {7 black: '#070707',8 white: '#fbfbfb',9 gray: ['#141415', '#1F1F21', '#39393c', '#424245', '#79797F', '#84848A', '#adadb1'],10 },11
12 // Accent colors — used for syntax highlighting13 red: '#ff2e3f',14 green: '#0dbe4e',15 blue: '#009fff',16 purple: '#7b43f8',17 cyan: '#00cab1',18 orange: '#fe8c2c',19 yellow: '#ffca00',20 magenta: '#c635e4',21
22 // Muted variants — softer colors for dark theme tokens23 redMuted: '#ff678d',24 greenMuted: '#5ecc71',25 blueMuted: '#69b1ff',26 purpleMuted: '#9d6afb',27 cyanMuted: '#61d5c0',28 orangeMuted: '#ffa359',29 yellowMuted: '#ffd452',30 magentaMuted: '#d568ea',31};After editing your palette, the build script automatically regenerates all theme variants. Each color in the palette is used consistently across light theme, dark theme, and vibrant variants.
The src/theme.ts file maps your palette colors to specific syntax tokens. This
is where you control which colors are used for comments, strings, keywords, and
other code elements:
1import { palette } from './palette';2
3// Map palette colors to syntax token scopes4export function getTokenColors(variant: 'light' | 'dark') {5 const isDark = variant === 'dark';6
7 return [8 {9 scope: ['comment', 'punctuation.definition.comment'],10 settings: { foreground: palette.scale.gray[5] },11 },12 {13 scope: ['string', 'constant.other.symbol'],14 settings: { foreground: isDark ? palette.greenMuted : palette.green },15 },16 {17 scope: ['keyword', 'storage', 'storage.type'],18 settings: { foreground: isDark ? palette.redMuted : palette.red },19 },20 {21 scope: ['entity.name.function', 'support.function'],22 settings: { foreground: isDark ? palette.purpleMuted : palette.purple },23 },24 {25 scope: ['entity.name.type', 'entity.name.class'],26 settings: { foreground: isDark ? palette.magentaMuted : palette.magenta },27 },28 {29 scope: ['variable', 'meta.definition.variable'],30 settings: { foreground: isDark ? palette.orangeMuted : palette.orange },31 },32 {33 scope: ['constant.numeric', 'constant.language.boolean'],34 settings: { foreground: isDark ? palette.cyanMuted : palette.cyan },35 },36 // ... additional token rules37 ];38}For a complete reference of TextMate scopes, see the VS Code syntax highlighting documentation and the TextMate language grammars manual.
The repo includes several npm scripts for development:
| Script | Description |
|---|---|
npm start | Watch mode — rebuilds on file changes |
npm run build | Generate theme JSON files in ./themes directory |
npm test | Validate theme structure (runs build first) |
npm run package | Create .vsix file for VS Code/Cursor publishing |
Before publishing your theme, update the package.json with your own details:
1{2 "name": "my-custom-theme",3 "displayName": "My Custom Theme",4 "description": "A beautiful theme for VS Code and Shiki",5 "version": "1.0.0",6 "publisher": "your-publisher-id",7 "author": "Your Name",8 "license": "MIT",9 "repository": {10 "type": "git",11 "url": "https://github.com/YOUR_USERNAME/my-custom-theme"12 },13 "categories": ["Themes"],14 "contributes": {15 "themes": [16 {17 "label": "My Theme Dark",18 "uiTheme": "vs-dark",19 "path": "./themes/my-theme-dark.json"20 },21 {22 "label": "My Theme Light",23 "uiTheme": "vs",24 "path": "./themes/my-theme-light.json"25 }26 ]27 }28}Once you've built your theme JSON files, you can use them with @pierre/diffs
by registering them before rendering:
1import { registerCustomTheme } from '@pierre/diffs';2
3// Register your theme JSON files before rendering4// The name must match the "name" field in your theme JSON5
6// Option 1: Import from your bundled theme files7registerCustomTheme('my-theme-dark', () => import('./themes/my-theme-dark.json'));8registerCustomTheme('my-theme-light', () => import('./themes/my-theme-light.json'));9
10// Option 2: Fetch from a URL (for CDN-hosted themes)11registerCustomTheme('my-theme-dark', async () => {12 const response = await fetch('/themes/my-theme-dark.json');13 return response.json();14});Then reference your theme in any component:
1import { FileDiff } from '@pierre/diffs/react';2
3export function DiffWithCustomTheme({ fileDiff }) {4 return (5 <FileDiff6 fileDiff={fileDiff}7 options={{8 // Single theme9 theme: 'my-theme-dark',10
11 // Or both variants for automatic light/dark mode12 theme: {13 dark: 'my-theme-dark',14 light: 'my-theme-light',15 },16 }}17 />18 );19}The Pierre Theme repo automatically generates "Vibrant" variants that use the Display P3 color space for ~25% more color range on compatible displays.
Display P3 colors are not supported in VS Code or Cursor. However, they work
perfectly in Shiki for web rendering, including with @pierre/diffs.
The vibrant variants are generated automatically when you run npm run build.
They use enhanced saturation to push colors into the wider P3 gamut. See the
repo's DISPLAY-P3.md for technical details on the color conversion algorithm.
To publish your theme to the VS Code Marketplace or Open VSX:
package.json with your publisher ID and theme metadatanpm run package to create the .vsix fileFor Shiki/web use only, you can skip publishing and simply host your theme JSON files or bundle them with your application.
Collectively, our team brings over 150 years of expertise designing, building, and scaling the world's largest distributed systems at Cloudflare, Coinbase, Discord, GitHub, Reddit, Stripe, X, and others.