{"slug": "show-hn-slidown-markdown-to-powerpoint-in-pure-go-no-ai-in-generation", "title": "Show HN: Slidown – Markdown to PowerPoint in pure Go, no AI in generation", "summary": "Slidown, a pure-Go tool for converting Markdown to PowerPoint files without AI, has been released as an open-source sibling to the deck Google Slides tool. It writes standalone .pptx files via a native OOXML writer, supports in-place updates that preserve manual edits, and offers watch mode for automatic rebuilds. The tool is designed to work interchangeably with deck from the same Markdown source.", "body_md": "`slidown`\n\nis a tool for creating PowerPoint (`.pptx`\n\n) presentations from Markdown.\n\nIt is a sibling project of [ k1LoW/deck](https://github.com/k1LoW/deck), a\nMarkdown → Google Slides tool by\n\n[@k1LoW](https://github.com/k1LoW).\n\n`slidown`\n\nshares `deck`\n\n's philosophy of *Markdown for content, slide tooling for design*, and adopts the same Markdown format and element mapping. The difference is the output target:\n\n`slidown`\n\nwrites standalone `.pptx`\n\nfiles via a pure-Go OOXML\nwriter, with no third-party Office dependencies.`deck`\n\nand `slidown`\n\nare designed to be used together or interchangeably from\nthe same Markdown source, so you can pick the right delivery target — Google\nSlides or PowerPoint — without rewriting your slides.\n\n**Homebrew:**\n\n``` bash\n$ brew install Songmu/tap/slidown\n```\n\n**go install:**\n\n``` bash\n$ go install github.com/Songmu/slidown/cmd/slidown@latest\n```\n\nWrite your slides in Markdown:\n\n```\n---\ntitle: Talk about slidown\n---\n\n# First slide\n\n## A subtitle\n\n- a bullet point\n- **bold** and *italic* and `code`\n  - a nested point\n\n---\n\n# Second slide\n\nA paragraph with a [link](https://example.com).\n```\n\nThen apply it to a `.pptx`\n\n:\n\n``` bash\n$ slidown apply deck.md\nWrote deck.pptx (2 slide(s))\n```\n\nBy default the output file is the input file name with a `.pptx`\n\nextension.\nOverride it with `--output`\n\n/`-o`\n\n, or with the `output`\n\nfrontmatter field:\n\n``` bash\n$ slidown apply deck.md -o talk.pptx\n```\n\nIf the output `.pptx`\n\nalready exists, `apply`\n\nupdates it in place. Slides\nwhose source content has not changed keep their existing slide parts\nverbatim, so manual edits made in PowerPoint to unchanged slides are\npreserved; only changed slides are regenerated:\n\n``` bash\n$ slidown apply deck.md -o deck.pptx\nUpdated deck.pptx (2 slide(s))\n```\n\nImage-only differences (recompression, reordering or repositioning) are treated as unchanged, so adjusting images in PowerPoint does not trigger a regenerate.\n\nTo make reuse robust against page reordering, give a page a stable `key`\n\n—\notherwise pages are matched by position:\n\n``` php\n# Overview\n\n<!-- {\"key\": \"overview\"} -->\n```\n\nA page can also be **frozen** with the `freeze`\n\npage configuration. A\nfrozen page keeps its existing slide as-is on rebuild even if its Markdown\nchanged — useful for pinning a slide you have hand-tuned in PowerPoint:\n\n``` php\n# Hand-tuned slide\n\n<!-- {\"freeze\": true} -->\n```\n\nTo bring in a slide **pasted from another presentation**, declare a keyed,\nfrozen placeholder page for it in the Markdown and paste the slide at that\nposition in PowerPoint:\n\n``` php\n# Imported slide\n\n<!-- {\"key\": \"imported-architecture\", \"freeze\": true} -->\n```\n\nOn rebuild, `apply`\n\npairs the placeholder with the pasted slide by position,\nkeeps the pasted slide verbatim (`freeze`\n\n), and stamps the `key`\n\nonto it — so\nlater rebuilds match it by key even after reordering. The deck source is\nauthoritative for keys: a key renamed or removed in the Markdown is updated or\ncleared on the slide accordingly, and `freeze: true`\n\nneed only stay in the\nMarkdown.\n\nUse `--watch`\n\n(or `-w`\n\n) to keep `apply`\n\nrunning and automatically re-apply\nwhen the deck markdown file changes:\n\n``` bash\n$ slidown apply deck.md --watch\nWrote deck.pptx (2 slide(s))\nUpdated deck.pptx (2 slide(s))\n```\n\n`slidown`\n\nwatches the deck file's directory so editor atomic-save patterns\n(`rename`\n\n/`remove`\n\n+ `create`\n\n) are handled, filters events to the deck file,\nand debounces bursts so one save triggers one rebuild. If a rebuild fails, the\nerror is printed and watch mode keeps running until you stop it with `Ctrl-C`\n\n.\n\n`--watch`\n\nand `--template`\n\nare mutually exclusive. `--template`\n\nis only for\ninitial generation; when you need watch mode with a template, set `template`\n\nin the config file instead.\n\nMVP scope: watch mode currently tracks deck markdown file changes only.\n\nSupply a `.pptx`\n\n(or `.potx`\n\n) whose theme, slide masters and layouts should\nbe used as the design when creating a new output file:\n\n``` bash\n$ slidown apply deck.md --template theme.pptx\n```\n\nA template can only be supplied when the output file does not yet exist. It\nmay also be set with the `template`\n\nconfig field. When the output already\nexists it is updated in place, reusing itself as the template, and passing\n`--template`\n\nis an error (choose a different `--output`\n\n, or remove the file\nfirst). See [docs/templates.md](/Songmu/slidown/blob/main/docs/templates.md) for layout selection,\ninspecting available layouts with `ls-layouts`\n\n, and repurposing existing\nplaceholders as subtitle targets. Templates can also include a\n[ style layout](/Songmu/slidown/blob/main/docs/templates.md#style-layout) to customize inline syntax and\ntable styling. Incremental updates reuse unchanged slides from the existing\noutput file and still honor\n\n`freeze: true`\n\n.The Markdown used by `slidown`\n\nconsists of an optional YAML frontmatter and\na body. Slides are separated by a line of three or more hyphens (`---`\n\n).\n\n```\n---\ntitle: Talk about slidown\noutput: talk.pptx\n---\n\n# First Slide\n\nContent...\n```\n\n`title`\n\n(string): The title of the presentation, written to the generated`.pptx`\n\ndocument properties (metadata).`output`\n\n(string): Output`.pptx`\n\npath (used when`--output`\n\nis not given).`breaks`\n\n(boolean): Control how single line breaks are rendered. Default (`false`\n\n) renders them as spaces;`true`\n\npreserves them as line breaks.`codeBlockToImageCommand`\n\n(string): Command used to convert code blocks to images (see[Code blocks to images](#code-blocks-to-images)).`defaults`\n\n(array): Conditional page configuration using CEL expressions.\n\n`slidown`\n\nfollows the same Markdown specification as `deck`\n\n: CommonMark\nplus selected GitHub Flavored Markdown extensions (tables, strikethrough),\nwith a restricted set of raw inline HTML for text-level semantics\n(`<mark>`\n\n, `<kbd>`\n\n, `<sub>`\n\n, `<sup>`\n\n, `<u>`\n\n, …). Speaker notes are written\nas HTML comments (`<!-- ... -->`\n\n).\n\nWithin each slide, headings are mapped to placeholders by depth:\n\n- The\n**shallowest** heading on the slide →**title** - The\n**next** heading level →**subtitle** - Everything else →\n**body**\n\nSee [docs/markdown.md](/Songmu/slidown/blob/main/docs/markdown.md) for the full Markdown reference,\nincluding supported/unsupported features, inline-style mappings and\nline-break handling. A few edge behaviors (notably how content that overflows\nthe available placeholders is handled) currently differ from `deck`\n\nand are not\nyet a stable contract; these are called out inline in that reference.\n\n`slidown`\n\nreads optional global configuration:\n\n`${XDG_CONFIG_HOME:-~/.config}/slidown/config-{profile}.yml`\n\n(with`--profile`\n\n)`${XDG_CONFIG_HOME:-~/.config}/slidown/config.yml`\n\n```\nbreaks: true\ncodeBlockToImageCommand: \"go run ./cmd/txt2img\"\ntemplate: \"theme.pptx\"\n```\n\nSettings in frontmatter take precedence over the configuration file. The\n`template`\n\nfield is honored only from the configuration file (or the\n`--template`\n\nflag) and only when creating a new output file; it cannot be\nset in a deck's frontmatter.\n\nYou can convert Markdown code blocks to images by specifying a command that\noutputs image data (PNG/JPEG/GIF) to standard output, or to a file via the\n`{{output}}`\n\nplaceholder:\n\n``` bash\n$ slidown apply deck.md --code-block-to-image-command \"some-command\"\n```\n\nThis is useful for rendering diagrams (e.g. Mermaid) or syntax-highlighted code as images.\n\n`slidown`\n\nis under active development. `apply`\n\nalready reuses unchanged\nwhole slides; finer-grained intra-slide (sub-element) diffing is future\nwork. See [docs/design.md](/Songmu/slidown/blob/main/docs/design.md) for the architecture and the\nincremental-rebuild design.\n\n—`k1LoW/deck`\n\n`slidown`\n\nis a sibling project of`deck`\n\nand reuses its Markdown parsing and content model. The Markdown specification, the element-to-slide mapping rules and much of the surrounding design come from`deck`\n\n. Many thanks to[@k1LoW](https://github.com/k1LoW)and the`deck`\n\ncontributors.", "url": "https://wpnews.pro/news/show-hn-slidown-markdown-to-powerpoint-in-pure-go-no-ai-in-generation", "canonical_source": "https://github.com/Songmu/slidown", "published_at": "2026-07-07 04:54:56+00:00", "updated_at": "2026-07-07 04:58:56.808944+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Slidown", "deck", "k1LoW", "Songmu", "GitHub", "Homebrew", "Go", "PowerPoint"], "alternates": {"html": "https://wpnews.pro/news/show-hn-slidown-markdown-to-powerpoint-in-pure-go-no-ai-in-generation", "markdown": "https://wpnews.pro/news/show-hn-slidown-markdown-to-powerpoint-in-pure-go-no-ai-in-generation.md", "text": "https://wpnews.pro/news/show-hn-slidown-markdown-to-powerpoint-in-pure-go-no-ai-in-generation.txt", "jsonld": "https://wpnews.pro/news/show-hn-slidown-markdown-to-powerpoint-in-pure-go-no-ai-in-generation.jsonld"}}