Overview

Code blocks are the backbone of technical documentation. HolyDocs renders fenced code blocks with syntax highlighting powered by Shiki, supporting 100+ programming languages out of the box. Every code block includes a copy button, optional line numbers, line highlighting, and a filename header.

Basic Usage

Create a code block by wrapping your code in triple backticks with a language identifier:

mdx
```javascriptconst holydocs = require('@holydocs/cli');holydocs.deploy({ projectId: 'my-project' });```

The language identifier determines syntax highlighting. If omitted, the block renders as plain text.

Supported Languages

HolyDocs supports all major programming languages and configuration formats. Here are the most commonly used identifiers:

LanguageIdentifier(s)LanguageIdentifier(s)
JavaScriptjavascript, jsTypeScripttypescript, ts
Pythonpython, pyGogo
Rustrust, rsJavajava
Rubyruby, rbPHPphp
C#csharp, csC / C++c, cpp
SwiftswiftKotlinkotlin, kt
Shell / Bashbash, shell, shPowerShellpowershell, ps1
SQLsqlGraphQLgraphql, gql
JSONjsonYAMLyaml, yml
TOMLtomlXMLxml
HTMLhtmlCSScss
SCSSscssMarkdownmarkdown, md
MDXmdxDiffdiff
DockerdockerfileNginxnginx
PrismaprismaProtocol Buffersprotobuf

If your language is not listed here, it is likely still supported. HolyDocs uses the full Shiki grammar library. Try using the standard file extension as the identifier.

Code Block Titles

Add a filename or descriptive title after the language identifier to display a header above the code block:

mdx
```typescript docs.json{ "name": "My Docs", "theme": "holy"}```
mdx
```python app/main.pyfrom fastapi import FastAPIapp = FastAPI()@app.get("/")async def root(): return {"message": "Hello World"}```

Titles are particularly useful when showing file contents, configuration examples, or when multiple code blocks on a page need to be distinguishable at a glance.

Line Highlighting

Highlight specific lines to draw attention to important code. Add line numbers in curly braces after the language identifier:

mdx
```javascript {3,5-7}const express = require('express');const app = express();const port = 3000; // highlightedapp.get('/', (req, res) => { // highlighted res.send('Hello World'); // highlighted}); // highlightedapp.listen(port);```

Highlight Syntax

SyntaxDescriptionExample
{3}Single lineHighlights line 3
{3,5}Multiple linesHighlights lines 3 and 5
{3-7}Line rangeHighlights lines 3 through 7
{1,3-5,8}MixedHighlights line 1, lines 3-5, and line 8

Highlighted lines receive a subtle background tint that works in both light and dark modes.

Line Numbers

Enable line numbers on a code block by adding showLineNumbers after the language identifier:

mdx
```typescript showLineNumbersinterface User { id: string; name: string; email: string; role: 'admin' | 'member' | 'viewer';}function getUser(id: string): Promise<User> { return fetch(`/api/users/${id}`).then(r => r.json());}```

Line numbers are useful for longer code blocks or when you need to reference specific lines in your prose.

Line numbers and line highlighting can be combined. Use {3,5} with showLineNumbers to highlight numbered lines.

Copy Button

Every code block includes a copy-to-clipboard button in the top-right corner. When clicked, the full contents of the block are copied and the button displays a checkmark confirmation for 2 seconds.

The copy button is automatic and requires no configuration. It copies only the raw code content, excluding line numbers and any decorative elements.

CodeGroup

The CodeGroup component renders multiple code blocks as a tabbed interface. This is ideal for showing the same concept in multiple languages or the same command for different package managers.

mdx
<CodeGroup>```bash npmnpm install @holydocs/cli``````bash pnpmpnpm add @holydocs/cli``````bash yarnyarn add @holydocs/cli``````bash bunbun add @holydocs/cli```</CodeGroup>

Each code block's tab label is derived from the text after the language identifier. If no custom title is provided, the language name is used.

Multi-Language API Examples

