A markdown-based presentation builder built with Next.js, MDX, and Framer Motion. Create beautiful, AI-agent-friendly slides using simple .mdx files with frontmatter configuration.
- MDX-based slides - Write slides in Markdown with YAML frontmatter
- Animated transitions - Smooth Framer Motion animations between slides
- Six slide types: Hero, Timeline, Messages, Stats, Quote, and Terminal
- Automatic ordering - Slides are sorted alphabetically by filename
- Syntax highlighting - Prism-based code highlighting for technical demos
- Frontmatter validation - Catch errors before they break your presentation
- AI-ready - Clean JSON types and programmatic control for AI agents
cd preso-builder
npm install
npm run devOpen http://localhost:3000 to view the presentation.
Vision Deck includes a built-in demo showcasing all 6 slide types. The demo slides are numbered 10- through 12- to appear after the existing example slides.
| # | Slide | Description |
|---|---|---|
| 10 | Stats | Platform statistics with animated counters |
| 11 | Quote | Testimonial with author attribution |
| 12 | Terminal | Code walkthrough with syntax highlighting |
The demo is included in the default installation:
npm run dev
# Open http://localhost:3000
# Navigate through all slides using arrow keys or click the dotsapp/slides/
├── 10-demo-stats.mdx # Stats slide demo
├── 11-demo-quote.mdx # Quote slide demo
└── 12-demo-terminal.mdx # Terminal slide demo
npm run validate
# ✅ All slides are valid!Add .mdx files to the app/slides/ directory. Slides are automatically sorted and rendered in alphabetical order.
For title slides with a main heading and subtitle:
---
type: hero
title: "Your Title Here"
subtitle: "Your subtitle or tagline"
---For displaying a chronological sequence of events:
---
type: timeline
title: "Timeline Title"
subtitle: "Optional subtitle"
points:
- date: "2024 Q1"
title: "First milestone"
- date: "2024 Q2"
title: "Second milestone"
- date: "2024 Q3"
title: "Third milestone"
---For displaying cards with icons and descriptions:
---
type: messages
title: "Key Messages"
cards:
- number: "01"
title: "First Message"
icon: "rocket"
description: "Description of your first message"
- number: "02"
title: "Second Message"
icon: "star"
description: "Description of your second message"
- number: "03"
title: "Third Message"
icon: "zap"
description: "Description of your third message"
---For KPIs and metrics with animated counters:
---
type: stats
title: "Our Impact"
subtitle: "2024 Annual Report"
layout: "grid" # options: "grid" | "row" | "columns"
stats:
- value: 1000
label: "Total Users"
suffix: "+"
- value: 99.9
label: "Uptime"
suffix: "%"
- value: 50000
label: "Revenue"
prefix: "$"
- value: 150
label: "Team Members"
---For testimonials and inspiring quotes:
---
type: quote
quote: "The future belongs to those who believe in the beauty of their dreams."
author: "Eleanor Roosevelt"
title: "Visionary Leader"
company: "Historical Figures Inc."
avatar: "https://example.com/avatar.jpg" # Optional
background: "gradient" # options: "gradient" | "minimal" | "accent"
---For code demonstrations and command tutorials:
---
type: terminal
title: "Quick Start"
theme: "dark" # options: "dark" | "light" | "monokai"
commands:
# Terminal command style (with prompt)
- prompt: "~"
command: "npm install vision-deck"
output: "added 3 packages in 2s"
# Code block style (no prompt, specify language)
- command: |
import { createDeck } from 'vision-deck'
const deck = await createDeck({
theme: 'dark',
slides: ['./slides/*.mdx']
})
await deck.present()
language: "typescript"
---Use these components directly in your slide content for rich formatting:
<Callout type="info" title="Note">
This is an informational callout box.
</Callout>
<Highlight color="yellow">Important text</Highlight>
<Badge variant="success">New Feature</Badge>
<Progress value={75} label="Completion" />
<Step number={1} title="First Step">
Content for step 1
</Step>| Component | Props | Description |
|---|---|---|
<Callout> |
type?, title? |
Info/warning/success/error boxes |
<Highlight> |
color? |
Text highlighting (yellow, green, blue, pink, purple) |
<Badge> |
variant?, size? |
Status badges |
<Progress> |
value, label?, showValue?, color? |
Animated progress bars |
<Code> |
- | Inline code styling |
<Counter> |
value, prefix?, suffix? |
Animated number counters |
<AnimatedNumber> |
value, decimals? |
Precise animated numbers |
<Step> |
number, title, active? |
Step-by-step content |
<AccordionItem> |
title, defaultOpen? |
Collapsible sections |
The Messages slide supports icons from Lucide React:
rocket,star,zap,lightning(alias for zap)target,crosshair,compasstrending-up,growth,chartshield,lock,keyheart,smile,users- And any other Lucide React icon name
Copy templates from the templates/ directory to app/slides/:
cp templates/stats.mdx.template app/slides/06-stats.mdx
cp templates/quote.mdx.template app/slides/07-quote.mdx
cp templates/terminal.mdx.template app/slides/08-terminal.mdxRun the validation script to check your slides for errors:
npm run validateThis will verify:
- Required frontmatter fields are present
- Array fields have content
- Slide types are valid
Use numbered prefixes to control slide order:
01-hero.mdx
02-timeline.mdx
03-messages.mdx
04-stats.mdx
05-quote.mdx
06-terminal.mdx
preso-builder/
├── app/
│ ├── slides/ # Add your .mdx slide files here
│ │ ├── 01-hero.mdx
│ │ ├── 02-timeline.mdx
│ │ └── ...
│ ├── api/
│ │ └── slides/ # API endpoint for loading slides
│ ├── layout.tsx
│ └── page.tsx
├── components/
│ ├── slides/ # Slide component definitions
│ │ ├── HeroSlide.tsx
│ │ ├── TimelineSlide.tsx
│ │ ├── MessagesSlide.tsx
│ │ ├── StatsSlide.tsx
│ │ ├── QuoteSlide.tsx
│ │ └── TerminalSlide.tsx
│ └── mdx/ # MDX components for slide content
│ └── MDXComponents.tsx
├── lib/
│ ├── slides.ts # Slide loading & parsing logic
│ ├── slides-client.ts # Client-side types
│ └── validate-slides.ts # Frontmatter validation
├── templates/ # Slide templates
│ ├── stats.mdx.template
│ ├── quote.mdx.template
│ └── terminal.mdx.template
└── public/ # Static assets
npm run dev # Start development server
npm run build # Build for production
npm run start # Start production server
npm run lint # Run ESLint
npm run validate # Validate slide frontmatter- Next.js 16 - React framework
- React 19 - UI library
- MDX - Markdown with JSX
- Framer Motion - Animations
- Tailwind CSS 4 - Styling
- gray-matter - YAML frontmatter parsing
- next-mdx-remote - MDX compilation
- Lucide React - Icons
- prism-react-renderer - Syntax highlighting
Vision Deck is designed for AI agent usage:
import { loadSlides, SlideData } from '@/lib/slides-client';
// Load all slides
const slides: SlideData[] = await loadSlides();
// Access slide content programmatically
for (const slide of slides) {
console.log(`Slide ${slide.id}: ${slide.content.type}`);
}All slide content is strongly typed:
type SlideContent =
| HeroSlideContent
| TimelineSlideContent
| MessagesSlideContent
| StatsSlideContent
| QuoteSlideContent
| TerminalSlideContent;GET /api/slides- Returns all slides as JSON for programmatic access
Deploy to Vercel with zero configuration:
npm run buildThen connect your repository to Vercel.
- Define the content type interface in
lib/slides.tsandlib/slides-client.ts - Create a new component in
components/slides/ - Add the component to
app/page.tsxfor rendering - Add validation schema in
lib/validate-slides.ts - Use the new slide type in your
.mdxfiles
Modify app/globals.css for global styles or use Tailwind utility classes in individual slide components.