> Agent-readable docs index: /llms.txt. Download /docs.zip to grep all markdown files locally.

---
title: Code Blocks
description: Syntax highlighting, code groups, and inline code.
icon: code
---

# Code Blocks

Holocron uses Prism for syntax highlighting. Fenced code blocks are rendered with full language support and configurable meta options.

## Basic code block

```ts
const greeting = 'Hello, world!'
console.log(greeting)
```

Line numbers are shown by default. Format:

````mdx
```ts
const greeting = 'Hello, world!'
console.log(greeting)
```
````

## Meta options

Add options after the language identifier to customize code blocks. Options use `key=value` syntax. Bare words (without `=`) become the **title**.

### Title

The first bare word(s) after the language become the title, useful for showing filenames:

```ts vite.config.ts
export default defineConfig({
  plugins: [holocron()],
})
```

````mdx
```ts vite.config.ts
export default defineConfig({
  plugins: [holocron()],
})
```
````

You can also set the title explicitly with `title="..."` for titles with special characters:

````mdx
```ts title="src/vite.config.ts"
export default defineConfig({
  plugins: [holocron()],
})
```
````

### Line numbers

Line numbers are **on by default**. Disable them with `lines=false`:

```bash lines=false
npm install @holocron.so/vite
```

````mdx
```bash lines=false
npm install @holocron.so/vite
```
````

### Bleed

Fenced code blocks bleed into the **right** margin by default so the code text lines up with the prose left edge. Set `bleed=true` (or `bleed=both`) to extend into both margins, or `bleed=none` (or `bleed=false`) to keep the block fully inside the content column:

```ts bleed=true
import { defineConfig } from 'vite'
import { holocron } from '@holocron.so/vite'

export default defineConfig({
  plugins: [holocron()],
})
```

````mdx
```ts bleed=true
import { defineConfig } from 'vite'
...
```
````

The `bleed` meta accepts `true`/`both`, `right` (the fenced-block default), or `false`/`none`.

### Highlight lines

Dim all lines except the ones you want to focus on. Pass a comma-separated list of line numbers or ranges to `highlight`:

```ts highlight="1,4-5"
import { defineConfig } from 'vite'
import { holocron } from '@holocron.so/vite'

export default defineConfig({
  plugins: [holocron()],
})
```

````mdx
```ts highlight="1,4-5"
import { defineConfig } from 'vite'
import { holocron } from '@holocron.so/vite'

export default defineConfig({
  plugins: [holocron()],
})
```
````

### Combining options

Options can be combined freely:

```ts vite.config.ts highlight="3" bleed=true
import { defineConfig } from 'vite'
import { holocron } from '@holocron.so/vite'

export default defineConfig({
  plugins: [holocron()],
})
```

````mdx
```ts vite.config.ts highlight="3" bleed=true
import { defineConfig } from 'vite'
...
```
````

## Code groups

Group related code blocks into tabs with the `CodeGroup` component. The bare word after the language becomes the tab label:

<Tabs items={["npm", "pnpm", "yarn"]}>
  <Tab title="npm">
    ```bash
    npm install @holocron.so/vite
    ```
  </Tab>

  <Tab title="pnpm">
    ```bash
    pnpm add @holocron.so/vite
    ```
  </Tab>

  <Tab title="yarn">
    ```bash
    yarn add @holocron.so/vite
    ```
  </Tab>
</Tabs>

````mdx
<CodeGroup>

```bash npm
npm install @holocron.so/vite
```

```bash pnpm
pnpm add @holocron.so/vite
```

```bash yarn
yarn add @holocron.so/vite
```

</CodeGroup>
````

See [Code Groups](/docs/components/code-groups) for more options.

## Inline code

Use backticks for inline code: `` `variable` `` renders as `variable`.

## Reusing Holocron's Prism bundle

Holocron **vendors its own Prism bundle**: a single pre-built ESM module containing prismjs core plus all \~300 language grammars. This avoids Vite's dev optimizer discovering each grammar one by one, and keeps the highlighter out of the SSR build.

If your app already depends on `@holocron.so/vite` and you need to highlight code **outside** of MDX (for example in a custom React component), import the same bundle from the `@holocron.so/vite/prism` export instead of adding `prismjs` yourself. This way you **don't ship a duplicate Prism bundle** in your client output.

```tsx Highlighter.tsx
import { useEffect, useState } from 'react'

export function Highlighted({ code, lang }: { code: string; lang: string }) {
  const [html, setHtml] = useState<string>()

  // Lazy-load so the ~891KB Prism bundle doesn't block first paint.
  useEffect(() => {
    let cancelled = false
    import('@holocron.so/vite/prism').then(({ Prism }) => {
      if (cancelled) return
      const grammar = Prism.languages[lang]
      if (!grammar) return
      setHtml(Prism.highlight(code, grammar, lang))
    })
    return () => {
      cancelled = true
    }
  }, [code, lang])

  if (html) {
    return <code className={`language-${lang}`} dangerouslySetInnerHTML={{ __html: html }} />
  }
  return <code className={`language-${lang}`}>{code}</code>
}
```

The export resolves by build condition:

| Condition | Resolves to       | Behavior                                                |
| --------- | ----------------- | ------------------------------------------------------- |
| `browser` | full Prism bundle | real syntax highlighting                                |
| `ssr`     | no-op stub        | returns text unchanged, highlighting runs on the client |

Because highlighting is client-only, always **lazy-load with a dynamic `import()`** and render plain code as the fallback so SSR output and first paint stay unhighlighted, then upgrade once Prism loads.

<Tip title="Tip">
  Use `Prism.languages[lang]` to check a grammar exists before calling `Prism.highlight`. Missing grammars return `undefined`, so guard against it and fall back to plain text.
</Tip>

### Rendering the CodeBlock component directly

If you want the exact same code block UI that MDX renders (copy button, line numbers, line highlighting, Prism), import the `CodeBlock` component from `@holocron.so/vite/mdx`. This is handy for rendering code outside of docs, for example in a **dashboard** or settings page.

```tsx Dashboard.tsx
import { CodeBlock } from '@holocron.so/vite/mdx'

const CLI_EXAMPLES = `npx @holocron.so/cli build
npx @holocron.so/cli dev`

export function CliHelp() {
  return (
    <CodeBlock lang='bash' showLineNumbers={false}>
      {CLI_EXAMPLES}
    </CodeBlock>
  )
}
```

`CodeBlock` lazy-loads the same vendored Prism bundle internally, so you get highlighting without shipping a duplicate prismjs. The `children` prop is the raw code **string**.

The `bleed` prop controls how far the block extends past its content column. The component **defaults to no bleed**, so it stays fully inside its parent, which is what you want in a dashboard, modal, or card. Opt into bleed only when you render inside the docs prose column:

| `bleed` value      | Behavior                                          |
| ------------------ | ------------------------------------------------- |
| `'both'` / `true`  | extends into both left and right margins          |
| `'right'`          | extends into the right margin only                |
| `'none'` / `false` | no bleed, stays fully inside its parent (default) |

| Prop              | Type      | Description                                            |
| ----------------- | --------- | ------------------------------------------------------ |
| `children`        | `string`  | The raw code to render.                                |
| `lang`            | `string`  | Language id for Prism, defaults to `jsx`.              |
| `showLineNumbers` | `boolean` | Line numbers on the left, on by default.               |
| `title`           | `string`  | Filename or label shown above the block.               |
| `highlight`       | `string`  | Comma-separated lines/ranges to focus, e.g. `"1-3,7"`. |
| `bleed`           | `boolean` | Extend into the page margins, off by default.          |
