docs/
├── 00-intro.adoc # first
├── 01-basics.adoc # second
├── 02-advanced.adoc # third
├── 10-appendix.adoc # tenth
lazyslide
A tool for writing presentations lazily in text form.
Bootstrap new talks with lazyslide init
Render a deck from index.adoc or a directory of .adoc files
Watch source files and re-render on change
Serve the output locally
TUI dashboard while working
Use JBang to install the lazyslide app:
jbang app install lazyslide@maxandersen
lazyslide init my-talk
Generated starter decks include:
README.adoc
slides/index.adoc
slides/css/presentation.css
slides/img/
.gitignore
You can also just create a single index.adoc file and start writing slides.
lazyslide render
Looks for index.adoc in the current directory or in the given path. If not found, it creates one that includes all .adoc files in the directory.
Render a specific entrypoint:
lazyslide render index.adoc
Render a directory of .adoc files:
lazyslide render docs/
lazyslide serve
That will:
render the deck
serve the output over HTTP
watch source files
refres the browser on demand
show a inline dashboard in the terminal
Pass a directory to lazyslide to scan for .adoc files and auto-generate an index.adoc.
No argument? It tries slides/ first, then docs/.
Files are included in lexicographic (alphabetical string) order by relative path.
This means c10.adoc sorts before c2.adoc because '1' < '2' character-by-character.
Use zero-padded numbers to get the order you expect:
docs/
├── 00-intro.adoc # first
├── 01-basics.adoc # second
├── 02-advanced.adoc # third
├── 10-appendix.adoc # tenthAny .adoc file whose name does not start with . or _.
Files starting with . (hidden) or _ (AsciiDoc partial convention)
Files inside hidden directories (.git/, .asciidoctor/, etc.)
Files inside the output directory
Use the _ prefix for reusable fragments that are included manually from other files but should not become their own section in the generated deck.
The virtual index sets sensible defaults for reveal.js slides:
:icons: font
:source-highlighter: highlightjs
:revealjs_theme: black
:revealjs_transition: slide
:stem: latexmath
:revealjs_hash: true
:revealjs_history: true
:revealjs_width: 1920
:revealjs_height: 1080To override these defaults for the whole deck, create an attributes file in the source directory. lazyslide looks for the first one that exists, in this order:
_lazyslide_attributes.adoc — lazyslide-specific, won’t clash with other tools
_attributes.adoc — generic convention
attributes.adoc — simple name (note: no _ prefix, so excluded from slide scanning by name match)
The file is loaded as soft-set attributes at render time, so it overrides lazyslide’s defaults but individual .adoc files can still override per-file:
docs/
├── _attributes.adoc # project-wide overrides
├── 00-intro.adoc
├── 01-main.adocExample:
:revealjs_theme: white
:revealjs_transition: fade
:imagesdir: imgFrom lowest to highest:
lazyslide built-in defaults
_attributes.adoc (project-wide overrides)
Per-file inline attributes (e.g. :imagesdir: ../img in a subdirectory file)
This works for both directory mode and single-file mode — lazyslide looks for _attributes.adoc next to the source file or in the scanned directory.
lazyslide serve lazyslide/README.adocYou can also render remote files:
lazyslide serve https://raw.githubusercontent.com/maxandersen/lazyslide/main/README.adocJust be aware it will not be able to access relative paths to the file you are rendering.
There is a kitchensink file that includes most if not all the features of lazyslide + reveal.js + AsciiDoctor features.
This slide uses the document title as section header.
Press Space or → to navigate.
Press S for speaker notes. Press Esc for overview.
Bold, italic, bold italic, monospace, strikethrough
Superscript: E = mc2
Subscript: H2O
Small text and Big text
Keyboard shortcut: Ctrl+Shift+P
Menu: File ▸ Save As…
Apples
Granny Smith
Fuji
Oranges
Bananas
First step
Second step
Sub-step A
Sub-step B
Third step
Central Processing Unit
Random Access Memory
Solid State Drive
External link: Asciidoctor
Link with tooltip: reveal.js
Email: Contact Us
Items appear one at a time:
First, this appears
Then this
And finally this
Fade in
Fade out
Highlight red
Highlight current blue
Grow
Shrink
public class Hello {
public static void main(String[] args) {
var message = "Hello, reveal.js!";
System.out.println(message);
var list = List.of("one", "two", "three");
list.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
}
}from dataclasses import dataclass
@dataclass
class Slide:
title: str
content: str
fragments: list[str] = None
def render(self) -> str:
return f"== {self.title}\n\n{self.content}"
slides = [Slide("Intro", "Welcome!"), Slide("End", "Thanks!")]
for slide in slides:
print(slide.render())#!/bin/bash
set -euo pipefail (1)
INPUT="${1:?Usage: render.sh <file>}" (2)
echo "Rendering $INPUT..." (3)
lazyslide render "$INPUT" (4)| 1 | Strict mode: exit on error, undefined vars, pipe failures |
| 2 | Require first argument or show usage |
| 3 | Log what we’re doing |
| 4 | Delegate to lazyslide |
Inline: System.out.println() or SELECT * FROM users
server:
port: 8080
host: 0.0.0.0
database:
url: jdbc:postgresql://localhost/mydb
pool-size: 10SELECT u.name, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.created_at > '2024-01-01'
GROUP BY u.name
ORDER BY order_count DESC
LIMIT 10;Images can be:
Inline with text
Sized and positioned
Loaded from URLs or local files
Text over a background image.
Set per-slide background colors with the background-color attribute.
Works with light themes too.
This slide uses a CSS gradient background.
Point one
Point two
Point three
{
"layout": "columns",
"count": 2
}Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world.
Talk is cheap. Show me the code.
| Feature | AsciiDoc | Markdown | LaTeX |
|---|---|---|---|
Slides | |||
Diagrams | |||
Live Reload | |||
Single File |
| Month | Revenue | Growth |
|---|---|---|
Jan | $12000 | — |
Feb | $14500 | +20.8% |
Mar | $13800 | -4.8% |
Apr | $16200 | +17.4% |
May | $18900 | +16.7% |
| This is a note — useful for supplementary info. |
| This is a tip — a helpful suggestion. |
| This is important — don’t skip this. |
| This is a warning — proceed with caution. |
| This is a caution — danger ahead. |
AsciiDoc supports inline footnotes.[1]
You can also reuse them by giving a name.[2]
Here’s the same footnote again.[2]
The quadratic formula:
Euler’s identity: \(e^{i\pi} + 1 = 0\)
Maxwell’s equations:
This slide zooms in.
This slide fades in.
This slide uses a convex transition.
This slide uses a concave transition.
This slide has no transition.
This is rendered as-is.
Whitespace is preserved.
No formatting applied.Sidebars render with a background in standard AsciiDoc output, but reveal.js themes don’t style .sidebarblock
(See kitchensink.css for how to style it).
Raw HTML passthrough lets you do anything reveal.js supports.
Navigate down with ↓
This is a vertical (nested) slide.
And another one.
Feature complete | |
Needs review | |
Blocked | |
In progress |
lazyslide provides an :name: inline macro:
🚀 🔥 🎉 👍 ❤ ⭐ ⚠
☕ 🍕 🍺 ☀ 🌔 🌈 ✨
emoji:rocket[] Launch day!
emoji:warning[] Caution ahead.Matched element will be animated automatically!
Matched element will be animated automatically!
And move to the right position!
⬆️
⬆️
⬆️
| Key | Action |
|---|---|
→ / Space | Next slide |
← | Previous slide |
↑ / ↓ | Navigate vertical slides |
Esc / O | Overview mode |
S | Speaker notes |
F | Fullscreen |
B / . | Blackout |
Ctrl+Shift+F | Search slides |
? | Show keyboard help |
⚠ Here be diagrams ⚠
24 diagram types follow — PlantUML, Ditaa, QR codes, Graphviz, Mermaid, and more.
Some need external tools; missing ones fail gracefully.
Press → to skip the whole section, ↓ to dive in.
PlantUML is bundled — no install required.
Ditaa is bundled — no install required.
QR codes are bundled — no install required.
vl2vg and vg2svg: npm install -g vega-lite vega-cligraphviz: brew install graphviz / apt install graphvizFailed to generate image: mmdc failed: Generating single mermaid chart
graph LR
A[Write AsciiDoc] --> B{lazyslide}
B -->|render| C[Static HTML]
B -->|serve| D[Live Preview]
B -->|watch| E[Auto Rebuild]
D --> F[Browser]
E --> Fmermaid-cli: npm install -g @mermaid-js/mermaid-clierd or erd-go: go install github.com/kaishuu0123/erd-go@latestwavedrom-cli: npm install -g wavedrom-clivl2vg and vg2svg: npm install -g vega-lite vega-clinomnoml: npm install -g nomnomlbytefield-svg: npm install -g bytefield-svgFailed to generate image: Could not find the 'svgbob', 'svgbob_cli' executable in PATH; add it to the PATH or specify its location using the 'svgbob' document attribute
+----------+
| |
| lazyslide|
| |
+----+-----+
|
+-----+-----+
| |
+---v---+ +----v----+
| HTML | | Browser |
+-------+ +---------+svgbob_cli: cargo install svgbob_clidbml-renderer: npm install -g @softwaretechnik/dbml-renderersmcat: npm install -g state-machine-catmscgen: brew install mscgen / apt install mscgengnuplot: brew install gnuplot / apt install gnuplota2s: go install github.com/asciitosvg/asciitosvg/cmd/a2s@latestFailed to generate image: Could not find the 'pintora' executable in PATH; add it to the PATH or specify its location using the 'pintora' document attribute sequenceDiagram User ->> lazyslide: edit file lazyslide ->> Browser: reload
pintora: npm i -g @pintora/cliFailed to generate image: Could not find the 'vhs' executable in PATH; add it to the PATH or specify its location using the 'vhs' document attribute Set Width 1024 Set Height 400 Type "lazyslide serve --port 0 README.adoc" Enter Sleep 2s
vhs: brew install vhs / go install github.com/charmbracelet/vhs@latestThat’s the kitchen sink!
Covers: text, code, fragments, tables, math, charts, diagrams,
backgrounds, transitions, layout, icons, video, auto-animate.