# Benefits of Using Shiki for Code Highlighting in Astro: Complete Technical Guide

> Discover Shiki code highlighting benefits in Astro. Get VS Code-grade syntax highlighting with zero runtime overhead. Learn how Shiki generates static HTML at build time for faster sites.

- Repository: [Angelos Chalaris/30-seconds-of-code](https://github.com/Chalarangelo/30-seconds-of-code)
- Tags: tutorial
- Published: 2026-02-25

---

**Shiki delivers VS Code-grade syntax highlighting with zero runtime overhead by generating static HTML at build time.**

The **30-seconds-of-code** project leverages **Shiki for code highlighting in Astro** to produce high-fidelity syntax highlighting without burdening the client. Unlike traditional client-side highlighters, this approach pre-renders all code blocks during the static site generation process. The result is a faster, more accurate presentation of code snippets that matches the visual experience developers expect from modern editors.

## Architecture: How Shiki Integrates with Astro

The implementation follows a pipeline that converts raw markdown into static HTML before reaching the browser.

The process begins in [`src/lib/contentUtils/extractor.js`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/src/lib/contentUtils/extractor.js), where the `extractData` function selects **Shiki** as the default highlighter. It invokes `ShikiHighlighter.setup` with available language grammars, creating a singleton highlighter instance. This instance utilizes the **Oniguruma WASM engine** for tokenization and loads bundled language definitions from `@shikijs/langs/${lang}`.

Once initialized, the `MarkdownParser` processes code fences through `ShikiHighlighter.highlightCode`, generating HTML strings through the `codeToHtml` method. These pre-rendered strings become part of each **Snippet model**. Finally, `AstroContent.generateSnippetPages()` writes these snippets to JSON files that Astro consumes at build time, ensuring the final pages contain fully highlighted code without client-side execution.

## Core Benefits of Shiki for Static Sites

### VS Code-Level Syntax Accuracy

Shiki reuses the same **TextMate grammars** that power VS Code, delivering tokenization precision that matches the editor developers use daily. In [`src/lib/contentUtils/markdownParser/codeHighlighters/shiki.js`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/src/lib/contentUtils/markdownParser/codeHighlighters/shiki.js), languages load dynamically via `loadBundledLanguages`, which constructs a lazy import map from the grammars list. This ensures the site supports exact syntax definitions rather than simplified approximations.

### WASM-Driven Performance

The heavy parsing logic runs inside a compact **WebAssembly module**, keeping client-side bundles minimal. The highlighter configuration specifies `engine: () => createOnigurumaEngine(import('shiki/wasm'))`, ensuring textmate parsing happens server-side during the build. Since highlighting occurs at build time, the runtime cost for users is zero.

### Bundled Themes and Custom Transformers

The project ships with a custom "cosmos" theme and enhances visual presentation through custom transformers. The `highlightCode` method applies `transformerColorSwatches`, `transformerLineHighlights`, `transformerSectionFolding`, and `transformerColorizedBrackets` to add interactive features without JavaScript execution. Themes load via `loadBundledThemes` in [`shiki.js`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/shiki.js), while transformers execute during the HTML generation phase.

### Static-Site Friendliness

Because Shiki returns **pure HTML strings** through `codeToHtml`, Astro writes the final markup directly to the output folder via `AstroContent.generateSnippetPages()`. The `snippet.page.serialize` objects contain pre-highlighted HTML that Astro injects into pages, eliminating the need for client-side highlighting libraries entirely.

## Implementation Examples

### Setting Up the Shiki Highlighter

The `ShikiHighlighter` class initializes the singleton instance with bundled languages and the WASM engine:

```javascript
// src/lib/contentUtils/markdownParser/codeHighlighters/shiki.js
export default class ShikiHighlighter {
  static setup(grammars) {
    const bundledLanguages = loadBundledLanguages(grammars);
    const bundledThemes = loadBundledThemes();

    const createHighlighter = createdBundledHighlighter({
      langs: bundledLanguages,
      themes: bundledThemes,
      engine: () => createOnigurumaEngine(import('shiki/wasm')),
    });

    Object.assign(this, createSingletonShorthands(createHighlighter));
  }
}

```

*The `setup` method receives the grammars list from `extractData` and configures the highlighter for the markdown parser.*

### Selecting the Highlighter

The extraction layer allows switching between highlighters while defaulting to Shiki:

```javascript
// src/lib/contentUtils/extractor.js
export const extractData = async (highlighter = 'shiki') => {
  const codeHighlighter =
    highlighter === 'shiki' ? ShikiHighlighter : PrismHighlighter;
  codeHighlighter.setup(grammars);

  MarkdownParser.setupProcessors({ languages, grammars, codeHighlighter });
};

```

*Changing the default parameter to `"prism"` would revert to the legacy highlighter, though this bypasses the performance benefits of the WASM-based approach.*

### Generating Highlighted HTML

The `highlightCode` method applies the cosmos theme and custom transformers:

```javascript
// Inside ShikiHighlighter.highlightCode()
const highlightedCode = await this.codeToHtml(code, {
  lang: language,
  theme: 'cosmos',
  transformers: [
    transformerColorSwatches(),
    transformerLineHighlights(metadata),
    transformerSectionFolding(metadata),
    transformerColorizedBrackets({ themes: { cosmos: [...] } }),
  ],
});

```

*Custom transformers add visual enhancements like bracket colorization and collapsible sections directly into the static HTML.*

### Static Generation Integration

Astro receives pre-rendered content through the content generation pipeline:

```javascript
// src/lib/astroContent.js
static generateSnippetPages() {
  const snippets = process.env.NODE_ENV === 'development'
    ? Snippet.all
    : Snippet.scope('published');

  const pages = snippets.reduce((acc, snippet) => {
    acc[snippet.page.key] = snippet.page.serialize;
    return acc;
  }, {});

  fs.writeJson(settings.paths.out.snippets, pages, ...this.outputParams);
}

```

*The `page.serialize` property contains the fully highlighted HTML, allowing Astro to write static files without runtime highlighting overhead.*

## Summary

- **Shiki provides VS Code-grade accuracy** by using the same TextMate grammars as the popular editor, loaded dynamically from `@shikijs/langs` bundles.
- **Zero runtime overhead** results from executing the Oniguruma WASM engine during the build process, with `AstroContent.generateSnippetPages()` writing pre-highlighted HTML to static files.
- **Custom visual features** like line highlights and section folding are implemented through server-side transformers in [`shiki.js`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/shiki.js), requiring no client-side JavaScript.
- **Architecture flexibility** allows fallback to PrismJS via the `extractData` parameter, though Shiki remains the default for its superior static generation capabilities.

## Frequently Asked Questions

### How does Shiki differ from PrismJS in Astro projects?

Shiki generates highlighted HTML at build time using a WASM-based TextMate parser, while PrismJS traditionally runs in the browser. The 30-seconds-of-code implementation stores pre-highlighted strings in `snippet.page.serialize`, eliminating client-side execution and reducing bundle sizes. Shiki also provides more accurate syntax tokenization by using VS Code's exact grammar definitions rather than simplified regex patterns.

### Can I use custom themes with Shiki in Astro?

Yes, the 30-seconds-of-code repository demonstrates this by loading a custom "cosmos" theme through `loadBundledThemes()` in [`src/lib/contentUtils/markdownParser/codeHighlighters/shiki.js`](https://github.com/Chalarangelo/30-seconds-of-code/blob/main/src/lib/contentUtils/markdownParser/codeHighlighters/shiki.js). You can drop JSON theme files into the `themes` directory and reference them by name in the `codeToHtml` configuration. The setup supports both bundled themes from Shiki's collection and completely custom color schemes.

### Does Shiki impact the build performance of large Astro sites?

The initial setup in `extractData` creates a singleton highlighter that reuses the WASM engine across all files, minimizing overhead. While the TextMate parsing is computationally heavier than simple regex highlighting, it runs entirely during the build phase. The resulting static HTML requires no client-side processing, making the runtime performance significantly faster than client-side alternatives.

### What languages does Shiki support in this implementation?

The implementation uses `loadBundledLanguages` to dynamically import language grammars from `@shikijs/langs/${lang}` based on a configurable grammars list. This approach supports all languages available in the Shiki ecosystem while keeping the initial bundle size small through lazy loading. New languages can be added by updating the grammars configuration and ensuring the corresponding Shiki language package is available.