Lazy Slide

lazyslide logo

A tool for writing presentations lazily in text form.

What it does

  • 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

Install

Use JBang to install the lazyslide app:

jbang app install lazyslide@maxandersen

Bootstrap a new presentation

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.

Render 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/

Serve with live reload

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

Directory scanning

Pass a directory to lazyslide to scan for .adoc files and auto-generate an index.adoc.

No argument? It tries slides/ first, then docs/.

File ordering

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    # tenth

What gets included

Any .adoc file whose name does not start with . or _.

What gets excluded

  • 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.

Default attributes

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: 1080

Overriding defaults with an attributes file

To 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:

  1. _lazyslide_attributes.adoc — lazyslide-specific, won’t clash with other tools

  2. _attributes.adoc — generic convention

  3. 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.adoc

Example:

:revealjs_theme: white
:revealjs_transition: fade
:imagesdir: img

Attribute precedence

From lowest to highest:

  1. lazyslide built-in defaults

  2. _attributes.adoc (project-wide overrides)

  3. 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.

Render this README as slides

lazyslide serve lazyslide/README.adoc

You can also render remote files:

lazyslide serve https://raw.githubusercontent.com/maxandersen/lazyslide/main/README.adoc

Just be aware it will not be able to access relative paths to the file you are rendering.

Kitchensink

There is a kitchensink file that includes most if not all the features of lazyslide + reveal.js + AsciiDoctor features.

Kitchen Sink: AsciiDoc Reveal.js

Title Slide (Auto)

This slide uses the document title as section header.

Press Space or to navigate.

Press S for speaker notes. Press Esc for overview.

Text Formatting

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…​

Lists

Unordered

  • Apples

    • Granny Smith

    • Fuji

  • Oranges

  • Bananas

Ordered

  1. First step

  2. Second step

    1. Sub-step A

    2. Sub-step B

  3. Third step

Description

CPU

Central Processing Unit

RAM

Random Access Memory

SSD

Solid State Drive

Fragments

Items appear one at a time:

  • First, this appears

  • Then this

  • And finally this

Fragment Styles

Fade in

Fade out

Highlight red

Highlight current blue

Grow

Shrink

Source Code — Java

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);
    }
}

Source Code — Python

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())

Source Code with Callouts

#!/bin/bash
set -euo pipefail  (1)

INPUT="${1:?Usage: render.sh <file>}"  (2)

echo "Rendering $INPUT..."  (3)
lazyslide render "$INPUT"  (4)
1Strict mode: exit on error, undefined vars, pipe failures
2Require first argument or show usage
3Log what we’re doing
4Delegate to lazyslide

Inline Code & Code Blocks

Inline: System.out.println() or SELECT * FROM users

A YAML config file
server:
  port: 8080
  host: 0.0.0.0

database:
  url: jdbc:postgresql://localhost/mydb
  pool-size: 10
SQL query
SELECT 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

Picsum Photo

Images can be:

  • Inline with text

  • Sized and positioned

  • Loaded from URLs or local files

Background Image

Text over a background image.

Colored Backgrounds

Set per-slide background colors with the background-color attribute.

Light Background

Works with light themes too.

This slide uses a CSS gradient background.

Iframe Background

Two-Column Layout

Left Column
  • Point one

  • Point two

  • Point three

Right Column
{
  "layout": "columns",
  "count": 2
}

Block Quotes

Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world.

— Albert Einstein

Talk is cheap. Show me the code.

https://lkml.org
— Linus Torvalds

Tables

Table 1. Comparison of Approaches
FeatureAsciiDocMarkdownLaTeX

Slides

Diagrams

Live Reload

Single File

Table — CSV Data

Table 2. Monthly Revenue
MonthRevenueGrowth

Jan

$12000

Feb

$14500

+20.8%

Mar

$13800

-4.8%

Apr

$16200

+17.4%

May

$18900

+16.7%

Admonitions

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.

Footnotes

AsciiDoc supports inline footnotes.[1]

You can also reuse them by giving a name.[2]

Here’s the same footnote again.[2]

1. This is an inline footnote — it appears at the bottom of the slide.
2. This footnote can be referenced again.

Math with LaTeX

The quadratic formula:

\[x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}\]

Euler’s identity: \(e^{i\pi} + 1 = 0\)

Maxwell’s equations:

\[\nabla \times \vec{E} = -\frac{\partial \vec{B}}{\partial t}\]

Zoom Transition

This slide zooms in.

Fade Transition

This slide fades in.

Convex Transition

This slide uses a convex transition.

Concave Transition

This slide uses a concave transition.

No Transition

This slide has no transition.

Literal & Sidebar Blocks

A literal block
This is rendered as-is.
  Whitespace is preserved.
    No formatting applied.
A sidebar (needs custom CSS in reveal.js)

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).

Passthrough (Raw HTML)

Red
Green
Blue

Raw HTML passthrough lets you do anything reveal.js supports.

Nested Slides (Vertical)

Navigate down with ↓

Vertical Slide 1

This is a vertical (nested) slide.

Vertical Slide 2

And another one.

Icons (Font Awesome)

Feature complete

Needs review

Blocked

In progress

Emoji

lazyslide provides an :name: inline macro:

🚀 🔥 🎉 👍 ❤ ⭐ ⚠

☕ 🍕 🍺 ☀ 🌔 🌈 ✨

Usage
emoji:rocket[] Launch day!
emoji:warning[] Caution ahead.

Embedded Video

Auto-animate

Matched element will be animated automatically!

Matched element will be animated automatically!

And move to the right position!

⬆️
⬆️
⬆️

reveal.js Keyboard Shortcuts

KeyAction

/ 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 — Sequence

PlantUML is bundled — no install required.

sequence diagram

PlantUML — Class Diagram

class diagram

PlantUML — Activity Diagram

activity diagram

PlantUML — State Diagram

state diagram

PlantUML — Component Diagram

component diagram

PlantUML — Use Case Diagram

usecase diagram

PlantUML — Entity Relationship

er diagram

PlantUML — Mindmap

mindmap diagram

PlantUML — Gantt Chart

gantt diagram

PlantUML — Work Breakdown Structure

wbs diagram

PlantUML — JSON Visualization

json diagram

PlantUML — YAML Visualization

yaml diagram

PlantUML — Timing Diagram

timing diagram

PlantUML — Network Diagram (nwdiag)

network diagram

Ditaa — ASCII Art Diagrams

Ditaa is bundled — no install required.

architecture

QR Code

QR codes are bundled — no install required.

qr demo

Vega-Lite — Bar Chart.[1]

vegalite bar chart
1. Requires vl2vg and vg2svg: npm install -g vega-lite vega-cli

Vega-Lite — Line Chart

vegalite line chart

Vega-Lite — Pie Chart

vegalite pie chart

Graphviz.[1]

graphviz diagram
1. Requires graphviz: brew install graphviz / apt install graphviz

Mermaid.[1]

Failed 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 --> F
1. Requires mermaid-cli: npm install -g @mermaid-js/mermaid-cli

D2.[1]

d2 diagram
1. Requires d2: brew install d2 / https://d2lang.com

ERD.[1]

erd diagram
1. Requires erd or erd-go: go install github.com/kaishuu0123/erd-go@latest

WaveDrom.[1]

wavedrom diagram
1. Requires wavedrom-cli: npm install -g wavedrom-cli

Vega-Lite.[1]

vegalite diagram
1. Requires vl2vg and vg2svg: npm install -g vega-lite vega-cli

Nomnoml.[1]

nomnoml diagram
1. Requires nomnoml: npm install -g nomnoml

ByteField.[1]

bytefield diagram
1. Requires bytefield-svg: npm install -g bytefield-svg

SvgBob.[1]

Failed 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 |
  +-------+  +---------+
1. Requires svgbob_cli: cargo install svgbob_cli

DBML.[1]

dbml diagram
1. Requires dbml-renderer: npm install -g @softwaretechnik/dbml-renderer

State Machine Cat.[1]

smcat diagram
1. Requires smcat: npm install -g state-machine-cat

MSC (Message Sequence Chart).[1]

msc diagram
1. Requires mscgen: brew install mscgen / apt install mscgen

Gnuplot.[1]

gnuplot diagram
1. Requires gnuplot: brew install gnuplot / apt install gnuplot

a2s (ASCII to SVG).[1]

a2s diagram
1. Requires a2s: go install github.com/asciitosvg/asciitosvg/cmd/a2s@latest

Pintora.[1]

Failed 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
1. Requires pintora: npm i -g @pintora/cli

VHS (terminal recording).[1]

Failed 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
1. Requires vhs: brew install vhs / go install github.com/charmbracelet/vhs@latest

That’s the kitchen sink!

Covers: text, code, fragments, tables, math, charts, diagrams,
backgrounds, transitions, layout, icons, video, auto-animate.