AI-powered slide generation from Markdown with PNG and PDF export via Gemini.
  • Rust 63.7%
  • JavaScript 24.8%
  • HTML 6.3%
  • CSS 4.1%
  • Python 0.9%
  • Other 0.2%
Find a file
mik-tf 560874cc58
All checks were successful
lab publish / publish (push) Successful in 16m48s
ci(lab-publish): publish latest from main, latest-dev from development
Match the canonical pattern so development publishes the latest-dev prerelease
tag instead of overwriting the stable latest release. Pick the release tag by
branch (main -> latest, development -> latest-dev, v* -> ref name).

See lhumina_code/home#268

Signed-by: mik-tf <mik-tf@noreply.invalid>
2026-06-07 17:38:55 -04:00
.forgejo/workflows ci(lab-publish): publish latest from main, latest-dev from development 2026-06-07 17:38:55 -04:00
.hero chore: rename FORGEJO_TOKEN → FORGE_TOKEN in CI and normalize whitespace across docs 2026-05-26 12:56:35 +02:00
crates fix:scan command failure due to schema missmatch 2026-06-07 11:55:10 +03:00
demo_deck fix(server,ui): complete collections migration — wire all RPC handlers to collection+deck routing 2026-04-22 22:01:13 +02:00
deploy deploy: drop down subcommand; add auto-update workflow for devslides 2026-05-21 15:02:33 +02:00
docs chore: rename FORGEJO_TOKEN → FORGE_TOKEN in CI and normalize whitespace across docs 2026-05-26 12:56:35 +02:00
examples chore: rename FORGEJO_TOKEN → FORGE_TOKEN in CI and normalize whitespace across docs 2026-05-26 12:56:35 +02:00
schema chore: auto-commit local changes before pull 2026-05-31 23:45:58 +02:00
testplan chore: rename FORGEJO_TOKEN → FORGE_TOKEN in CI and normalize whitespace across docs 2026-05-26 12:56:35 +02:00
.gitignore chore: ignore .hero dir, fix folder.pick async call in server rpc 2026-05-11 00:10:44 +02:00
Cargo.lock chore(deps): update cargo lock 2026-06-07 11:54:35 +03:00
Cargo.toml chore(deps): point Cargo git deps at upstream main branches 2026-06-03 14:36:06 +02:00
Cargo.toml.hero_builder_backup chore: migrate from hero_rpc/hero_blueprint to hero_lib stack 2026-06-01 09:33:31 +02:00
IMPLEMENTATION_SPEC.md chore: rename FORGEJO_TOKEN → FORGE_TOKEN in CI and normalize whitespace across docs 2026-05-26 12:56:35 +02:00
PURPOSE.md refactor: migrate all binaries to herolib_core::base helpers 2026-05-15 15:26:19 +02:00
README.md chore: rename FORGEJO_TOKEN → FORGE_TOKEN in CI and normalize whitespace across docs 2026-05-26 12:56:35 +02:00
rust-toolchain.toml chore: migrate off hero_blueprint to hero_lib stack 2026-06-01 13:00:44 +02:00

hero_slides

AI-powered slide generation. Generates PNG slide images from markdown using Gemini, exports PDFs, and exposes every AI workflow as a direct CLI command.

Components

Binary Role
hero_slides CLI tool — all commands documented here
hero_slides_server Background RPC server — holds the collection registry, manages generation queues
hero_slides_admin Web admin UI — browse decks, trigger generation, inspect slides

Deck structure

my_deck/
├── .slides ← marker file (identifies this directory as a deck)
├── theme.md ← visual theme description
├── intent.md ← one intent entry per slide (optional)
├── instructions.md ← AI agent / deck-level instructions (optional)
├── 01_intro.md ← slide content files (lowercase, underscores)
├── 02_overview.md
├── metadata.toml ← SHA-256 change-detection hashes + source image refs
├── slides.pdf ← assembled PDF (written by pdf export)
├── output/
│ ├── 01_intro.png ← generated slide images
│ ├── 02_overview.png
│ └── .versions/
│ ├── 01_intro/
│ │ ├── v001.png
│ │ └── v002.png
│ └── 02_overview/
│ └── v001.png
└── content/
 └── background/ ← AI background context
 ├── company/ ← named folder (selectable via --context)
 │ └── overview.md
 └── market/
 └── report.md

Addressing — collection/deck/slide

All commands use a UNC-style address. Names are lowercase identifiers (letters, digits, underscores — no hyphens, no uppercase).

Format Meaning
collection/deck A deck within a registered collection
collection/deck/slide A specific slide (no .md extension)

Examples:

myslides/quarterly_review
myslides/quarterly_review/03_market

Collections are registered with --scan and stored in heroDb. The CLI resolves every address through the registry and gives a clear error if the collection or deck is not found.


Service lifecycle

# Start the server + admin UI (registers with hero_proc)
hero_slides --start

# Stop both processes
hero_slides --stop

# Register a collection (works while server is running or directly via heroDb)
hero_slides --scan myslides=/data/presentations

# List registered collections
hero_slides collections

The server must be running (or heroDb must be reachable) for collection registration and address resolution to work.


Background context (--context)

Many commands accept --context — a comma-separated list of folder names under content/background/. The AI receives the text from those folders as context.

--context company,market # include two specific folders
 # (omit to use all background folders)

