Code Blocks
Beautiful syntax highlighting and interactive code blocks powered by Shiki.
Streamdown provides beautiful, interactive code blocks with syntax highlighting powered by Shiki. Every code block includes a copy button and supports a wide range of programming languages.
Basic Usage
Create code blocks using triple backticks with an optional language identifier:
```javascript
function greet(name) {
return `Hello, ${name}!`;
}
```Streamdown will automatically apply syntax highlighting based on the specified language.
Enabling Syntax Highlighting
Syntax highlighting requires the code plugin. Install it:
npm install @streamdown/codeThen import and pass the plugin to Streamdown:
import { Streamdown } from "streamdown";
import { code } from "@streamdown/code";
export default function Page() {
return (
<Streamdown plugins={{ code: code }}>
{markdown}
</Streamdown>
);
}Without the code plugin, code blocks render as plain text with no highlighting.
Supported Languages
Streamdown supports 200+ programming languages through Shiki. All languages are lazy-loaded on demand, so only the grammars you use are downloaded.
Common Languages
- Web: JavaScript, TypeScript, JSX, TSX, HTML, CSS
- Data: JSON, YAML, TOML
- Shell: Bash, Shell Script, PowerShell
- Backend: Python, Go, Java, Rust, C, C++, C#, PHP, Ruby
- Functional: Haskell, Elixir, Clojure, F#, OCaml
- Markup: Markdown, LaTeX, MDX, XML
- And 180+ more languages
Language Examples
TypeScript
```typescript
interface User {
id: number;
name: string;
email: string;
}
async function fetchUser(id: number): Promise<User> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
```Python
```python
def fibonacci(n: int) -> list[int]:
"""Generate Fibonacci sequence up to n terms."""
fib = [0, 1]
for i in range(2, n):
fib.append(fib[i-1] + fib[i-2])
return fib
print(fibonacci(10))
```Rust
```rust
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
let sum: i32 = numbers.iter().sum();
println!("Sum: {}", sum);
}
```Theme Configuration
Streamdown uses dual themes for light and dark modes. You can customize the themes using the shikiTheme prop:
import { Streamdown } from "streamdown";
import { code } from "@streamdown/code";
export default function Page() {
return (
<Streamdown
plugins={{ code: code }}
shikiTheme={["dracula", "dracula"]}
>
{markdown}
</Streamdown>
);
}Available Themes
Streamdown supports all Shiki themes including:
github-light(default light theme)github-dark(default dark theme)dracula,nord,one-dark-pro,monokaicatppuccin-latte,catppuccin-mochavitesse-light,vitesse-darktokyo-night,slack-dark,slack-ochin- And many more
Interactive Features
Copy Button
Every code block includes a copy button that appears on hover. Users can click to copy the entire code block content to their clipboard.
The copy button:
- Appears on hover (desktop) or is always visible (mobile)
- Provides visual feedback on successful copy
- Is automatically disabled during streaming (when
isAnimating={true})
Disable Copy Button
You can disable the copy button using the controls prop:
<Streamdown controls={{ code: false }}>{markdown}</Streamdown>Or disable all controls:
<Streamdown controls={false}>{markdown}</Streamdown>Inline Code
Inline code uses backticks and receives subtle styling:
Use the `useState` hook to manage state in React.Inline code is styled with:
- Monospace font family
- Subtle background color
- Rounded corners
- Appropriate padding
Code Block Styling
Code blocks include:
- Line Numbers - Optional line numbers for reference
- Rounded Corners - Modern, polished appearance
- Proper Padding - Comfortable spacing
- Scrolling - Horizontal scroll for long lines
- Responsive Design - Adapts to container width
Streaming Considerations
Code blocks work seamlessly with streaming content:
Incomplete Code Blocks
When a code block is streaming in, Streamdown handles the incomplete state gracefully:
```javascript
function example() {
// Streaming in progress...
```The unterminated block parser ensures the code block renders properly even without the closing backticks.
Disabling Interactions During Streaming
Use the isAnimating prop to disable copy buttons while streaming:
<Streamdown isAnimating={isStreaming}>{markdown}</Streamdown>This prevents users from copying incomplete code.
Plugin Interface
The Code plugin implements the CodeHighlighterPlugin interface:
interface CodeHighlighterPlugin {
name: "shiki";
type: "code-highlighter";
highlight: (options: HighlightOptions, callback?: (result: HighlightResult) => void) => HighlightResult | null;
supportsLanguage: (language: BundledLanguage) => boolean;
getSupportedLanguages: () => BundledLanguage[];
getThemes: () => [BundledTheme, BundledTheme];
}Exported Types
import type {
CodeHighlighterPlugin,
HighlightOptions,
HighlightResult,
} from '@streamdown/code';
// HighlightOptions - parameters for highlighting
interface HighlightOptions {
code: string;
language: BundledLanguage;
themes: [string, string];
}
// HighlightResult - Shiki's TokensResult type
type HighlightResult = TokensResult;Programmatic Highlighting
Use the plugin directly for custom highlighting:
import { code } from '@streamdown/code';
// Check language support
if (code.supportsLanguage('typescript')) {
code.highlight(
{ code: 'const x = 1;', language: 'typescript', themes: ['github-light', 'github-dark'] },
(result) => {
// Handle highlighted tokens
console.log(result.tokens);
}
);
}