TanStack logo

Skill

configure-selective-highlighting

configure selective code highlighting registries

Covers Performance Configuration Frontend

Description

Configure minimal @tanstack/highlight registries with createHighlighter, direct language subpaths, aliases, fallbackLanguage, and shared SSR/client modules. Load for initial setup, browser bundle reduction, language registration, embedded-language dependencies, or hydration consistency.

SKILL.md

Configure Selective Highlighting

Setup

Create one module that both server and client code import:

import { createHighlighter } from '@tanstack/highlight/core'
import { css } from '@tanstack/highlight/languages/css'
import { html } from '@tanstack/highlight/languages/html'
import { js } from '@tanstack/highlight/languages/js'
import { json } from '@tanstack/highlight/languages/json'
import { shell } from '@tanstack/highlight/languages/shell'
import { ts } from '@tanstack/highlight/languages/ts'
import { tsx } from '@tanstack/highlight/languages/tsx'

export const highlighter = createHighlighter({
  languages: [css, html, js, json, shell, ts, tsx],
})

Keep this module isomorphic. It needs no server-only or browser-only imports.

Core Patterns

Render static blocks and later client content

import { highlighter } from './highlight'

export function renderDocumentationCode(code: string, lang: string) {
  return highlighter.renderCodeBlockData({
    code,
    lang,
    lineNumbers: true,
  })
}

Initial SSR output can hydrate unchanged; call the same function only for code introduced after hydration.

Normalize aliases before application branching

import { highlighter } from './highlight'

export function getRegisteredLanguage(lang: string | undefined) {
  return highlighter.normalizeLanguage(lang)
}

getRegisteredLanguage('typescript')
getRegisteredLanguage('bash')
getRegisteredLanguage('not-registered')

The results are ts, shell, and the configured fallback, which defaults to plaintext.

Choose an intentional fallback

import { createHighlighter } from '@tanstack/highlight/core'
import { json } from '@tanstack/highlight/languages/json'

export const jsonHighlighter = createHighlighter({
  fallbackLanguage: 'json',
  languages: [json],
})

Unknown language names are tokenized as JSON in this registry; there is no auto-detection.

Register optional embedded languages explicitly

import { createHighlighter } from '@tanstack/highlight/core'
import { css } from '@tanstack/highlight/languages/css'
import { html } from '@tanstack/highlight/languages/html'
import { js } from '@tanstack/highlight/languages/js'

export const markupHighlighter = createHighlighter({
  languages: [html, css, js],
})

Without css and js, HTML tags still highlight but style and script bodies remain plain.

Common Mistakes

CRITICAL Importing all languages into the client

Wrong:

import { highlight } from '@tanstack/highlight'

export const html = highlight('const answer = 42', { lang: 'ts' }).html

Correct:

import { createHighlighter } from '@tanstack/highlight/core'
import { ts } from '@tanstack/highlight/languages/ts'

const highlighter = createHighlighter({ languages: [ts] })

export const html = highlighter.highlightToHtml('const answer = 42', {
  lang: 'ts',
})

The root entry constructs and retains the all-language registry.

Source: docs/guides/language-registration.md

HIGH Rebuilding the registry per block

Wrong:

import { createHighlighter } from '@tanstack/highlight/core'
import { tsx } from '@tanstack/highlight/languages/tsx'

export function render(code: string) {
  return createHighlighter({ languages: [tsx] }).highlightToHtml(code, {
    lang: 'tsx',
  })
}

Correct:

import { createHighlighter } from '@tanstack/highlight/core'
import { tsx } from '@tanstack/highlight/languages/tsx'

const highlighter = createHighlighter({ languages: [tsx] })

export function render(code: string) {
  return highlighter.highlightToHtml(code, { lang: 'tsx' })
}

The immutable registry can be shared across blocks and requests.

Source: docs/guides/language-registration.md

HIGH Assuming an omitted language is detected

Wrong:

import { highlighter } from './highlight'

export const html = highlighter.highlightToHtml('const answer = 42')

Correct:

import { highlighter } from './highlight'

export const html = highlighter.highlightToHtml('const answer = 42', {
  lang: 'ts',
})

Only registered names and aliases resolve; omitted or unknown names use the fallback.

Source: src/core.ts

CRITICAL Diverging server and client registries

Wrong:

import { createHighlighter } from '@tanstack/highlight/core'
import { html } from '@tanstack/highlight/languages/html'
import { js } from '@tanstack/highlight/languages/js'

const languages = typeof window === 'undefined' ? [html, js] : [html]

export const highlighter = createHighlighter({ languages })

Correct:

import { createHighlighter } from '@tanstack/highlight/core'
import { html } from '@tanstack/highlight/languages/html'
import { js } from '@tanstack/highlight/languages/js'

export const highlighter = createHighlighter({ languages: [html, js] })

Different registries change normalization and embedded delegation across hydration.

Source: docs/guides/ssr-and-client.md

HIGH Omitting embedded tokenizer registrations

Wrong:

import { createHighlighter } from '@tanstack/highlight/core'
import { html } from '@tanstack/highlight/languages/html'

export const highlighter = createHighlighter({ languages: [html] })

Correct:

import { createHighlighter } from '@tanstack/highlight/core'
import { css } from '@tanstack/highlight/languages/css'
import { html } from '@tanstack/highlight/languages/html'
import { js } from '@tanstack/highlight/languages/js'

export const highlighter = createHighlighter({
  languages: [html, css, js],
})

Outer markup remains highlighted, but unregistered script and style bodies are intentionally plain.

Source: docs/guides/embedded-languages.md

HIGH Tension: convenience versus client size

The root helpers simplify setup but retain every language. Use @tanstack/highlight/core and direct language subpaths in hydrated clients.

See also: integrate-framework-code-blocks/SKILL.md - framework adapters should consume the same selective registry.

HIGH Tension: language isolation versus embedding depth

Embedded highlighting depends on the application's registry. Keep dependencies explicit rather than importing another language from a definition.

See also: extend-language-support/SKILL.md - custom tokenizers delegate through TokenizerContext.

References

See also: integrate-framework-code-blocks/SKILL.md - matching registries and package versions preserve hydrated output.

© 2026 YourAI.tools. Every skill from an identity-verified publisher.

Independent catalog. Not affiliated with, endorsed by, or sponsored by Anthropic or any listed publisher. All trademarks belong to their respective owners.