The identifier straight after the opening backticks. It selects the Prism grammar and fills the language name on the right of the header bar. A fence with no identifier falls back to plain text.
Code Blocks
Every fenced code block in an MDX page renders through the same component: Prism.js syntax highlighting, a header bar carrying the file title and the language name, line numbers down the left edge, and a copy button. You tune all of it from the metastring — the space-separated text you write after the language on the opening fence line.
Quick Start
A fence with nothing but a language identifier already gets highlighting, line numbers, a header bar, and a copy button.
async function fetchDocumentation(slug) {
const response = await fetch(`/api/docs/${slug}`)
return response.json()
}```javascript
async function fetchDocumentation(slug) {
const response = await fetch(`/api/docs/${slug}`)
return response.json()
}
```Adding Options
Options are space-separated and order never matters. This fence names a file and highlights the three lines that do the work.
import { SignJWT } from 'jose'
const secret = new TextEncoder().encode(process.env.JWT_SECRET)
export async function createSession(payload) {
return new SignJWT(payload).setProtectedHeader({ alg: 'HS256' }).sign(secret)
}```typescript {3-5} title="lib/auth.ts"
import { SignJWT } from 'jose'
const secret = new TextEncoder().encode(process.env.JWT_SECRET)
export async function createSession(payload) {
return new SignJWT(payload).setProtectedHeader({ alg: 'HS256' }).sign(secret)
}
```Advanced
All eight options stack on one fence. The block below sets a title, highlights
two ranges, starts numbering at 120, marks every SearchItem, and collapses to
six visible lines with a "Show more" button.
```typescript {2,5-7} title="lib/search-index.ts" showLineNumbers=120 /SearchItem/ expandable maxLines=6
export function buildSearchIndex(version?: string): SearchItem[] {
const searchIndex: SearchItem[] = []
const pages = collectPages(version)
for (const page of pages) {
const record: SearchItem = toSearchItem(page)
searchIndex.push(record)
}
return searchIndex
}
```Options
Each option below is matched independently against the metastring, so you can write them in any order. Only the first occurrence of an option counts, and text the parser doesn't recognize is ignored rather than treated as an error.
languagestringDefault: texttitle="filename"stringDefault: language nameFile path shown on the left of the header bar, in double or single quotes. Covered on File title.
{lines}number[]Lines to tint, as single numbers, ranges, or both: {1,3-5}. Covered on Line
highlighting.
showLineNumbersbooleanDefault: trueLine numbers are already on for every block, so writing this only makes the intent explicit. Covered on Line numbers.
showLineNumbers=NnumberDefault: 1Starts the gutter at line N instead of 1. Covered on Line numbers.
/pattern/stringMarks every literal occurrence of the text between the slashes. Covered on Word highlighting.
expandablebooleanDefault: falseCollapses the block behind a "Show more" button. Covered on Collapsible code.
maxLines=NnumberHow many lines stay visible while the block is collapsed. Covered on Collapsible code.
Diff markers are the one feature that lives in the code rather than the metastring — see Diff highlighting.
Languages
The language registry holds 71 identifiers and 49 aliases, so ts, yml, sh,
py, rs, tf, and dockerfile all resolve to their full names. The resolved
name is what you see on the right of the header bar: ts shows as TypeScript,
tf as HCL, wat as WebAssembly.
Two details are worth knowing. tsx borrows the TypeScript grammar, so JSX
inside a .tsx sample is highlighted as TypeScript. And an identifier with no
loaded grammar still renders: escaped, unhighlighted, with the badge and the
copy button intact. An unknown language degrades quietly instead of breaking the
page.
Terminal languages get their own header icon. bash, sh, shell, zsh,
powershell, terminal, and console show a terminal glyph; everything else
shows a file glyph.
npm install
npm run build
npm start```bash title="deploy.sh" {1,3}
npm install
npm run build
npm start
```Copy behavior
The copy button hands over the block's original source text, not the rendered markup. Line numbers are drawn with CSS counters, so they never end up on the clipboard. Diff markers do — they are part of the source you wrote. Text pasted from a collapsed block includes the hidden lines as well, because collapsing only clips the height.