Create or update presentation notebooks with embedded HTML and JavaScript in markdown cells using EDS blocks. Convert executable code cells to informative text. Build presentations, slides, demos, showcases with accordion, cards, tabs, hero, grid, table blocks. No runnable JavaScript cells - only visual markdown with inline scripts for presentation mode.
Transform Jupyter notebooks into beautiful presentation-mode experiences using embedded HTML and JavaScript within markdown cells. Leverages EDS blocks for visual appeal while preventing code execution by users.
Interactive Notebooks (e.g., test.ipynb):
Educational Notebooks (e.g., tutorial.ipynb):
jupyter-educational-notebook skillPresentation Notebooks (e.g., demo.ipynb):
Navigation Notebooks (e.g., docs-navigation.ipynb):
docs/for-ai/templates/ipynb/navigation-template.ipynb<script> tags within markdown for interactivitySee resources/blocks-reference.md for complete details on all blocks.
Visual Layout Blocks:
accordion - Collapsible sectionscards - Card grid layoutstabs - Tabbed contentgrid - Flexible grid layoutshero - Hero bannerstable - Data tablesContent Blocks:
quote - Pull quotescolumns - Multi-column layoutsmodal - Dialog overlaysvideo - Embedded videosInteractive Blocks:
code-expander - Expandable code snippetscounter - Animated countersfloating-alert - Dismissible alertsUse /create-presentation command with:
- Topic or title
- Key sections/topics
- Desired blocks (accordion, cards, tabs, etc.)
Example:
/create-presentation "Product Demo" with sections: Features, Benefits, Pricing
Use cards for features, accordion for benefits, table for pricing
Use /create-presentation with path to existing .ipynb file
All code cells will be converted to informative markdown
Example:
/create-presentation convert education.ipynb
Keep structure but make it presentation-only
Every presentation notebook should have:
{
"metadata": {
"title": "Presentation Title",
"description": "Brief description",
"author": "Author Name",
"creation-date": "{{TODAY'S DATE IN YYYY-MM-DD FORMAT}}",
"version": "1.0",
"last-modified": "{{TODAY'S DATE IN YYYY-MM-DD FORMAT}}",
"category": "presentation",
"repo": "https://github.com/username/repo",
"manual-path": "docs/for-ai/your-documentation.md"
}
}
⚠️ CRITICAL - Version and Date Management:
version AND last-modified whenever you make ANY change to an .ipynb fileKey Fields:
title - Main presentation title (required)description - One-line summary (optional)author - Author name (optional)creation-date - Initial creation date in YYYY-MM-DD format (required, never change)version - Version tracking (required, increment on every edit)last-modified - Last modification date in YYYY-MM-DD format (required, update on every edit)category - Content category, e.g., "presentation" (optional)repo - Repository URL for linking .md files (optional)manual-path - Path to documentation for "Read the Manual" button (optional)
manual-path is providedrepo and plain .md: Creates GitHub link {repo}/blob/main/{manual-path}/...): Used as-isImportant: Do NOT automatically include a Table of Contents. The presentation template does not include a TOC by default. Only add navigation if explicitly requested by the user.
Typical structure:
Title Cell (Markdown):
# 🎯 Presentation Title
**Subtitle or tagline**
---
## Overview
Brief introduction to the presentation
Content Cells (Markdown with Embedded Blocks):
## Section Title
<div class="accordion block">
<div>
<div>Feature 1</div>
<div>Description of feature 1 with details...</div>
</div>
<div>
<div>Feature 2</div>
<div>Description of feature 2 with details...</div>
</div>
</div>
<script type="module">
// Initialize block
const block = document.querySelector('.accordion.block');
const module = await import('/blocks/accordion/accordion.js');
await module.default(block);
</script>
Navigation Cell (Markdown):
---
## 📋 Table of Contents
- [Section 1](#section-1)
- [Section 2](#section-2)
- [Conclusion](#conclusion)
Best For: FAQs, feature lists, detailed explanations
<div style="background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); border-radius: 12px; padding: 32px; margin: 0 0; border-left: 6px solid #0288d1; color: #212121;">
<h2 style="color: #0d47a1; font-size: 28px; font-weight: 700; margin-bottom: 24px;">Section Title</h2>
<div class="accordion block">
<div>
<div>Question or Title</div>
<div>Answer or detailed content here...</div>
</div>
</div>
<script type="module">
const block = document.querySelector('.accordion.block');
const module = await import('/blocks/accordion/accordion.js');
await module.default(block);
</script>
</div>
Best For: Features, team members, product showcase
<div style="background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); border-radius: 12px; padding: 32px; margin: 0 0; border-left: 6px solid #0288d1; color: #212121;">
<h2 style="color: #0d47a1; font-size: 28px; font-weight: 700; margin-bottom: 24px;">Section Title</h2>
<div class="cards block">
<div>
<div><strong>📊 Card Title</strong></div>
<div>Card content with description...</div>
</div>
<div>
<div><strong>🚀 Another Card</strong></div>
<div>More content here...</div>
</div>
</div>
<script type="module">
const block = document.querySelector('.cards.block');
const module = await import('/blocks/cards/cards.js');
await module.default(block);
</script>
</div>
Best For: Organizing related information, code examples, comparisons
<div style="background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); border-radius: 12px; padding: 32px; margin: 0 0; border-left: 6px solid #0288d1; color: #212121;">
<h2 style="color: #0d47a1; font-size: 28px; font-weight: 700; margin-bottom: 24px;">Section Title</h2>
<div class="tabs block">
<div>
<div>Tab 1</div>
<div>Content for tab 1...</div>
</div>
<div>
<div>Tab 2</div>
<div>Content for tab 2...</div>
</div>
</div>
<script type="module">
const block = document.querySelector('.tabs.block');
const module = await import('/blocks/tabs/tabs.js');
await module.default(block);
</script>
</div>
See resources/blocks-reference.md for all block patterns.
CRITICAL: All presentations must follow these exact styling standards for consistency.
font-size: 48px; font-weight: 800color: #0d47a1; font-size: 28px; font-weight: 700; margin-bottom: 24px;
32pxcolor: #0d47a1; font-size: 26px; font-weight: 700; margin-bottom: 20px;
28pxdisplay: flex; align-items: center; gap: 12px;font-size: 16px; line-height: 1.8; color: #212121;20pxfont-size: 18px; font-weight: 500##, ###)background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);color: #212121; to prevent text fadingmargin: 0 0; (no vertical gaps that expose dark ipynb-viewer background)border-radius: 12px;padding: 32px;border-left: 6px solid #0288d1; (thick border for major parts)border-left: 4px solid #0288d1; (thinner border for content within sections)border-left: 4px solid #0288d1; (matches subsection weight)H2 Major Section (NO section tag):
<div style="background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); border-radius: 12px; padding: 32px; margin: 0 0; border-left: 6px solid #0288d1; color: #212121;">
<h2 style="color: #0d47a1; font-size: 28px; font-weight: 700; margin-bottom: 24px;">🎯 Section Title</h2>
<p style="font-size: 16px; line-height: 1.8;">Body text content here...</p>
</div>
IMPORTANT: Do NOT wrap cells in <section> tags - they cause overlay jumping between slides.
H3 Subsection (standalone):
<div style="background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); border-radius: 12px; padding: 32px; margin: 0 0; border-left: 4px solid #0288d1; color: #212121;">
<h3 style="color: #0d47a1; font-size: 26px; font-weight: 700; margin-bottom: 20px; display: flex; align-items: center; gap: 12px;">
<span style="font-size: 28px;">✨</span>
Subsection Title
</h3>
<p style="font-size: 16px; line-height: 1.8;">Body text content here...</p>
</div>
Hero Cell (title page):
<div style="background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); color: white; border-radius: 16px; padding: 48px; text-align: center; margin: 0 0; box-shadow: 0 8px 20px rgba(0,0,0,0.25); color: #212121;">
<h1 style="font-size: 48px; font-weight: 800; margin: 0 0 16px 0; display: flex; align-items: center; justify-content: center; gap: 16px;">
<span style="font-size: 56px;">🎯</span>
<span>Presentation Title</span>
</h1>
<p style="font-size: 20px; margin: 16px 0; opacity: 0.95; font-weight: 300;">
Compelling subtitle or tagline
</p>
</div>
CRITICAL: All EDS blocks MUST be wrapped INSIDE styled divs, not as siblings.
Blocks inherit dark background from ipynb-viewer if not properly wrapped:
<div style="background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); border-radius: 12px; padding: 32px; margin: 0 0; border-left: 6px solid #0288d1; color: #212121;">
<h2 style="color: #0d47a1; font-size: 28px; font-weight: 700; margin-bottom: 24px;">Section Title</h2>
<!-- Optional explanation box -->
<div style="background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); border-radius: 12px; padding: 20px; margin: 0 0 24px 0; border-left: 4px solid #0288d1; color: #212121;">
Explanation text about the block demonstration
</div>
<!-- Block INSIDE the container -->
<div class="block-name block">
<!-- block content -->
</div>
<script type="module">
const block = document.querySelector('.block-name.block');
const module = await import('/blocks/block-name/block-name.js');
await module.default(block);
</script>
</div> <!-- Close container AFTER block -->
##, ###) - they render grey<section> tags to wrap cells - causes overlay jumping between slidescolor: #212121; on gradient divs - text fadesmargin: 32px 0;) - creates black gapsApply consistent inline HTML styling to all markdown cells for professional presentation:
Standard Color Palette:
{
heading: '#0d47a1', // Dark Blue (all headings)
text: '#212121', // Dark Gray (all body text)
border: '#0288d1', // Blue (left borders)
gradient_start: '#e3f2fd', // Light Blue (gradient start)
gradient_end: '#bbdefb', // Medium Blue (gradient end)
// Legacy/optional colors:
primary: '#1976d2', // Material Blue
secondary: '#dc004e', // Material Pink
success: '#2e7d32', // Green
warning: '#ed6c02', // Orange
background: '#f5f5f5', // Light Gray
surface: '#ffffff' // White
}
Hero Header:
<div style="background: linear-gradient(135deg, #1976d2 0%, #1565c0 100%); color: white; border-radius: 16px; padding: 48px; text-align: center; margin: 32px 0; box-shadow: 0 8px 16px rgba(0,0,0,0.2);">
<h1 style="font-size: 48px; font-weight: 800; margin: 0 0 16px 0;">
🗺️ Presentation Title
</h1>
<p style="font-size: 20px; margin: 16px 0; opacity: 0.95;">
Your compelling subtitle or tagline
</p>
</div>
Content Card:
<div style="background: white; border-radius: 12px; padding: 28px; margin: 20px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.08);">
<h3 style="color: #1976d2; font-size: 24px; font-weight: 700; margin-bottom: 20px;">Section Title</h3>
<div style="color: #212121; line-height: 1.8; font-size: 16px;">
Your content here with proper typography
</div>
</div>
Block Wrapper (for EDS blocks):
<div style="background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); border-radius: 12px; padding: 32px; margin: 0 0; border-left: 6px solid #0288d1; color: #212121;">
<h3 style="color: #0d47a1; font-size: 26px; font-weight: 700; margin-bottom: 16px;">What this demonstrates</h3>
<p>Explanatory text before the EDS block</p>
<div class="cards block">
<!-- Block HTML here -->
</div>
<script type="module">
const block = document.querySelector('.cards.block');
const module = await import('/blocks/cards/cards.js');
await module.default(block);
</script>
</div>
List with Icons (Compact Spacing):
<ul style="list-style: none; padding: 0; margin: 0;">
<li style="padding: 12px 0; border-bottom: 1px solid rgba(0,0,0,0.08); font-size: 16px; display: flex; align-items: center; gap: 12px;">
<span style="font-size: 20px;">✅</span>
<span>List item text</span>
</li>
<!-- Remove border-bottom from last item -->
<li style="padding: 12px 0; font-size: 16px; display: flex; align-items: center; gap: 12px;">
<span style="font-size: 20px;">✅</span>
<span>Last list item</span>
</li>
</ul>
Hover Effects:
Best Practices:
:hover pseudo-class - Inline JavaScript event handlers (onmouseover, onmouseout) are blocked by browser security<style> tags with classes - Define reusable classes for hover statestransition - For smooth animations (e.g., transition: background 0.2s)Security Note:
Browsers block inline JavaScript event handlers when content is inserted via innerHTML (which ipynb-viewer uses). Always use CSS :hover instead of onmouseover/onmouseout.
const { testBlock } = await import('/scripts/ipynb-helpers.js');
const block = await testBlock('accordion', content);
return block.outerHTML;
<div style="background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); border-radius: 12px; padding: 32px; margin: 0 0; border-left: 6px solid #0288d1; color: #212121;">
<h3 style="color: #0d47a1; font-size: 26px; font-weight: 700; margin-bottom: 16px;">Code Example: Testing Accordion Block</h3>
<p>This example demonstrates how to test the accordion block programmatically:</p>
**Original code:**
\```javascript
const { testBlock } = await import('/scripts/ipynb-helpers.js');
const block = await testBlock('accordion', content);
return block.outerHTML;
\```
**What it does:**
1. Imports the testBlock helper function
2. Tests the accordion block with provided content
3. Returns the rendered HTML
**Result:** The accordion block is decorated and ready for display.
---
**Note:** In presentation mode, code is shown for reference only. See the live accordion demonstration below:
<div class="accordion block">
<!-- Actual working accordion here -->
</div>
<script type="module">
const block = document.querySelector('.accordion.block');
const module = await import('/blocks/accordion/accordion.js');
await module.default(block);
</script>
</div>
---) between major sectionsBoth presentation (non-interactive) and educational (interactive) notebooks can use either approach.
Auto-wrapping (pure markdown):
| IPynb Viewer (notebook) |)Manual HTML styling (inline styles):
Decision matrix: | Factor | Use Auto-Wrapping | Use Manual HTML | |--------|------------------|-----------------| | Display mode | Notebook mode | Any mode (paged, autorun, basic, notebook) | | Priority | Speed/simplicity | Design control/polish | | Content | Simple structure | Complex layouts | | Notebook type | Both presentation & educational | Both presentation & educational |
Key insight: "Presentation" refers to non-interactive style (no runnable code), NOT a display mode. Auto-wrapping works for presentation notebooks displayed in notebook mode.
Mixing Both Approaches: You can combine auto-wrapping with custom HTML in the same notebook for maximum flexibility:
<!-- Most cells: pure markdown (auto-wrapped) -->
# Section Title
Regular content here...
<!-- Special cell: custom HTML for emphasis -->
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 12px; padding: 48px; margin: 0; text-align: center; color: white;">
<h2 style="font-size: 36px; font-weight: 800; margin: 0;">🎯 Key Takeaway</h2>
<p style="font-size: 20px;">Custom styling for this important message</p>
</div>
This hybrid approach gives you speed (pure markdown) with flexibility (custom HTML) where needed.
Action Cards for Navigation (NEW):
Create beautiful navigation links using pure markdown with action cards:
# 🎯 Product Launch Presentation
Discover our revolutionary new features.
<!-- action-cards -->
- [Overview](#)
- [Key Features](#)
- [Pricing](#)
How it works:
<!-- action-cards --> HTML comment in your markdown cell(#) as placeholderImportant: The <!-- action-cards --> marker only applies to the first list that follows it. Any subsequent lists in the same cell will remain as normal bullet lists.
Example matching:
[Overview](#) finds heading containing "Overview" (like "## Overview" or "### 📊 Overview Section")[Key Features](#) finds heading containing "Key Features" (like "## Section 2: Key Features")Best Practices:
[Section 1: Overview](#) instead of just [Overview](#)Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer