✨ Publier v1 is live — a polished docs platform built for the open web.
Skip to content

Code blocks

Fenced code with titles, frames, line/word highlighting, diff markers, and a copy button — powered by astro-expressive-code, auto-wired by Publier.

Fenced code blocks in any .mdx file render through astro-expressive-code, which Publier wires automatically. No imports, no extra config — write Markdown and everything below works.

Plain block

export function hello(name: string) {
return `Hello, ${name}!`;
}
```ts
export function hello(name: string) {
return `Hello, ${name}!`;
}
```

Titled block (file-tab chrome)

src/lib/greet.ts
export function hello(name: string) {
return `Hello, ${name}!`;
}
```ts title="src/lib/greet.ts"
export function hello(name: string) {
return `Hello, ${name}!`;
}
```

Terminal frame

Shell sessions get a different chrome automatically — bash, sh, zsh, powershell render as a terminal:

Terminal window
pnpm add @publier/shell
publier dev
```bash
pnpm add @publier/shell
publier dev
```

Force the terminal chrome on any language with frame="terminal", or drop it entirely with frame="none":

curl https://publier.net | head
```bash frame="none"
curl https://publier.net | head
```

Line highlighting

Mark single lines with {n}, ranges with {n-m}, or combine:

function sum(values: number[]) {
let total = 0; // highlighted line 2
for (const v of values) total += v;
return total;
} // highlighted line 5
// highlighted line 6
```ts {2,5-6}
function sum(values: number[]) {
let total = 0; // highlighted line 2
for (const v of values) total += v;
return total;
} // highlighted line 5
// highlighted line 6
```

Diff markers (ins / del)

Use semantic labels for additions and deletions:

function sum(values: number[]) {
let total: number = 0;
let total = 0;
for (const v of values) total += v;
return total;
}
```diff lang="ts"
function sum(values: number[]) {
- let total: number = 0;
+ let total = 0;
for (const v of values) total += v;
return total;
}
```

Word highlighting

Highlight individual strings inside a block:

export function greet(name: string) {
return `Hello from greet(): ${name}!`;
}
```ts "greet"
export function greet(name: string) {
return `Hello from greet(): ${name}!`;
}
```

Copy button

Every block gets a copy-to-clipboard button in the top-right corner automatically — hover any code fence above to see it. No opt-in required.

Languages

Expressive Code ships Shiki with ~40 languages pre-loaded. Common ones:

def greet(name: str) -> str:
return f"Hello, {name}!"
fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
publier.config.yaml
nav:
docs:
tabs:
- label: Documentation
href: /docs
package.json
{
"name": "my-publier-site",
"dependencies": {
"@publier/shell": "^1.3.1"
}
}

Behaviour

  • Syntax highlighting — Shiki via astro-expressive-code, with theme colors pulled from your active theme’s --color-* tokens so switching themes (maple, aspen, ruby) doesn’t require a rebuild.
  • Frame chrome styling is auto-injected by Publier.
  • Copy button, highlight colors, scrollbars all respect dark mode.
  • Zero JavaScript for rendering — the copy button is the only script.