ai-vibe-slides
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAI Vibe Slides — Beautiful HTML Slide Decks, Ready to Present
AI Vibe Slides — 美观的HTML幻灯片,随时可演示
Goal
目标
Produce a single HTML or React artifact file containing a complete slide deck that can:
- Present fullscreen directly in the browser
- Navigate via arrow keys, spacebar, or click
- Look professional, polished, and stylistically consistent
- Print or export to PDF when needed
Inspired by banana-slides: a 3-step pipeline of Idea → Outline → Finished Slides, but the output is a self-contained HTML file instead of a fullstack application.
生成单个HTML或React文件,包含完整的幻灯片演示文稿,具备以下功能:
- 可直接在浏览器中全屏展示
- 通过箭头键、空格键或点击进行导航
- 外观专业、精致,风格统一
- 需要时可打印或导出为PDF
灵感来源于banana-slides:采用想法 → 大纲 → 成品幻灯片的三步流程,但输出为独立HTML文件而非全栈应用。
Slide Creation Pipeline
幻灯片创建流程
Step 1: Understand the Request → Build an Outline
步骤1:理解需求 → 构建大纲
When the user provides a request, first build an outline mentally (no need to display it unless the user asks):
- Identify the main topic and target audience (students, business, tech talk...)
- Break it into logical sections:
- Slide 1: Cover (title + subtitle + author)
- Slides 2-3: Introduction / context
- Middle slides: Core content (one key idea per slide)
- Final slide: Conclusion / Call to action / Thank you
- Each slide should have: a title, 2-5 bullet points or visual content, and a layout type
If the user only gives a short sentence (e.g., "create slides about AI in healthcare"), automatically expand it into 8-12 slides with a logical structure.
当用户提出需求时,首先在脑海中构建大纲(除非用户要求,否则无需展示):
- 确定主题和目标受众(学生、商务人士、技术演讲听众等)
- 将内容拆分为逻辑章节:
- 第1页:封面(标题+副标题+作者)
- 第2-3页:介绍/背景
- 中间页面:核心内容(每页一个关键观点)
- 最后一页:结论/行动号召/致谢
- 每页幻灯片应包含:标题、2-5个要点或视觉内容,以及布局类型
如果用户仅提供短句(例如“创建关于医疗AI的幻灯片”),自动将其扩展为8-12页结构合理的幻灯片。
Step 2: Choose a Design Direction
步骤2:选择设计方向
Based on context, commit to one clear design direction:
| Context | Suggested Style |
|---|---|
| Startup pitch deck | Bold, dark theme, gradient accents, strong sans-serif |
| Academic / education | Clean, light, diagram-heavy, readable fonts |
| Tech talk / conference | Modern dark, code-style typography, neon accents |
| Corporate / report | Minimal, professional, navy/white, serif headings |
| Creative / marketing | Colorful, asymmetric layout, bold typography |
| Kids / early education | Pastel, rounded corners, playful icons, large text |
General rules:
- Pick 2-3 primary colors and use them consistently across the entire deck
- 1 heading font + 1 body font (use Google Fonts)
- Minimal text, generous whitespace — max 5-6 lines per slide
- Clear visual hierarchy: large title → medium content → small notes
根据场景确定清晰的设计风格:
| 场景 | 推荐风格 |
|---|---|
| 初创企业推介演示文稿 | 大胆深色主题、渐变点缀、醒目无衬线字体 |
| 学术/教育场景 | 简洁浅色、重图表、易读字体 |
| 技术演讲/会议 | 现代深色、代码风格排版、霓虹色点缀 |
| 企业/报告 | 极简专业、蓝白配色、衬线标题 |
| 创意/营销 | 色彩丰富、不对称布局、醒目排版 |
| 儿童/早教 | 马卡龙色系、圆角、趣味图标、大字体 |
通用规则:
- 选择2-3种主色调,并在整个演示文稿中保持一致
- 1种标题字体 + 1种正文字体(使用Google Fonts)
- 文字精简、留白充足——每页最多5-6行文字
- 清晰的视觉层级:大标题 → 中等内容 → 小注释
Step 3: Generate the HTML/React Slide Deck
步骤3:生成HTML/React幻灯片演示文稿
Create a single file ( or ) containing everything:
.html.jsx创建单个文件(或),包含所有内容:
.html.jsxHTML Slide Deck Structure
HTML幻灯片演示文稿结构
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{Presentation Title}</title>
<link
href="https://fonts.googleapis.com/css2?family={Font1}&family={Font2}&display=swap"
rel="stylesheet"
/>
<style>
/* === RESET + BASE === */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* === SLIDE CONTAINER === */
.slide-deck {
width: 100vw;
height: 100vh;
overflow: hidden;
position: relative;
}
.slide {
width: 100%;
height: 100%;
display: none;
flex-direction: column;
justify-content: center;
padding: 60px 80px;
position: absolute;
top: 0;
left: 0;
}
.slide.active {
display: flex;
}
/* === TYPOGRAPHY === */
h1 {
font-family: "{Font1}", sans-serif;
font-size: 3.2rem;
margin-bottom: 1rem;
}
h2 {
font-family: "{Font1}", sans-serif;
font-size: 2.4rem;
margin-bottom: 1.5rem;
}
p,
li {
font-family: "{Font2}", sans-serif;
font-size: 1.4rem;
line-height: 1.8;
}
/* === THEME COLORS === */
:root {
--bg-primary: #0f172a;
--bg-slide: #1e293b;
--text-primary: #f8fafc;
--text-secondary: #94a3b8;
--accent: #3b82f6;
--accent-2: #8b5cf6;
}
/* === NAVIGATION UI === */
.nav-hint {
position: fixed;
bottom: 20px;
right: 30px;
font-size: 0.8rem;
color: var(--text-secondary);
opacity: 0.5;
}
.slide-counter {
position: fixed;
bottom: 20px;
left: 30px;
font-size: 0.8rem;
color: var(--text-secondary);
}
/* === TRANSITIONS === */
.slide {
animation: fadeIn 0.4s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* === LAYOUT VARIANTS === */
.slide.cover {
justify-content: center;
align-items: center;
text-align: center;
}
.slide.two-column {
flex-direction: row;
gap: 60px;
align-items: center;
}
.slide.two-column .col {
flex: 1;
}
.slide.centered {
align-items: center;
text-align: center;
}
/* === VISUAL ELEMENTS === */
.card {
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 24px;
margin: 8px 0;
}
.badge {
display: inline-block;
background: var(--accent);
color: white;
padding: 4px 14px;
border-radius: 20px;
font-size: 0.85rem;
}
.divider {
width: 60px;
height: 4px;
background: var(--accent);
border-radius: 2px;
margin: 16px 0;
}
.icon-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
}
/* === PRINT / PDF EXPORT === */
@media print {
.slide {
page-break-after: always;
display: flex !important;
position: relative;
}
.nav-hint,
.slide-counter {
display: none;
}
}
</style>
</head>
<body>
<div class="slide-deck" id="deck">
<!-- SLIDE 1: COVER -->
<div
class="slide cover active"
style="background: linear-gradient(135deg, var(--bg-primary), #1a1a2e);"
>
<div class="badge">Topic</div>
<h1 style="font-size: 3.8rem; margin-top: 20px;">Main Title</h1>
<p
style="color: var(--text-secondary); font-size: 1.3rem; margin-top: 12px;"
>
Short subtitle description
</p>
<div class="divider" style="margin: 20px auto;"></div>
<p style="color: var(--text-secondary); font-size: 1rem;">
Author — Date
</p>
</div>
<!-- SLIDE 2+: CONTENT -->
<div class="slide">
<h2>Slide Title</h2>
<div class="divider"></div>
<ul>
<li>Key point 1</li>
<li>Key point 2</li>
<li>Key point 3</li>
</ul>
</div>
<!-- ... more slides ... -->
</div>
<div class="slide-counter">
<span id="current">1</span> / <span id="total"></span>
</div>
<div class="nav-hint">← → or click to navigate</div>
<script>
const slides = document.querySelectorAll(".slide");
let currentSlide = 0;
document.getElementById("total").textContent = slides.length;
function showSlide(n) {
slides[currentSlide].classList.remove("active");
currentSlide = (n + slides.length) % slides.length;
slides[currentSlide].classList.add("active");
document.getElementById("current").textContent = currentSlide + 1;
}
document.addEventListener("keydown", (e) => {
if (e.key === "ArrowRight" || e.key === " ")
showSlide(currentSlide + 1);
if (e.key === "ArrowLeft") showSlide(currentSlide - 1);
if (e.key === "f") document.documentElement.requestFullscreen?.();
if (e.key === "Escape") document.exitFullscreen?.();
});
document.querySelector(".slide-deck").addEventListener("click", (e) => {
const x = e.clientX / window.innerWidth;
x > 0.5 ? showSlide(currentSlide + 1) : showSlide(currentSlide - 1);
});
</script>
</body>
</html>html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{Presentation Title}</title>
<link
href="https://fonts.googleapis.com/css2?family={Font1}&family={Font2}&display=swap"
rel="stylesheet"
/>
<style>
/* === RESET + BASE === */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* === SLIDE CONTAINER === */
.slide-deck {
width: 100vw;
height: 100vh;
overflow: hidden;
position: relative;
}
.slide {
width: 100%;
height: 100%;
display: none;
flex-direction: column;
justify-content: center;
padding: 60px 80px;
position: absolute;
top: 0;
left: 0;
}
.slide.active {
display: flex;
}
/* === TYPOGRAPHY === */
h1 {
font-family: "{Font1}", sans-serif;
font-size: 3.2rem;
margin-bottom: 1rem;
}
h2 {
font-family: "{Font1}", sans-serif;
font-size: 2.4rem;
margin-bottom: 1.5rem;
}
p,
li {
font-family: "{Font2}", sans-serif;
font-size: 1.4rem;
line-height: 1.8;
}
/* === THEME COLORS === */
:root {
--bg-primary: #0f172a;
--bg-slide: #1e293b;
--text-primary: #f8fafc;
--text-secondary: #94a3b8;
--accent: #3b82f6;
--accent-2: #8b5cf6;
}
/* === NAVIGATION UI === */
.nav-hint {
position: fixed;
bottom: 20px;
right: 30px;
font-size: 0.8rem;
color: var(--text-secondary);
opacity: 0.5;
}
.slide-counter {
position: fixed;
bottom: 20px;
left: 30px;
font-size: 0.8rem;
color: var(--text-secondary);
}
/* === TRANSITIONS === */
.slide {
animation: fadeIn 0.4s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* === LAYOUT VARIANTS === */
.slide.cover {
justify-content: center;
align-items: center;
text-align: center;
}
.slide.two-column {
flex-direction: row;
gap: 60px;
align-items: center;
}
.slide.two-column .col {
flex: 1;
}
.slide.centered {
align-items: center;
text-align: center;
}
/* === VISUAL ELEMENTS === */
.card {
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 24px;
margin: 8px 0;
}
.badge {
display: inline-block;
background: var(--accent);
color: white;
padding: 4px 14px;
border-radius: 20px;
font-size: 0.85rem;
}
.divider {
width: 60px;
height: 4px;
background: var(--accent);
border-radius: 2px;
margin: 16px 0;
}
.icon-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
}
/* === PRINT / PDF EXPORT === */
@media print {
.slide {
page-break-after: always;
display: flex !important;
position: relative;
}
.nav-hint,
.slide-counter {
display: none;
}
}
</style>
</head>
<body>
<div class="slide-deck" id="deck">
<!-- SLIDE 1: COVER -->
<div
class="slide cover active"
style="background: linear-gradient(135deg, var(--bg-primary), #1a1a2e);"
>
<div class="badge">Topic</div>
<h1 style="font-size: 3.8rem; margin-top: 20px;">Main Title</h1>
<p
style="color: var(--text-secondary); font-size: 1.3rem; margin-top: 12px;"
>
Short subtitle description
</p>
<div class="divider" style="margin: 20px auto;"></div>
<p style="color: var(--text-secondary); font-size: 1rem;">
Author — Date
</p>
</div>
<!-- SLIDE 2+: CONTENT -->
<div class="slide">
<h2>Slide Title</h2>
<div class="divider"></div>
<ul>
<li>Key point 1</li>
<li>Key point 2</li>
<li>Key point 3</li>
</ul>
</div>
<!-- ... more slides ... -->
</div>
<div class="slide-counter">
<span id="current">1</span> / <span id="total"></span>
</div>
<div class="nav-hint">← → or click to navigate</div>
<script>
const slides = document.querySelectorAll(".slide");
let currentSlide = 0;
document.getElementById("total").textContent = slides.length;
function showSlide(n) {
slides[currentSlide].classList.remove("active");
currentSlide = (n + slides.length) % slides.length;
slides[currentSlide].classList.add("active");
document.getElementById("current").textContent = currentSlide + 1;
}
document.addEventListener("keydown", (e) => {
if (e.key === "ArrowRight" || e.key === " ")
showSlide(currentSlide + 1);
if (e.key === "ArrowLeft") showSlide(currentSlide - 1);
if (e.key === "f") document.documentElement.requestFullscreen?.();
if (e.key === "Escape") document.exitFullscreen?.();
});
document.querySelector(".slide-deck").addEventListener("click", (e) => {
const x = e.clientX / window.innerWidth;
x > 0.5 ? showSlide(currentSlide + 1) : showSlide(currentSlide - 1);
});
</script>
</body>
</html>Slide Layout Types
幻灯片布局类型
Each slide should use the layout that best fits its content:
每页幻灯片应选择最适合其内容的布局:
1. Cover Slide
1. 封面幻灯片
- Centered, extra-large font, gradient background
- Topic badge + main title + subtitle + author
- 居中对齐、超大字体、渐变背景
- 主题标签+主标题+副标题+作者
2. Section Divider
2. 章节分隔页
- Only section title + number, accent color background
- Used to separate major sections of the presentation
- 仅显示章节标题+编号,点缀色背景
- 用于分隔演示文稿的主要章节
3. Content + Bullets
3. 内容+要点
- Left-aligned title + list of key points
- Use icons/emoji at the start of each bullet instead of plain dots
- 左对齐标题+关键要点列表
- 用图标/表情符号替代普通圆点作为要点前缀
4. Two-Column
4. 双栏布局
- layout: text on left, visuals/list/cards on right
.two-column - Great for comparisons, before-after, text+illustration
- 布局:左侧文字,右侧视觉内容/列表/卡片
.two-column - 非常适合对比、前后变化、文字+插图场景
5. Cards Grid
5. 卡片网格
- 2-3 column grid, each card containing icon + title + short description
- Great for features, benefits, team members
- 2-3列网格,每张卡片包含图标+标题+简短描述
- 适合展示功能、优势、团队成员
6. Big Number / Statistic
6. 大数字/统计数据
- Huge number in the center (font-size: 5rem+) + small label below
- Great for data points, KPIs, impact numbers
- 屏幕中央显示超大数字(字体大小≥5rem)+下方小标签
- 适合展示数据点、关键绩效指标(KPI)、影响数值
7. Quote / Highlight
7. 引用/高亮
- Large text, centered, with decorative quotation marks
- Different background (light accent color)
- 大字体、居中对齐,搭配装饰性引号
- 使用不同背景(浅点缀色)
8. Timeline / Steps
8. 时间线/步骤
- Horizontal or vertical flexbox, dots connecting each step
- Great for processes, roadmaps, history
- 水平或垂直弹性布局,用圆点连接各步骤
- 适合展示流程、路线图、历史
9. Thank You / CTA
9. 致谢/行动号召
- Centered, simple, contact info or call to action
- 居中对齐、简洁明了,包含联系方式或行动号召
MANDATORY Design Rules
强制设计规则
- 16:9 aspect ratio: Always use — each slide fills the entire screen
width: 100vw; height: 100vh - Minimal text: Maximum 6 lines per slide. If content is long → split into multiple slides
- Large font sizes: Heading ≥ 2.4rem, body ≥ 1.3rem — must be readable on a projector
- High contrast: Text must be clearly legible against its background. Verify visually
- Consistency: Same fonts, same color palette, same spacing throughout the entire deck
- No placeholder images: Never use . Replace with CSS shapes, gradients, icons (emoji or Lucide for React), or inline SVGs
<img src="placeholder"> - Subtle animation: Only fadeIn on slide transition. No complex animations that distract
- Responsive fullscreen: Must work well at all screen sizes
- Print-ready: Include rules so each slide becomes one printed page
@media print
- 16:9宽高比:始终使用——每页幻灯片填满整个屏幕
width: 100vw; height: 100vh - 文字精简:每页最多6行文字。如果内容过长→拆分为多页
- 大字体:标题≥2.4rem,正文≥1.3rem——确保在投影仪上清晰可读
- 高对比度:文字与背景必须清晰可辨。需视觉验证
- 一致性:整个演示文稿使用相同字体、配色方案、间距
- 无占位图片:绝不使用。替换为CSS形状、渐变、图标(表情符号或React的Lucide图标)或内联SVG
<img src="placeholder"> - 微妙动画:仅在幻灯片切换时使用淡入效果。避免使用分散注意力的复杂动画
- 响应式全屏:在所有屏幕尺寸下都能正常显示
- 可打印:包含规则,使每页幻灯片对应一个打印页面
@media print
When Using React (.jsx) Instead of HTML
使用React (.jsx)替代HTML的情况
If creating a React artifact, use this pattern:
jsx
import { useState, useEffect, useCallback } from "react";
const slides = [
{ type: "cover", title: "...", subtitle: "..." },
{ type: "content", title: "...", points: ["...", "..."] },
{ type: "twoColumn", title: "...", left: "...", right: "..." },
// ...
];
export default function SlideDeck() {
const [current, setCurrent] = useState(0);
const next = useCallback(
() => setCurrent((c) => (c + 1) % slides.length),
[],
);
const prev = useCallback(
() => setCurrent((c) => (c - 1 + slides.length) % slides.length),
[],
);
useEffect(() => {
const handleKey = (e) => {
if (e.key === "ArrowRight" || e.key === " ") next();
if (e.key === "ArrowLeft") prev();
if (e.key === "f") document.documentElement.requestFullscreen?.();
};
window.addEventListener("keydown", handleKey);
return () => window.removeEventListener("keydown", handleKey);
}, [next, prev]);
const renderSlide = (slide) => {
switch (slide.type) {
case "cover":
return /* cover layout */;
case "content":
return /* content layout */;
case "twoColumn":
return /* two-column layout */;
// ...
}
};
return (
<div
className="w-screen h-screen overflow-hidden relative"
onClick={(e) => (e.clientX > window.innerWidth / 2 ? next() : prev())}
style={{ fontFamily: "'Outfit', sans-serif" }}
>
{renderSlide(slides[current])}
<div className="fixed bottom-5 left-8 text-sm opacity-40">
{current + 1} / {slides.length}
</div>
</div>
);
}Advantages of React: Tailwind CSS utilities, Lucide icons, more complex logic, recharts for charts.
如果创建React文件,采用以下模式:
jsx
import { useState, useEffect, useCallback } from "react";
const slides = [
{ type: "cover", title: "...", subtitle: "..." },
{ type: "content", title: "...", points: ["...", "..."] },
{ type: "twoColumn", title: "...", left: "...", right: "..." },
// ...
];
export default function SlideDeck() {
const [current, setCurrent] = useState(0);
const next = useCallback(
() => setCurrent((c) => (c + 1) % slides.length),
[],
);
const prev = useCallback(
() => setCurrent((c) => (c - 1 + slides.length) % slides.length),
[],
);
useEffect(() => {
const handleKey = (e) => {
if (e.key === "ArrowRight" || e.key === " ") next();
if (e.key === "ArrowLeft") prev();
if (e.key === "f") document.documentElement.requestFullscreen?.();
};
window.addEventListener("keydown", handleKey);
return () => window.removeEventListener("keydown", handleKey);
}, [next, prev]);
const renderSlide = (slide) => {
switch (slide.type) {
case "cover":
return /* cover layout */;
case "content":
return /* content layout */;
case "twoColumn":
return /* two-column layout */;
// ...
}
};
return (
<div
className="w-screen h-screen overflow-hidden relative"
onClick={(e) => (e.clientX > window.innerWidth / 2 ? next() : prev())}
style={{ fontFamily: "'Outfit', sans-serif" }}
>
{renderSlide(slides[current])}
<div className="fixed bottom-5 left-8 text-sm opacity-40">
{current + 1} / {slides.length}
</div>
</div>
);
}React的优势:可使用Tailwind CSS工具类、Lucide图标、更复杂的逻辑、recharts图表库。
Pre-Delivery Checklist
交付前检查清单
- Correct number of slides (cover + content + closing)
- Arrow keys ← → work, click navigates
- Counter displays correct "X / N"
- Press F for fullscreen
- All text is readable with sufficient contrast
- No broken images or placeholders
- Google Fonts load correctly (or good fallback)
- Print/PDF exports properly ()
@media print - Consistent style throughout the entire deck
- Each slide has exactly one key idea, not overloaded with text
- 幻灯片数量正确(封面+内容+结尾页)
- 箭头键← →可正常使用,点击可导航
- 计数器显示正确的“X / N”
- 按F键可进入全屏
- 所有文字对比度充足、清晰可读
- 无损坏图片或占位符
- Google Fonts加载正常(或有良好的备选方案)
- 打印/PDF导出功能正常(生效)
@media print - 整个演示文稿风格一致
- 每页幻灯片仅包含一个关键观点,内容不过载
Natural Language Editing
自然语言编辑
After initial creation, the user can request modifications:
- "Switch to a light theme" → update CSS variables
- "Add 2 slides about case studies" → insert slides into the array
- "Slide 3 has too much text, split it" → refactor content across slides
- "Change the font to Playfair Display" → update Google Fonts link + CSS
- "Add a chart to slide 5" → use CSS chart or recharts (React)
On each edit, keep unchanged slides intact and only update what the user requested.
初始创建完成后,用户可请求修改:
- “切换为浅色主题” → 更新CSS变量
- “添加2页关于案例研究的幻灯片” → 在数组中插入幻灯片
- “第3页文字太多,拆分它” → 将内容重构到多页幻灯片
- “将字体改为Playfair Display” → 更新Google Fonts链接+CSS
- “在第5页添加图表” → 使用CSS图表或recharts(React)
每次编辑时,保留未修改的幻灯片,仅更新用户要求的内容。