Releases: GMfatcat/goslide
v1.5.0
π GoSlide v1.5.0
What's New
π PDF export
New goslide export-pdf <file.md> command renders your deck to a PDF
via headless Chrome. Whatever you see in goslide serve β fonts,
themes, Chart.js, Mermaid diagrams, LLM-baked API results β renders
in the PDF, because the renderer is literally a real browser.
goslide export-pdf talk.md
goslide export-pdf talk.md -o handout.pdf
goslide export-pdf talk.md --notes # include speaker notes
goslide export-pdf talk.md --paper-size a4-landscapePaper sizes (default slide-16x9):
| Preset | Dimensions | Intended use |
|---|---|---|
slide-16x9 |
1920 Γ 1080 px | On-screen presentation look (default) |
slide-4x3 |
1600 Γ 1200 px | Legacy projector aspect |
a4-landscape |
297 Γ 210 mm | Print-friendly handout |
letter-landscape |
11 Γ 8.5 in | US letter handout |
Fragment animations are collapsed to their final state β one slide,
one PDF page.
π§ Chrome discovery: install-once, no bundled chromium
GoSlide stays a single ~8MB binary. export-pdf locates Chrome in
this order:
GOSLIDE_CHROME_PATHenv var (explicit override)- PATH β searches
chrome,chromium,chromium-browser,
google-chrome,microsoft-edge - Platform-specific known install locations
(C:\Program Files\Google\Chrome\Application\chrome.exe,
/Applications/Google Chrome.app/..., etc.)
If nothing is found, the command exits non-zero with an actionable
message listing every location it checked. No auto-download.
π§© How it works
Under the hood export-pdf is a thin wrapper:
- Runs the existing
goslide buildto produce static HTML with
everything (LLM bakes included) already inlined. - Launches Chrome headless against that HTML with reveal.js's
?print-pdfmode. - Waits for
window.__goslideReady(new front-end marker that fires
once Mermaid promises settle β async-safe rendering). - Calls Chrome DevTools
Page.printToPDFwith the resolved paper
dimensions and writes the bytes to the output path.
The Launcher interface keeps unit tests deterministic (fake launcher
for orchestrator tests) and the real ChromedpLauncher only runs when
Chrome is actually present. The integration test auto-skips when
FindChrome() errors, so CI without Chrome stays green.
Compatibility
No breaking changes. v1.4.0 decks export unchanged; the new command is
additive. Existing goslide build / serve / generate / host are
untouched.
Go version: still 1.21.6. Chromedp is pinned to v0.10.0 β the last
release compatible with Go 1.21.
Requirements
- Chrome / Edge / Chromium installed locally. Developers typically
have one of these; if not, any distribution works. Set
GOSLIDE_CHROME_PATHif you want to pick a specific binary.
Out of scope (future work)
- Fragment-per-page mode.
- Custom header/footer, page numbers, bookmarks.
- Password-protected PDFs.
- Auto-downloading or bundling Chromium.
Full Changelog
See v1.4.0...v1.5.0 for all changes.
v1.4.0
π GoSlide v1.4.0
What's New
π§ LLM transformer inside api components (experimental)
The api component accepts a new render item of type llm. Fetched
JSON is substituted into a user-authored prompt via {{data}} and the
model's reply renders inline alongside the chart, table, or metric.
~~~api
endpoint: /api/sales
fixture: sales.json # optional; used by goslide build
render:
- type: chart:bar
label-key: quarter
data-key: revenue
- type: llm
prompt: |
Write 2 analyst bullets on these numbers:
{{data}}
~~~
Control model (three layers, not configurable β that's the point):
- Cache-first β identical
(model, prompt, data)triples call the
LLM at most once. Results land in.goslide-cache/<sha256>.json
(human-readable, commit-safe). Canonical JSON keying means logically
equal data (different key order, whitespace) hits the same entry. - Click-to-call β
goslide serveshows aGenerate β¨button on
cache miss. Page load never triggers an LLM call automatically.
Localstorage caches per-browser. - Build-lock β
goslide buildinlines cached results as a
data-llm-bakesattribute on the api component. The exported HTML
never contacts an LLM at view time.
# Warm cache via the dev loop:
goslide serve talk.md # click Generate to populate .goslide-cache/
# Export to static HTML (reads cache only, zero network):
goslide build talk.md
# Or refresh cache during build (the one place we call LLM non-interactively):
goslide build talk.md --llm-refreshCache miss during goslide build is a hard error by default, listing
every affected slide / component / render-item. Pass --llm-refresh
to opt in to filling the cache during the build.
Offline build with a fixture file β fixture: ./sales.json on the
api component lets goslide build read static data instead of calling
a live endpoint. Great for committing a reproducible snapshot.
Reuses existing generate: config β no new YAML keys; the same
OpenAI-compatible endpoint that powers goslide generate powers the
LLM transformer. Works with any compatible provider (OpenAI,
OpenRouter, Ollama, vllm, sglang, etc.).
β Validation
The IR validator rejects llm render items missing prompt with code
llm-missing-prompt β goslide build / goslide serve won't start
against a broken deck.
π¦ Validated example
examples/ai-generated/api-llm-sales/
is a fully self-contained directory. Clone this repo, cd into the
directory, run goslide build demo.md, and you'll see an LLM-written
analyst summary render in the output HTML without ever touching an LLM
β the committed .goslide-cache/ entry satisfies the bake. Real-LLM
regeneration requires OPENROUTER_API_KEY and --llm-refresh.
Compatibility
No breaking changes. v1.3.0 decks build unchanged; the new llm render
type is additive and only exercises the new code path when present.
The internal change to builder.Build (moving config.Load earlier so
the bake can mutate the IR before render) is invisible to callers.
Out of scope (future work)
- Streaming LLM responses (SSE). Current MVP buffers the full reply.
- JSONPath-style
{{field.x}}expressions in the prompt. Current MVP
injects the whole response as{{data}}. goslide generateemittingllmrender items. Manual-author-only in
v1.4.0.
Full Changelog
See v1.3.0...v1.4.0 for all changes.
v1.3.0
π GoSlide v1.3.0
What's New
πΌοΈ Image Placeholder Component
A new placeholder component β a styled dashed-rectangle "image
stand-in" with an icon, title, and optional description. Drop one
wherever a real image will eventually go, then replace it with the
actual asset when ready.
~~~placeholder
hint: K8s cluster architecture
icon: πΊοΈ
aspect: 16:9
---
Control plane + worker node interaction
~~~
hint(required) β title text describing what the image will showicon(optional) β single emoji cue (π charts, πΊοΈ diagrams, π· photos, π trends, πΌοΈ generic)aspect(optional) β16:9(default),4:3,1:1,3:4, or9:16- Body (between
---and closing fence) β optional subtitle
Placeholders work in any layout: as a full-slide cover diagram, inside
an image-left/image-right region, or combined with the new
image-grid below.
π§© image-grid Layout
A new CSS-grid slide layout that packs multiple cells (placeholders,
real images, charts, or any other component) into 2, 3, or 4 columns.
<!-- layout: image-grid -->
<!-- columns: 2 -->
<!-- cell -->
~~~placeholder
hint: Architecture
icon: πΊοΈ
~~~
<!-- cell -->

<!-- cell -->
~~~chart
type: bar
title: Sales
data:
labels: [Q1, Q2, Q3]
values: [10, 12, 15]
~~~
<!-- cell -->
~~~placeholder
hint: Trends
icon: π
~~~
<!-- cell --> before each item marks a new grid cell; cells can hold
any content.
π€ Smarter goslide generate
The AI-generation command (Phase 6a) now knows about the new features.
The system prompt has been tightened so LLM output consistently uses the
correct fence and comment syntax:
- All component fences are
~~~(triple tilde). Triple-backtick blocks
are plain code and will not render as components. - Per-slide layout settings use HTML comments
(<!-- layout: image-grid -->,<!-- columns: 2 -->), never a
YAML---block mid-document. - Explicit "wrong vs right" examples and a new
image-gridexample in
the prompt.
On OpenRouter free tier, 5 of 6 models tested after this iteration
produce valid, first-pass-parseable output. See
examples/ai-generated/k8s-visual.md
for a real generation (openai/gpt-oss-20b:free, 13 placeholders + one
4-cell image-grid slide).
β Validation
goslide validate / goslide build emit:
- Error
placeholder-missing-hintwhen a placeholder lackshint - Warning
unknown-aspectwhenaspectisn't on the whitelist (falls back to 16:9) - Warning
columns-out-of-rangewhenimage-gridcolumns fall outside 2-4 - Warning
image-grid-emptywhen an image-grid layout contains no cells
Compatibility
No breaking changes. v1.2.0 decks work unchanged. The internal region
parser was refactored from a name-keyed map to an ordered slice so that
repeatable markers (<!-- cell -->) produce distinct regions β
transparent to existing layouts (two-column, three-column, etc.) since
none of them used repeated markers.
Full Changelog
See v1.2.0...v1.3.0 for all changes.
v1.2.0
π GoSlide v1.2.0
What's New
π€ AI Slide Generation (experimental)
New goslide generate command produces a full GoSlide presentation by
calling any OpenAI-compatible LLM endpoint β OpenAI, OpenRouter, Ollama,
vllm, sglang, and others.
export OPENAI_API_KEY=sk-...
goslide generate "Introduction to Kubernetes" # simple mode
goslide generate my-prompt.md -o talk.md # advanced mode
goslide generate --dump-prompt > system.txt # inspect promptHighlights
- Two modes. Single-topic strings for quick drafts;
prompt.mdfiles
with YAML frontmatter (topic/audience/slides/theme/
language) plus free-text body for controlled generation. - Embedded system prompt. Ships inside the binary, describes the
AI-facing GoSlide subset (frontmatter, layouts, card/chart components).
Dump it with--dump-promptto feed any chat UI manually. - Heuristic auto-fix. Four local rules recover the most common LLM
syntax slips (unclosed code fences, missing frontmatter terminator,
unquoted YAML values with colons, missing trailing newline). Fixes are
reported transparently on stderr. - Safe defaults. Refuses to overwrite existing output unless
--force
is passed. On unrecoverable parse failure, writes<output>.raw.mdand
<output>.fixed.mdnext to the target for diagnosis instead of
clobbering your work. - API keys never touch disk. Read from an environment variable named
bygenerate.api_key_env.
Configuration (goslide.yaml):
generate:
base_url: https://api.openai.com/v1 # or https://openrouter.ai/api/v1, http://localhost:11434/v1, etc.
model: gpt-4o
api_key_env: OPENAI_API_KEY
timeout: 120sExperimental notice. Output quality depends on the chosen model and
prompt wording; semantic quality (flow, accuracy, style) is not guaranteed.
CLI flags and API may change. Review generated slides before presenting.
β Validated Examples
See examples/ai-generated/ for real outputs
produced by openai/gpt-oss-120b:free on OpenRouter β English simple mode
and ηΉι«δΈζ advanced mode (high-school audience, εΏ«ι€ε»ζΏ metaphor). Both
parsed on first pass with no fixup needed. scripts/test-generate-llm.ps1
reproduces the test interactively.
π Documentation
PRD.mdΒ§13 reflects the implemented state- Both English and ηΉι«δΈζ READMEs get a new AI slide generation
section with an experimental warning
No Breaking Changes
v1.1.0 projects work unchanged. The generate: config section is optional
β absent when not using goslide generate.
Full Changelog
See v1.1.0...v1.2.0 for all changes.
v1.1.0
π GoSlide v1.1.0
What's New
π¨ 22 Themes (8 new)
Added 8 community-favorite themes, bringing the total to 22 themes Γ 8 accent colors = 176 visual combinations:
| New Theme | Style | Default Accent |
|---|---|---|
nord-light |
Arctic cool blue-grays | teal |
catppuccin-latte |
Soft warm pastels | pink |
paper |
Warm off-white, editorial | amber |
chalk |
Cool blue-grey, educational | purple |
synthwave |
Neon pink/cyan on deep purple | pink |
forest |
Deep forest greens, earthy | green |
rose |
Warm blush pink | pink |
amoled |
True black OLED, max contrast | blue |
π Card Overlay Polish
- Larger emoji icons (2em) for better visibility
- Proper table spacing with accent-colored borders
- Improved heading, paragraph, and list margins
- Inline code gets background + border-radius styling
π¬ 3D Transitions
perspectiveβ Y-axis 3D rotationflipβ X-axis 3D rotationcubeβ cube-face rotation (experimental)
π Documentation
- Mock API testing workflow documented in README
goslide.yamlvsgoslide.yaml.exampleusage clarified- Theme catalog updated with all 22 themes
Full Changelog
See v1.0.0...v1.1.0 for all changes.
v1.0.0
π GoSlide v1.0.0
Markdown-driven interactive presentations β single binary, offline-first.
β¨ Highlights
- 14 themes β default, dark, corporate, minimal, hacker, dracula, midnight, gruvbox, solarized, catppuccin-mocha, ink-wash, instagram, western, pixel
- 8 accent colors β 112 visual combinations out of the box
- 12 slide layouts β from simple title slides to multi-column and grid-cards
- Interactive components β charts, diagrams, sortable tables, tabs, sliders, toggles, expandable cards
- API dashboards β live data from backend APIs with auto-refresh and proxy support
- Static export β
goslide buildproduces a single self-contained HTML (~7MB), works offline - Host mode β serve a directory as a presentation library with index page
- Speaker view β press S for timer, notes, and next slide preview
- Live reload β edit your .md, browser auto-refreshes and keeps your slide position
π¦ Downloads
| Platform | File |
|---|---|
| Windows (x64) | goslide-windows-amd64.exe |
| macOS (Intel) | goslide-darwin-amd64 |
| macOS (Apple Silicon) | goslide-darwin-arm64 |
| Linux (x64) | goslide-linux-amd64 |
| Linux (ARM64) | goslide-linux-arm64 |
π Quick Start
# Create a presentation
goslide init
# Serve with live reload
goslide serve talk.md
# Export as standalone HTML
goslide build talk.md
# Host multiple presentations
goslide host ./slidesπ Full Feature List
Rendering
- Markdown β Reveal.js slides with
---separators - YAML frontmatter for presentation config
- 14 themes Γ 8 accent colors
- 12 layout templates (two-column, code-preview, grid-cards, etc.)
- Fragment animations (fade-in, fade-up, highlight-current)
- Custom slide transitions (slide, fade, perspective, flip, convex, concave, zoom)
- CJK support with bundled Noto Sans TC font
Components
- Charts: bar, line, pie, radar, sparkline (Chart.js)
- Diagrams: Mermaid.js (flowcharts, sequence, ERD)
- Tables: sortable with click-to-sort headers
- Tabs + Panels: tabbed content switching
- Slider: range input with live value display
- Toggle: switch control with panel visibility binding
- Expandable Cards: grid layout with click-to-expand detail overlay
- API Component: fetch from proxied APIs with 7 render types (metric, chart, table, json, log, image, markdown)
- Embed HTML: raw HTML/CSS/JS execution
- Embed Iframe: embedded external pages
Infrastructure
- Single binary with all assets embedded (~8MB)
- Live reload via WebSocket with slide position preservation
- API reverse proxy with header injection and env var expansion
- Custom theme overrides via goslide.yaml
- Static HTML export (single file, works offline)
- Host mode with index page and directory watching
- Speaker view with notes, timer, next slide preview
- Lightweight presenter sync (viewers see presenter's slide + jump button)
- Progress bar with click-to-jump
CLI
goslide serveβ single file with live reloadgoslide hostβ directory with index pagegoslide buildβ static HTML exportgoslide initβ scaffold from templates (basic, demo, corporate)goslide listβ list presentations with metadata