Creating Slidev Presentations
Slidev is a web-based slide maker designed for developers. Write slides in Markdown, leverage Vue 3 components, and export to PDF, PPTX, or PNG. Ideal for technical presentations, demos, and interactive content.
Quick Start
Create a New Project
npm init slidev # or pnpm create slidev
Basic Commands
npm run dev # Start development server (http://localhost:5173) npm run build # Build as static site npm run export # Export to PDF, PPTX, or PNG npm run format # Format slides.md
Slidev Markdown Structure
File Organization
- •slides.md - Main presentation file (default)
- •public/ - Static assets (images, files)
- •package.json - Dependencies and scripts
Slide Separators
Use --- with blank lines to separate slides:
--- layout: cover --- # Title Slide --- # Content Slide
Frontmatter Configuration
Headmatter (First Slide)
Configure the entire presentation in the first slide's frontmatter:
--- theme: default title: My Presentation info: Presentation description author: Your Name highlighter: shiki lineNumbers: true mdc: true css: unocss shiki: theme: nord layout: cover ---
Per-Slide Frontmatter
Configure individual slides:
---
layout: two-cols
background: url('/bg.jpg')
clicks: 3
transition: slide-left
---
Key Frontmatter Options
| Option | Values | Purpose |
|---|---|---|
theme | default, dark, custom theme | Presentation theme |
layout | cover, default, two-cols, image-right, center | Slide layout |
background | URL or color (#0D1117) | Slide background |
transition | slide-left, fade, none | Slide transition animation |
clicks | Number | Animation click steps |
hideInToc | Boolean | Hide from table of contents |
disabled | Boolean | Skip slide in export |
preload | Boolean | Preload before navigation |
Markdown Features
Code Blocks with Syntax Highlighting
\`\`\`typescript async function agent() { const skills = await Skill.all(); }
\`\`\`
\`\`\`python {1,3}
# Line 1 highlighted
print("not highlighted") print("highlighted") \`\`\`
Scoped CSS
Add styles to specific slides:
<style scoped>
h1 {
color: #58A6FF;
}
</style>
Vue Components
Use Vue 3 components in slides:
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">
Count: {{ count }}
</button>
</template>
Presenter Notes
Add notes visible only to presenter:
--- layout: cover --- # Title Slide <!-- This is a presenter note, not shown to audience -->
Common Layouts
Cover Slide
--- layout: cover --- # My Presentation
Title + Content
--- layout: default --- # Section Title - Bullet point 1 - Bullet point 2
Two Columns
--- layout: two-cols --- ::left:: # Left Column Content ::right:: # Right Column Content
Image Right
--- layout: image-right image: /path/to/image.png --- # Title Content on left, image on right
Center Layout
--- layout: center --- # Centered Content
Styling Slides
Inline Styles
<div style="color: #58a6ff; font-size: 24px"> Styled text </div>
CSS Classes
<div class="text-blue-500 text-xl font-bold"> Styled with UnoCSS </div>
Global Styles
Add to headmatter <style> block:
---
## ...
<style>
.slidev-layout {
background: #0D1117 !important;
}
h1 {
color: #F8FAFC !important;
}
</style>
Advanced Features
Diagrams with Mermaid
\`\`\`mermaid graph LR A[Start] --> B[Process] --> C[End] \`\`\`
LaTeX Math
$$
E = mc^2
$$
Inline: $\alpha = \frac{\beta}{\gamma}$
Animations & Clicks
--- clicks: 3 --- # Title <v-click>This appears on click 1</v-click> <v-click>This appears on click 2</v-click>
Draggable Elements
<div v-drag="'id-key'" style="position: absolute;"> Drag me around </div>
Exporting Presentations
Export to PDF
npm run export -- --format pdf npm run export -- --format pdf --output my-slides.pdf
Export to PPTX
npm run export -- --format pptx # All slides exported as images for compatibility
Export to PNG
npm run export -- --format png # Creates PNG for each slide in dist/
Export with Animations
npm run export -- --format pdf --with-clicks # Exports multiple pages per slide with animation steps
Export Options
# Specific slide range npm run export -- --range 1,3-5,10 # Dark mode npm run export -- --dark # Increase timeout for large presentations npm run export -- --timeout 60000 # Add table of contents npm run export -- --with-toc
Configuration File (slidev.config.ts)
Create slidev.config.ts for advanced configuration:
import { defineConfig } from "@slidev/cli";
export default defineConfig({
// Enable/disable features
monaco: true,
twoslash: true,
recorder: true,
// Export settings
export: {
format: "pdf",
timeout: 30000,
dark: false,
},
// Theme configuration
themeConfig: {
primary: "#5d8392",
},
});
Best Practices
Content Organization
- •Keep headmatter clean and focused
- •Use descriptive slide titles
- •One idea per slide
- •Limit bullet points to 3-5 per slide
Code in Presentations
- •Use syntax highlighting with language specification
- •Highlight important lines with
{1,3} - •Show complete, runnable examples
- •Explain code before revealing it with
<v-click>
Styling
- •Use consistent color scheme
- •Define global styles in headmatter
- •Use scoped styles for slide-specific customization
- •Test dark mode for exports
Interactive Elements
- •Use Vue components for dynamic content
- •Add click animations for complex topics
- •Include live code examples with Monaco editor
- •Record demos when presenting remotely
Accessibility
- •Use semantic HTML elements
- •Ensure sufficient color contrast
- •Provide alt text for images
- •Test with screen readers
Common Issues
Blank First Page
Ensure headmatter is properly formatted and includes layout: cover if needed.
First --- marks headmatter start, second --- marks headmatter end.
Code Block Rendering Issues
- •Verify language is specified:
```typescript - •Ensure blank lines around code blocks
- •Use proper escaping for special characters
Export Failures
- •Install Playwright:
npm install -D playwright-chromium - •Use modern Chromium browser
- •Increase timeout for large presentations
- •Check for missing fonts or images
Styling Not Applied
- •Use
!importantfor global overrides - •Scope CSS with
<style scoped> - •Check CSS specificity
- •Clear browser cache
Resources
- •Official Docs: https://sli.dev
- •GitHub: https://github.com/slidevjs/slidev
- •Discord: https://chat.sli.dev
- •Examples: https://sli.dev/resources/theme-gallery
Integration with Development Workflow
Version Control
- •Commit
slides.mdto git - •Ignore
dist/,node_modules/,.git-pptx/ - •Use
.gitignore:codedist/ node_modules/ *.pdf *.pptx *.png
CI/CD Export
# GitHub Actions example - name: Export slides to PDF run: npx slidev export --format pdf
Embedding in Web Projects
Build as static site and host:
npm run build # Deploy dist/ folder to web server
Example: Technical Presentation Template
---
theme: default
background: "#0D1117"
title: Agent Skills Integration
author: Your Name
highlighter: shiki
layout: cover
---
<style>
.slidev-layout {
background: #0D1117 !important;
}
h1, h2, h3 {
color: #F8FAFC !important;
}
p, li {
color: #E2E8F0 !important;
}
</style>
# Agent Skills Integration
Building reusable skill components
---
# Overview
- Skill definition and structure
- Automatic discovery
- System prompt injection
- Tool registration
---
# Implementation
\`\`\`typescript export function createSkillTool(skills: SkillInfo[]) { return
tool({ description: 'Load a skill', execute: async ({ name }) => { return await
Skill.load(name); }, }); } \`\`\`
---
layout: center
---
# Questions?
Workflow for Creating Professional Presentations
- •Plan: Outline content and structure
- •Draft: Write slides.md with basic content
- •Style: Add CSS, themes, and layout configuration
- •Animate: Add interactions and animations
- •Test: Preview in browser, test exports
- •Export: Generate PDF/PPTX for distribution
- •Present: Use Slidev dev server with presenter mode
FAQ - Common Pitfalls & Solutions
Blank First Page Issue
Problem: First slide appears blank even with content defined.
Root Cause:
- •Empty space between headmatter closing
---and content - •Headmatter not properly containing opening content
- •Missing
layoutconfiguration in headmatter
Solution:
--- theme: default title: My Presentation layout: cover --- # Title Content Starts Here Immediately No blank lines between --- and content!
Key Points:
- •Headmatter must have
layout: coverfor first slide to display properly - •Content starts immediately after closing
--- - •Do NOT have blank lines between
---and#heading - •The first slide content is part of the headmatter, not a separate slide
Markdown Code Blocks in HTML Containers
Problem: Code blocks don't render when nested inside HTML <div> elements.
<!-- ❌ WRONG --> <div class="code-container"> <div class="code-content"> ```markdown const x = 1;
```markdown const x = 1; ```
</div> </div> ```Root Cause: Slidev's markdown parser requires blank lines around code blocks, even inside HTML.
Solution:
- •Add blank line BEFORE opening backticks
- •Add blank line AFTER closing backticks
- •Indent appropriately for readability
Code Block Background Colors Not Working
Problem: Global <style> color overrides for code blocks are ignored.
Root Cause: Shiki syntax highlighter applies inline styles with higher specificity, and MDC/Vue markdown rendering creates additional nested elements.
Solution: Use !important in CSS rules:
<style>
.code-content {
padding: 16px 20px;
background: #0F172A !important;
color: #F1F5F9;
}
.code-content pre {
background: #0F172A !important;
}
.code-content code {
background: #0F172A !important;
color: #F1F5F9 !important;
}
</style>
Headings Appear Black in Dark Theme
Problem: <h1>, <h2>, <h3> tags render in black despite global style
definitions.
Root Cause:
- •Default theme styles have high specificity
- •Vue component scoping interferes with global selectors
- •CSS classes generated by Slidev override simple selectors
Solution: Define heading styles in headmatter <style> block with multiple
selector specificity:
<style>
/* Use both bare selectors AND .slidev-layout selectors */
h1, h2, h3 {
color: #F8FAFC !important;
}
.slidev-layout h1 {
color: #F8FAFC !important;
}
.slidev-layout h2 {
color: #F8FAFC !important;
}
.slidev-layout h3 {
color: #F8FAFC !important;
}
</style>
Inconsistent Styling Across Multiple Slides
Problem: Some slides have correct styling, others appear broken (wrong background, missing colors).
Root Cause: Individual slides not inheriting global frontmatter
configuration. Each slide using src: import needs its own frontmatter.
Solution: Either:
- •Merge all slides into single file (Recommended for small presentations):
--- theme: default background: "#0D1117" layout: cover --- <style> /* Global styles here */ </style> # First Slide --- # Second Slide --- # Third Slide
- •Or add frontmatter to each external slide file:
--- background: "#0D1117" --- # Slide Content
Using src: Import Creates Empty Blank Slide
Problem: Using src: ./slides/01-cover.md in frontmatter creates an
unwanted blank page.
Root Cause: Slidev treats src: import as a slide reference within the
frontmatter, creating a slide separator.
Solution: Don't use src: in headmatter. Merge all content into single
slides.md file:
<!-- ❌ WRONG --> --- ## theme: default src: ./slides/01-cover.md <!-- ✅ CORRECT --> --- ## theme: default <style> /* styles */ </style> # Content here --- # Next slide
Font/Color Changes Not Visible
Problem: CSS color definitions work locally but fail in exports (PDF/PPTX).
Root Cause:
- •Browser uses fallback fonts in export
- •CSS specificity issues in print context
- •Missing
!importantflags
Solution:
<style>
/* Always use !important for export compatibility */
h1 {
color: #F8FAFC !important;
}
p {
color: #E2E8F0 !important;
}
code {
background: #1E293B !important;
color: #38BDF8 !important;
}
</style>
Export Command Not Found
Problem: slidev export command fails or not recognized.
Root Cause: @slidev/cli not installed or playwright-chromium missing.
Solution:
# Install/reinstall dependencies npm install # Install playwright for export npm install -D playwright-chromium # Try export again npm run export -- --format pdf
Special Characters in Code Blocks Break Rendering
Problem: Angle brackets <>, curly braces {} in code blocks cause parsing
errors or display issues.
Root Cause: Vue/MDC markdown parser treats these as component syntax.
Solution: In inline code within markdown content, use HTML entities:
- •
<→< - •
>→> - •
{→{ - •
}→}
Generate `<available_skills>` XML list <!-- For code blocks, this usually isn't needed --> \`\`\`typescript const xml = `<skill>data</skill>`; \`\`\`
Scoped Styles Not Applying
Problem: <style scoped> block doesn't affect slide elements.
Root Cause: Vue scoping requires scoped attribute AND proper element
hierarchy.
Solution:
---
layout: default
---
<style scoped>
/* Scoped styles only affect direct children of this slide */
h2 {
color: #58A6FF;
}
.custom-class {
font-weight: bold;
}
</style>
# Title
<div class="custom-class">Affected by scoped style</div>
Images Not Loading in Presentation
Problem: Images referenced in slides don't display.
Root Cause: Incorrect path references. Slidev serves static assets from
public/ folder.
Solution:
<!-- ❌ WRONG --> <img src="./images/pic.png"> <!-- ✅ CORRECT --> <img src="/images/pic.png"> <!-- Even simpler for images in public/ root --> <img src="/pic.png"> <!-- Markdown image syntax also works --> 
Store images in public/ folder at project root.
Large Presentations Take Forever to Export
Problem: slidev export takes many minutes or times out.
Root Cause: Complex layouts, large code blocks, or too many animations requiring render time.
Solution:
# Increase timeout (in milliseconds) npm run export -- --format pdf --timeout 60000 # Add wait time between slides npm run export -- --format pdf --wait 1000 # Export specific slide range for testing npm run export -- --range 1-5 # Omit animations to speed up rendering npm run export -- --format pdf --with-clicks false
Presenter Notes Not Showing
Problem: HTML comments added as presenter notes don't appear in presenter view.
Root Cause: Notes must be placed at the END of the slide, not at the beginning.
Solution:
--- layout: default --- # Slide Title Visible content here. <!-- This is NOT a note - too early --> More content. <!-- This IS a presenter note - at the end of slide -->
Notes appear in the Slidev UI presenter panel when you click the presentation.
Line Highlighting in Code Blocks Not Working
Problem: Line number ranges like {1,3} don't highlight specified lines.
Root Cause:
- •Language not specified for code block
- •Syntax:
{1,3}must immediately follow backticks and language - •Shiki highlighter requires proper configuration
Solution:
<!-- ✅ CORRECT -->
\`\`\`typescript {1,3} const a = 1; // Line 1 - highlighted const b = 2; // Line
2 - normal const c = 3; // Line 3 - highlighted \`\`\`
<!-- ❌ WRONG - no language or space before braces -->
\`\`\` {1,3} const a = 1; \`\`\`
Theme Not Applying Globally
Problem: Changing theme: in headmatter has no effect.
Root Cause: Theme must be specified BEFORE other configuration. Some configurations override theme defaults.
Solution:
--- # THEME MUST BE FIRST theme: default # Then other config title: My Presentation background: '#0D1117' # Per-slide overrides at the end layout: cover ---
If using custom theme, ensure it's installed:
npm install @slidev/theme-myname
Then:
--- theme: myname ---