generate — AI image generation

Generate all slides in a deck

hero_slides generate deck myslides/quarterly_review
hero_slides generate deck myslides/quarterly_review --force

Generates a PNG for every slide that has changed since the last run. --force regenerates everything.

Generate a single slide

hero_slides generate slide myslides/quarterly_review/03_market
hero_slides generate slide myslides/quarterly_review/03_market --force
hero_slides generate slide myslides/quarterly_review/03_market --context company,market

content — slide text content

Create new slide content

Generate markdown for a new slide from a title and intent description.

hero_slides content create myslides/quarterly_review \
 --title "Market Overview" \
 --intent "Summarise the key market trends for Q1 2025"

# With a specific slide to pull source images from
hero_slides content create myslides/quarterly_review/03_market \
 --title "Market Overview" \
 --intent "Summarise key Q1 market trends" \
 --context market \
 --out 03_market.md

Output goes to stdout unless --out FILE is given.

Instruct — rewrite existing slide content

Reads the existing .md, applies the AI instruction, writes the result back (or to --out).

hero_slides content instruct myslides/quarterly_review/03_market \
 --instruction "Make it more concise — maximum 4 bullet points"

hero_slides content instruct myslides/quarterly_review/03_market \
 --instruction "Add a competitor comparison table" \
 --context market \
 --out 03_market_draft.md

theme — deck visual theme

Extract theme from an image or PDF

Analyzes the visual design and writes theme.md to the deck.

hero_slides theme extract myslides/quarterly_review --from brand_guidelines.pdf
hero_slides theme extract myslides/quarterly_review --from screenshot.png

Supports PNG, JPEG, WebP, GIF, and PDF. Detection is by file extension.

Instruct — modify the existing theme.md

Reads theme.md, applies the instruction, writes back in place.

hero_slides theme instruct myslides/quarterly_review \
 --instruction "Switch to dark mode with blue accents"

hero_slides theme instruct myslides/quarterly_review \
 --instruction "Add a typography section" \
 --context company

instructions — deck instructions.md

Reads instructions.md, applies the instruction via AI, writes back. Creates the file if it does not exist.

hero_slides instructions instruct myslides/quarterly_review \
 --instruction "Add a rule: every slide must start with a clear headline question"

hero_slides instructions instruct myslides/quarterly_review \
 --instruction "Rewrite for investor audience, not technical team" \
 --context company

pdf — PDF assembly and extraction

Export all slide PNGs to a PDF

hero_slides pdf export myslides/quarterly_review
# Writes: <deck>/slides.pdf

Extract a PDF from the background folder to markdown

Uses AI to produce a companion .md alongside the PDF.

# PDF is in content/background/market/
hero_slides pdf extract myslides/quarterly_review \
 --folder market \
 --file industry_report_2025.pdf

# PDF is in the deck root (omit --folder)
hero_slides pdf extract myslides/quarterly_review \
 --file source_doc.pdf

wizard — AI slide planning pass

The wizard proposes or rewrites slide content in bulk from a high-level intent.

Propose new slides

hero_slides wizard myslides/quarterly_review \
 --intent "Create a 5-slide investor pitch: market, product, traction, team, ask" \
 --count 5

hero_slides wizard myslides/quarterly_review \
 --intent "Propose 3 slides for the competitive landscape section" \
 --count 3 \
 --context market \
 --out suggestions.json

Rewrite existing slides

hero_slides wizard myslides/quarterly_review \
 --intent "Tighten the narrative — one clear takeaway per slide" \
 --slides 01_intro,02_market,03_product

Output is a JSON array printed to stdout (or written to --out):

[
 { "slide_name": "01_intro", "content": "..." },
 { "slide_name": "02_market", "content": "..." }
]

info — deck summary

hero_slides info myslides/quarterly_review

Prints slide count, generated count, first slide name, theme status, intent status, PDF status, background presence.


slides list

hero_slides slides list myslides/quarterly_review

Lists all .md slide files. Marks slides that have a generated PNG with .


background list

hero_slides background list myslides/quarterly_review

Lists all folders in content/background/ with file counts.


Environment variables

Variable Purpose
PATH_SOCKET Override socket directory (default: $HOME/hero/var/sockets)
RUST_LOG Log level filter (default: warn, hero_slides* modules at info)

AI credentials are managed by the hero_proc secret store and resolved automatically via AiClient::get().


hero_slides_server — --info requirements

lab validates every hero_* binary by running --info after a successful build. The server output must satisfy:

{
 "name": "hero_slides_server",
 "version": "<semver>",
 "description": "<non-empty string>",
 "kind": {
 "server": true,
 "admin": false,
 "web": false,
 "cli": false
 },
 "interfaces": {
 "openrpc": true,
 "sse": true,
 "rest": false,
 "webui": false
 },
 "sockets": [
 {
 "type": "rpc",
 "path": "<non-empty path>",
 "protocol": "openrpc"
 }
 ],
 "tcp": []
}

Required fields checked by lab:

  • name, version, description — non-empty strings
  • kind — object with boolean keys: server, admin, web, cli
  • interfaces — object with boolean keys: openrpc, sse, rest, webui
  • sockets — array; each entry must have non-empty string fields type, path, protocol
  • tcp — array; each entry must have address (string), port (number), purpose (string)

Extra fields (e.g. dependencies) are ignored by the validator.