🌏 English: this document · 한국어: README_kr.md
A tool that automatically converts Markdown files into Reveal.js presentations and EPUB e-books. An independent per-project folder structure lets you manage many lecture decks and e-books in an organized way.
🌐 Live demo: https://finfra.github.io/m2slide/
View the actually generated presentations directly in your web browser.
📊 m2slide intro decks:
📋 Public project list: Projects_org.md
The list of example projects included in this repository. It is auto-generated by
./m2slide.sh --sync-projects, so do not edit it by hand.
- Markdown → HTML conversion: slides are split automatically by the
---separator - Markmap table of contents: a clickable, interactive mind map
- Hierarchical navigation: automatic linking of main/sub chapters, parent-page button
- Responsive design: optimized for desktop and mobile
- Full Markdown support: headers, lists, tables, code blocks, images, blockquotes, and more
- EPUB 3.0 standard: works with all readers such as iBooks, Calibre, Google Play Books
- Automatic table of contents: hierarchical structure based on AGENDA.md
- Mermaid diagrams: auto-converted to SVG images (when mmdc is installed)
- Automatic image embedding: Markdown images are embedded inside the EPUB
- Independent folder structure: each project is managed in its own folder
- Consistent workflow: the same commands apply to every project
- Git-friendly: optional per-project version control
- HTML: Reveal.js presentation (default)
- EPUB: e-book (
--epub) - PDF: per-chapter combined PDF (
--pdf, uses decktape) - PPTX: PowerPoint-compatible (
--pptx, uses pandoc) - Automatic GitHub Pages deploy:
deploy_formatsin_config.yml+ the/deploy-docscommand auto-syncs artifacts and cards (see the GitHub Pages deployment section)
m2slide/
├── Projects/
│ ├── ProjectA/ # Independent project 1
│ │ ├── markdown/ # Markdown source
│ │ │ ├── AGENDA.md
│ │ │ ├── 01-section.md
│ │ │ └── ...
│ │ ├── slide/ # HTML output (auto-generated)
│ │ └── ProjectA.epub # EPUB output (auto-generated)
│ ├── ProjectB/ # Independent project 2
│ │ ├── markdown/
│ │ ├── slide/
│ │ └── ProjectB.epub
│ └── LlmAndVibeCoding/ # Example project (see below)
├── config.yml # Current working project setting
├── m2slide.sh # One-click conversion (HTML/EPUB)
├── lib/ # Script collection
│ ├── generate-slides.js # HTML conversion script
│ ├── generate-epub.js # EPUB conversion script
│ ├── deploy.sh # GitHub Pages deploy
│ └── debug_yaml.js # YAML parsing debug util
├── theme/ # Themes (default·default_lec tracked in git, others gitignored)
│ ├── default/ # General-purpose base theme
│ │ ├── slide.css # Global styles
│ │ └── layouts/_toc.html # System layout (auto-applied TOC)
│ └── default_lec/ # Official lecture theme
│ ├── slide.css
│ └── layouts/*.html # cover, contents, split-image-text, etc.
└── README.md
If AGENDA.md exists inside the markdown/ folder → chapter mode; if it is absent → single-page mode.
One Markdown file → one HTML slide deck. For short talks.
- Create the
Projects/{name}/folder - Write a Markdown file inside it (split slides with
---) - Run
./m2slide.sh Projects/{name} - Open
Projects/{name}/slide/{name}.htmlto check
Markdown file selection priority (when there are multiple .md files):
{project-folder-name}.md(ex:MarkdownGraph/MarkdownGraph.md)README.md- If there is only one .md file, that file
- If there is only one .md file starting with a normal character (letter/digit/Korean), that file
- If there are multiple candidates → error → rename to match the folder name
Multiple Markdown files → per-chapter HTML + a mind-map table of contents. For long lectures and e-books.
- Create the
Projects/{name}/markdown/folder - Write chapter files — main:
01-opening.md, sub:02.1-chat.md - Write the table of contents in
markdown/AGENDA.md(this file is the signal that enables chapter mode) - Run
./m2slide.sh Projects/{name} - Open
Projects/{name}/slide/index.html(mind-map TOC)
Simple way (recommended):
# Use the current project from config.yml
./m2slide.sh
# Specify a particular project
./m2slide.sh Projects/ProjectADetailed control (running Node.js directly):
# Use the default project
node generate-slides.js
# Specify a project folder
node generate-slides.js Projects/ProjectA
# Specify the markdown folder directly (../slide/ is created automatically)
node generate-slides.js Projects/ProjectA/markdown
# Specify input/output folders directly (advanced)
node generate-slides.js Projects/ProjectA/markdown Projects/ProjectA/slideOutput:
slide/*.html: per-chapter Reveal.js presentationsslide/index.html: full table of contents based on Markmap (mind map)slide/img/: images copied automatically
Generate HTML + EPUB at once:
# Current project from config.yml
./m2slide.sh --epub
# A particular project
./m2slide.sh Projects/ProjectA --epubEPUB only (skip HTML):
node generate-epub.js Projects/ProjectAMermaid diagram rendering (optional):
# Install the Mermaid CLI (mmdc)
npm install -g @mermaid-js/mermaid-cli
# Google Chrome is required (auto-detected)
# - macOS: /Applications/Google Chrome.app/
# - Linux: /usr/bin/google-chrome
# - Windows: C:\Program Files\Google\Chrome\Application\chrome.exe
# If mmdc is missing, a placeholder SVG is used insteadOutput:
Projects/ProjectA/ProjectA.epub: EPUB 3.0 e-bookslide/ProjectA.epub: copied automatically alongside the presentationindex.html: EPUB download link shown automatically
# Open in the browser
open Projects/ProjectA/slide/index.html # Mind-map navigation
open Projects/ProjectA/slide/01-section.html # Individual sectionNavigation:
- ← / →: previous/next slide
- ↑: chapter mode — go to the parent page (sub chapter → main chapter → TOC) / single-page mode — go to the first slide
- → twice on the last slide: move to the next chapter (chapter mode only)
- ESC: slide overview
- S: speaker-notes mode
- Bottom-right button: click the "↑ up" button to move to the parent page
- First slide: clickable Markmap TOC (includes sub-chapter links)
# 1. Create the project folder
mkdir -p Projects/NewProject/markdown
# 2. Write AGENDA.md and Markdown files
# In the markdown folder, use the following format:
# - AGENDA.md: ## [title](./filename.md) format
# - XX-title.md: main section (ex: 01-intro.md)
# - XX.Y-title.md: sub section (ex: 02.1-detail.md)
# - Split slides with the --- separator in each file
# 3. Add Git tracking (optional)
echo "!/NewProject/" >> Projects/.gitignore
# 4. Generate HTML/EPUB
./m2slide.sh Projects/NewProject --epub
# 5. Check
open Projects/NewProject/slide/index.html# Pandoc must be installed (brew install pandoc)
# Convert a single file
pandoc Projects/ProjectA/markdown/01-section.md -o presentation.pptx
# Combine all material
pandoc Projects/ProjectA/markdown/*.md -o complete.pptx- Automatic slide splitting: slide boundaries are detected automatically by the
---separator - Markmap TOC: visualizes the AGENDA.md structure as an interactive mind map
- Hierarchical navigation:
- main chapter TOC automatically shows sub-chapter links
- parent-page button (bottom-right "↑ up")
- keyboard ↑ moves to the parent page
- Complete Markdown parser:
- headers, Bold, Italic, inline code
- ordered/unordered lists, nested lists
- tables, code blocks, blockquotes
- images (auto size limit 400x300px)
- Responsive design: optimized for desktop and mobile
- Slide numbers: current/total display
- Automatic index.html generation: mind-map navigation based on the AGENDA.md structure
- EPUB 3.0 standard: mimetype, META-INF/container.xml, OEBPS/content.opf, toc.ncx
- Automatic TOC generation: extracts book title and chapter structure from AGENDA.md
- Mermaid diagram conversion:
- auto-converted to SVG images when the Mermaid CLI is installed
- uses the system Chrome (PUPPETEER_EXECUTABLE_PATH)
- generates a placeholder SVG on conversion failure
- Image embedding: images in markdown/img/ are embedded inside the EPUB
- Pure Node.js implementation: no external dependencies (mmdc is optional)
- Universal compatibility: all EPUB readers such as iBooks, Calibre, Google Play Books
- One-click conversion: the
./m2slide.shscript generates HTML/EPUB at once - config.yml support: automatically detects the current working project
- Automatic image copy: markdown/img/ → slide/img/, and inside the EPUB
- Automatic parent-page detection: derives the hierarchy from AGENDA.md
- Error resilience: generates placeholders on conversion failure
Each project specifies its theme and default layout in _config.yml.
theme: default_lec # applies theme/{name}/slide.css
theme_default_layout: contents # auto-applies theme/{name}/layouts/contents.htmlTo use a different layout for a specific slide only, add this at the start of the Markdown slide:
---
#cover
# First pageFor layouts that need slots such as left/right split, use a fenced div:
---
#split-image-text
# Slide title
::: left

:::
::: right
* Right-side text
:::System layout: the first slide (TOC) automatically gets the _toc layout. In theme/{name}/layouts/_toc.html, the markmap slot is marked by the {{markmap}} variable.
Folder structure (single CSS, only HTML templates per layout):
lib/css/base.css # Common skeleton shared by all themes (Issue64, ~1050 lines)
# @import + :root defaults + common layout + components + responsive
# injected automatically as an inline <style> by html-builder.js
theme/
├── default/ # Base theme (tracked in git, general-purpose ~400 lines)
│ ├── slide.css # Theme-specific: colors, background images, visual language
│ └── layouts/
│ └── _toc.html # System layout (TOC)
└── default_lec/ # Official lecture theme (tracked in git)
├── slide.css # Theme-specific selectors
└── layouts/ # HTML templates only (CSS is merged into slide.css)
├── _toc.html
├── _cover.html
├── _contents.html
├── split-image-text.html
└── ...
CSS priority (low → high): CDN (reset/reveal/highlight/open-props) → lib/css/base.css (inline) → theme/{name}/slide.css (link) → <body style> (config variables). Details: _doc_arch/css.md.
Guide for writing a new theme:
- Minimum requirement: create
theme/{name}/slide.css(an empty file is fine).base.cssprovides the cover/contents/chapter/exercise/blank/closing/toc skeletons plus:rootvariable defaults. - Optional:
:root --kn-*branding colors,theme/{name}/img/background images,theme/{name}/layouts/*.htmltemplates (falls back to default when absent). - In the
_config.ymlstylesection, specify only the values that deviate from the defaults (Issue64 1.b policy). Omitted keys use thelib/config.jsdefaults, guaranteeing the same result as the base.css:root.
Standard variables: {{title}}, {{content}}, {{slotName}}, {{markmap}} (system-reserved, _toc only)
Backward compatibility: the slide_css: key still works. When theme: and theme_default_layout: are unset, the existing behavior is preserved. When style.global.font_import[] is specified, a <link> is added after the base.css @import position (legacy append).
# Project title
## [Main section 1](./01-section.md)
### [Sub section 1.1](./01.1-detail.md)
### [Sub section 1.2](./01.2-detail.md)
## [Main section 2](./02-section.md)Important:
- Only the inline link format (
[title](filename)) is recognized ##: main section,###: sub section- File naming:
XX-title.md(main),XX.Y-title.md(sub)
# First slide
content...
---
# Second slide
content...- Edit the Markdown files in the
Projects/[Project]/markdown/folder - Run
./m2slide.sh --epub(generates HTML + EPUB at once) - Check
Projects/[Project]/slide/index.htmlin the browser - Check
Projects/[Project]/[Project].epubin an EPUB reader
Auto-generated files:
slide/*.html: all per-chapter Reveal.js presentationsslide/index.html: mind-map navigation based on AGENDA.md[Project].epub: EPUB 3.0 e-bookslide/[Project].epub: provided alongside the presentation
The root docs/ folder is the GitHub Pages source (main branch + /docs). It gathers many projects into one place and deploys them as cards (https://finfra.github.io/m2slide/).
A slash command defined in .claude/commands/deploy-docs.md. It supports automatic new/update/delete branching across many projects + an artifact-format option list + automatic main index card updates.
/deploy-docs <project> # update if docs/<project>/ exists, otherwise new
/deploy-docs <project> delete # remove the folder + main index card (user approval required)
/deploy-docs # print usage + current docs/ deployment list
Automatic artifact-format inclusion (EPUB/PDF/PPTX): add one line, deploy_formats, to the project's _config.yml:
deploy_formats: [epub, pdf, pptx] # all formats
deploy_formats: [epub] # EPUB only
## Omit the key or use [] → HTML only (default)Then a single /deploy-docs <project> call builds (auto-passing m2slide.sh options such as --epub) → syncs to docs/ → automatically shows download badges (📚 EPUB · 📄 PDF · 📊 PPTX) on the main index card.
## Automatically deploy the current project from _config.yml
./lib/deploy.sh
## Custom commit message
./lib/deploy.sh "Add new slides"- Automatically reads the current project from
_config.yml - Automatically copies the
slide/folder into thedocs/folder - Automatically runs Git add, commit, push
- Exits automatically when there are no changes
## 1. Regenerate HTML (+ optional artifacts)
./m2slide.sh <project> --epub --pdf --pptx
## 2. Copy into the docs/ folder
mkdir -p docs/<project>
cp -R Projects/<project>/slide/. docs/<project>/
## 3. Git commit and push
git add docs && git commit -m "Update slides" && git pushReflected within about 1–2 minutes after pushing. Check status:
gh api repos/<owner>/<repo>/pages/builds --jq '.[0] | {status, commit, updated_at}'
gh run list --repo <owner>/<repo> --limit 3- Open the GitHub repository
- Settings → Pages menu
- Source: Branch
main, Folder/docs - Click Save
- Reveal.js 5.0.4: HTML presentation framework
- Markmap.js: mind-map visualization (TOC)
- Mermaid.js 10.9.0: diagram rendering
- D3.js: data visualization
- Node.js: Markdown conversion scripts (pure standard library)
- Node.js: EPUB 3.0 generation (pure standard library)
- Mermaid CLI (optional): diagram SVG conversion (
@mermaid-js/mermaid-cli) - Google Chrome (optional): Mermaid rendering engine
- Pandoc (optional): PowerPoint conversion
- GitHub Pages: web hosting
Topic: LLM tooling evolution and the generational classification of vibe coding (30-minute lecture material)
Live demo: https://finfra.github.io/m2slide/
Content overview:
- Opening: the paradigm shift of AI coding
- LLM tooling evolution: chat → IDE → CLI progression
- Vibe coding: concept and philosophy
- Generational classification: based on the user interface (Gen 0: chat, Gen 1: IDE, Gen 2: CLI)
- Generational comparison: a selection guide
- Real-world cases: how to use them
- Adoption roadmap: a practical strategy
- Q&A and closing
File structure:
- Markdown source:
Projects/LlmAndVibeCoding/markdown/(16 files) - HTML presentation:
Projects/LlmAndVibeCoding/slide/ - EPUB e-book:
Projects/LlmAndVibeCoding/LlmAndVibeCoding.epub
Highlights:
- Markmap-based interactive navigation
- Hierarchical chapter structure (7 main, 9 sub)
- Mermaid diagrams (LLM tooling evolution timeline, etc.)
This project is a reference example that demonstrates all of m2slide's features.
./m2slide.sh determines the project in the following priority order:
- CLI argument:
./m2slide.sh MarkdownGraphor./m2slide.sh Projects/MyProj _config.ymlin the CWD:cdinto the project folder, then run../../m2slide.shcurrent_projectin the root_config.yml: (used only when present)
_config.org.ymlis used only as the defaults SSOT, andcurrent_projectis intentionally commented out. If the project cannot be determined, the usage is printed.
To set a default via the root _config.yml:
# _config.yml (root, for local user settings — can be tracked in git)
current_project: LlmAndVibeCoding./lib/deploy.sh reads current_project the same way.
Check the help:
./m2slide.sh --helpDual license — see LICENSE.md for full terms.
- Free (CC BY 4.0): Presentations generated with m2slide must keep the attribution line "Powered by finfra.kr, Made by m2slide" on the first and last slides.
- Paid (Commercial license): Generating presentations with that attribution removed requires a paid commercial license. Contact: finfra@gmail.com / https://finfra.kr