mdx
<CodeGroup>```javascript JavaScriptconst res = await fetch('https://api.example.com/users', { headers: { 'Authorization': 'Bearer YOUR_API_KEY' },});const users = await res.json();``````python Pythonimport requestsresponse = requests.get( 'https://api.example.com/users', headers={'Authorization': 'Bearer YOUR_API_KEY'},)users = response.json()``````go Goreq, _ := http.NewRequest("GET", "https://api.example.com/users", nil)req.Header.Set("Authorization", "Bearer YOUR_API_KEY")resp, _ := http.DefaultClient.Do(req)```</CodeGroup>

The reader's tab selection is persisted across CodeGroups on the same page. If a reader selects "Python" in one CodeGroup, all other CodeGroups on that page switch to "Python" too (when available).

Diff Highlighting

Use the diff language identifier to show additions and removals:

diff
- const API_URL = 'http://localhost:3000';+ const API_URL = process.env.API_URL || 'http://localhost:3000'; async function fetchUsers() {- const res = await fetch(API_URL + '/users');+ const res = await fetch(`${API_URL}/users`, {+ headers: { 'Authorization': `Bearer ${getToken()}` },+ }); return res.json(); }

Lines prefixed with + are highlighted green, lines with - are highlighted red, and unchanged lines (prefixed with a space) render normally.

Diff in Typed Code Blocks

You can also show diffs within a syntax-highlighted code block by combining the language with diff markers. Use // [!code ++] and // [!code --] annotations at the end of lines:

mdx
```typescriptconst config = { name: 'My Docs', theme: 'mint', // [!code --] theme: 'holy', // [!code ++] colors: { primary: '#007AFF', // [!code --] primary: '#FBBF24', // [!code ++] },};```

This approach preserves full TypeScript syntax highlighting while showing the diff.

Word Highlighting

Highlight specific words or phrases within a code block using the // [!code word:xxx] annotation:

mdx
```typescript// [!code word:apiKey]const apiKey = process.env.API_KEY;const client = new Client({ apiKey });```

Every occurrence of apiKey in the block is highlighted with a subtle background, making it easy for readers to track a variable or concept through a longer code example.

Code Block Themes

HolyDocs supports two code block theme modes, configured in docs.json:

json
{ "styling": { "codeblocks": "system" }}
ValueBehavior
systemCode blocks use a light theme in light mode and a dark theme in dark mode
darkCode blocks always use a dark background, regardless of the site theme

Most documentation sites use "dark" because dark code blocks provide better contrast for syntax highlighting and remain visually consistent across both appearance modes.

Long Lines

By default, code blocks scroll horizontally when lines exceed the block width. This preserves the original formatting and prevents awkward line breaks in the middle of expressions.

If you prefer wrapping, you can enable it globally through custom CSS:

css
.code-block pre { white-space: pre-wrap; word-break: break-all;}

Line wrapping can make code harder to read, especially for languages where indentation is significant (Python, YAML). Use horizontal scrolling unless you have a specific reason to wrap.

Inline Code

Use single backticks for inline code within paragraphs:

mdx
Run `npm install` to install dependencies. The config file is `docs.json`.

Inline code is styled with a subtle background and monospace font. It does not receive syntax highlighting.

Best Practices

Without a language identifier, code blocks render as plain text with no highlighting. Even for simple shell commands, use bash or shell to provide visual structure.

When showing the contents of a specific file, always include the filename as a title. This gives readers immediate context about where the code lives in their project.

Show the minimum code needed to illustrate the concept. Avoid boilerplate that distracts from the point. When a full file is necessary, use line highlighting to focus on the relevant lines.

Whenever you show the same operation in multiple languages or tools (e.g., npm vs pnpm vs yarn), wrap them in a CodeGroup rather than listing them sequentially. This saves vertical space and lets readers pick their preference.

Instead of generic placeholders like YOUR_VALUE_HERE, use realistic example values that help readers understand the expected format. For sensitive values like API keys, use clearly fake values like sk_test_abc123.

Ask a question... ⌘I