Skip to content
PowerMD
Language:en Author:AtomForge

Syntax reference

The complete reference for the presentation language. It is embedded below, and the same text is available in the app as a separate page.

pwmd syntax

pwmd turns Markdown into a presentation. Regular Markdown remains the content format: headings, lists, links, tables, blockquotes, images, and fenced code blocks all work normally. Presentation features use standalone HTML-comment directives:

<!-- @directive arguments -->

Prefer spaces just inside the comment delimiters: <!-- @directive --> or <!-- @directive arguments -->. This form is more compatible with Markdown renderers that handle compact comments differently; rendering behavior varies. pwmd also accepts compact comments for backward compatibility.

A directive is only interpreted on its own line and never inside a fenced code block. Invalid directives are left as ordinary hidden HTML comments.

FRONTMATTER

An optional flat frontmatter block at the very beginning sets the presentation title and multiplicative text scales for every slide:

---
title: "Product update"
text-scale: 120%
h1-scale: 150%
h2-scale: 110%
table-scale: 80%
---

# First slide

Presentation content.

title is a nonempty string naming the presentation independently of its filename. It appears in recent-presentation lists; it does not set or change slide headings or @slide titles. Omit it to use the filename or URL as the recent-list label.

Document typography

Supported scale keys are text-scale, h1-scale–h6-scale, table-scale, code-scale, quote-scale, and math-scale. Element base ratios are built into the theme. For example, h1 uses text scale × built-in h1 base × h1-scale. Missing values use the built-in defaults.

Slides and panels

A standalone --- starts a new slide; a standalone *** starts a new panel on the current slide. They are ignored inside fenced code blocks. A slide can contain up to 26 panels.

<!-- @slide Introduction -->

# First panel

***

# Second panel

---

<!-- @slide Next slide -->

# New slide

Slide metadata

Put slide directives at the beginning of a slide, before panel content. Slide-metadata parsing stops at the first non-empty, non-directive line.

Title

<!-- @slide Slide title -->

The title is editor metadata, used in the editor’s slide list and editing UI; the player does not currently render it. If omitted, the editor uses the slide’s first # heading and writes an @slide directive when saving.

Layout and visible grids

<!-- @layout AB/AC -->
<!-- @grid AB/AC -->

Letters identify panel areas. Repeating a letter merges its cells into one rectangular area; / starts a new row. Panel order follows each letter’s first occurrence.

AB/AC

+---+---+
| A | B |
+---+---+
| A | C |
+---+---+
  • @layout hides panel dividers.
  • @grid displays dashed panel dividers.
  • . represents an empty cell.
  • Rows must have equal length and every panel letter must form one contiguous rectangle.
  • Layouts support at most 26 rows, columns, and panels. Invalid layouts fall back to an automatic grid.

Add collapse to reduce the grid’s outer and panel padding:

<!-- @layout AA/BC collapse -->

Slide theme

<!-- @slide-theme stone blue gray -->

The three values are BASE ACCENT FRAME:

  • BASE: background, surface, and text palette
  • ACCENT: highlight color
  • FRAME: frame and divider color

Colors are built-in Tailwind color-family names such as slate, stone, blue, amber, and zinc. A theme affects the whole slide.

Slide background

A slide background can combine a wallpaper image, a color, and a gradient. Only the first directive of each kind takes effect.

<!-- @slide-wallpaper -->
![Background](./images/background.jpg)

<!-- @slide-bg slate-900/70 -->
<!-- @slide-gradient down transparent -> slate-900/70 60% -> slate-950 -->

# Content above the background
  • @slide-wallpaper consumes the following Markdown image; blank lines are allowed in between.
  • @slide-bg accepts a Tailwind color with optional -50…-950 shade and /0…/100 opacity, for example black/50.
  • @slide-gradient uses down, up, left, or right, with ->-separated stops. A stop may have a position, such as blue/60 45%.

Sound

Sound is slide-level YouTube audio. The directive must be followed by a Markdown link.

<!-- @sound autoplay on muted on volume 5 -->
[Soundtrack](https://www.youtube.com/watch?v=VIDEO_ID)

Options are pairs in any order:

  • autoplay on|off — default: off
  • muted on|off — default: off
  • volume 1…10 — default: 7

Browsers generally require muted on for autoplay.

Panel backgrounds

Use the same three background directives without the slide- prefix:

<!-- @wallpaper -->
![Panel background](./images/detail.jpg)

<!-- @bg black/55 -->
<!-- @gradient up black/80 -> transparent -->

# Panel content

Only a panel’s first @bg, @gradient, and @wallpaper are used. @wallpaper consumes its following image.

Content layout

Persistent directives affect following content within the panel until changed. One-off @width, @align, and @scale target only the next content block.

Alignment, width, and columns

<!-- @set-align left -->
<!-- @set-width 60% -->

Narrow, left-aligned content.

<!-- @width 80% -->

Only this paragraph is 80% wide.

This paragraph returns to 60%.

<!-- @set-align center -->
<!-- @set-width reset -->

Full-width centred content again.
  • @align left|center|right|justify sets alignment for the next content block only; without an argument it selects the default center for that block.
  • @set-align left|center|right|justify sets the persistent panel alignment; without an argument it restores center. reset is not an accepted alignment argument.
  • One-off overrides never change persistent defaults, even when a persistent directive follows a pending override. All three scopes reset at each new panel. For example, <!-- @set-align left -->, then <!-- @align right --> aligns the next block right and subsequent content left. Combine it with <!-- @width 80% --> and <!-- @scale 120% --> to independently style that block.
  • @width N% sets only the next content block’s width, then the persistent width resumes. @width reset is a one-off 100%.
  • @set-width N% sets the persistent width for following blocks in this panel. @set-width reset restores 100%.
  • Width defaults to 100% in each panel and is relative to that panel’s available content width, not the slide. Alignment defaults to center. Pending one-off width and alignment skips whitespace, layout directives, spacers, and hidden presenter notes; it applies to Markdown blocks (including headings, lists, code and tables), callouts, or media. Float/cover/contain retain their own explicit sizing.
  • @columns N [GAP] sets CSS columns for Markdown text. N is 1–12; GAP is 0–999 cqw units.
<!-- @columns 2 4 -->

Longer text in two columns.

<!-- @col-break -->

This paragraph starts in the next column.

<!-- @columns -->

@col-break starts the following Markdown content in the next CSS column. It only has an effect while @columns is active.

Scale

<!-- @set-scale 90% -->
This and the following content remain at 90%.

<!-- @scale 130% -->
Only this next content block is at 130%.

@set-scale PERCENT changes the persistent scale from that point onward. @scale PERCENT applies only to the next content block, then the persistent scale resumes. Both scale every text type after its document-level typography multipliers; they do not resize images or video. Use @set-scale 100% to restore the default block scale.

Colors

<!-- @color amber -->
This is amber.

<!-- @color reset -->
This uses the default text color.

@color accepts a color name or inline-color index 1, 2, or 3.

<!-- @set-colors cyan rose lime -->

_First color_, __second color__, ___third color___.

<!-- @color 2 -->
This uses the second color.
  • @set-colors COLOR1 COLOR2 COLOR3 overrides the inline palette for the rest of the panel.
  • @set-colors reset restores the default palette.
  • @set-color-1, @set-color-2, and @set-color-3 override one palette entry; use reset to restore it.
  • Defaults are amber, violet, and emerald.

Spacing

Top content.

<!-- @space -->

Bottom content.

@space fills the remaining panel height.

First block.

<!-- @gap 4 -->

Second block.

@gap N inserts an empty block N cqw high (N: -999–999). A negative value reduces the space before the following block, pulling it upward.

<!-- @set-gap 3 -->

# Heading

A paragraph.

<!-- @set-gap reset -->

@set-gap N changes the normal gap between panel content blocks. reset, or no argument, restores the default gap.

Progressive reveal

Visible immediately.

<!-- @reveal -->
Visible on the first next step.

<!-- @reveal 3 -->
Visible on step three.

<!-- @reveal end -->
Visible immediately again.

Reveal steps are shared across every panel on the slide. Hidden blocks retain their space and fade in. An unnumbered @reveal receives the next automatic step; blocks with the same explicit number appear together.

Block content

Callouts and notes

<!-- @callout warning -->
# Attention
> Highlighted content.
> It may span multiple lines.

The heading is optional; at least one quoted (>) line is required. Built-in icons: info, tip, success, warning, danger, error, question, quote, love, like, dislike.

Markdown callouts also work:

>[!warning] Attention
>Highlighted content.

Use <!-- @note --> directly before a blockquote to make it speaker-only; the audience will not see it. The paired mobile remote renders these notes as Markdown.

<!-- @note -->
> **Presenter cue:** Explain the feature demonstrated on this slide.
> Mention the next step before advancing.

An ordinary blockquote without @note remains visible audience content.

Images

A standalone Markdown image is normal Markdown content. @img turns the following image into a media block:

<!-- @img 16:9 rounded -->
![Description](./images/hero.jpg)

The optional ratio is WIDTH:HEIGHT; optional shape is rounded, square, or circle.

YouTube, QR, and draw.io

Each directive consumes the next Markdown link:

<!-- @youtube autoplay on muted on volume 5 -->
[Demo](https://youtu.be/VIDEO_ID?t=1m30s)

<!-- @qr -->
[Open presentation](https://example.com/deck.md)

<!-- @drawio -->
[Architecture](./diagrams/architecture.drawio)

@youtube supports autoplay on|off, muted on|off, and volume 1…10; URL t or start sets its start time. @qr generates a clickable QR code. @drawio renders a diagrams.net file.

@qr and @drawio can consume a data fenced block instead of a link:

<!-- @qr -->
```data
Any QR payload.
```

<!-- @drawio -->
```data
<mxfile>…</mxfile>
```

A gallery consumes the following contiguous Markdown list:

<!-- @gallery 4s rows-2 -->
- ![First](./images/one.jpg) 6s
- ![Second](./images/two.jpg)
- ![Third](./images/three.jpg) 3s

The first duration (ms or s) is the default, with a default of 5s and maximum of 60s. Images may have individual durations. rows-N requests 1–12 rows; galleries support up to 100 images.

@cover, @contain, and @float

@cover and @contain are panel-level display directives. Put one of them at the beginning of a panel, alongside panel background directives. They apply to the panel’s first supported content block, not merely to the line immediately following the directive. The directive may appear elsewhere in the source, but normalization moves it to the panel header.

<!-- @cover -->

# Introductory heading

![Full-panel image](./images/hero.jpg)

In this example the heading remains normal content and the image is the first supported target, so it fills the panel. @cover crops an image when necessary; @contain fills the panel while preserving the image aspect ratio, which is useful for diagrams and SVGs.

<!-- @contain -->

![System architecture](./diagrams/architecture.svg)

Only the first @cover or @contain in a panel takes effect. Supported targets are standalone Markdown images, tables, fenced code blocks, and @img, @youtube, @qr, @gallery, @callout, or @space blocks. If the panel has no supported target, the directive has no visual effect.

@float places its next block at one side so following content can flow next to it:

<!-- @float right 40% 3 -->
<!-- @img rounded -->
![Illustration](./images/example.jpg)

This Markdown can flow beside the image.

Syntax: @float left|right WIDTH [GAP]; WIDTH is a percentage and GAP is in cqw. The target can be an image, table, fenced code block, or @img, @youtube, @qr, @drawio, @gallery, @callout, or @space.

Markdown extensions

Formulas

A $$ pair on its own lines renders a KaTeX display formula:

$$
\sum_{i=1}^{n} i = \frac{n(n+1)}{2}
$$

Mermaid

flowchart LR
  A[Idea] --> B[Plan] --> C[Launch]

A fenced code block with language mermaid renders as a diagram.

Frontmatter limits

The frontmatter block supports flat key: value lines, not general YAML structures such as nested mappings, lists, or multiline values. Keep it at the very beginning of the document; outside that header, standalone --- lines separate slides. Use slide and panel directives for their local presentation settings.

Sizing guide

Use this section when planning a deck manually or asking an AI to author one. Values using cqw are proportional: 1cqw is 1% of the slide container width, so a value scales with the presentation instead of being a fixed pixel size.

Player baseline

Element Default size Planning implication
Panel safe padding 5cqw on every side Keep ordinary content inside this area. @cover and @contain intentionally remove it.
Body text 1.25cqw, 1.5 line-height A full-width slide supports short, presentation-sized paragraphs rather than document-length prose.
Default block gap about 0.8cqw Consecutive Markdown blocks already have breathing room.
H1 about 4.5cqw Use for one primary statement, usually no more than one per panel.
H2 about 2.75cqw Use for section labels or a secondary message.
H3 about 1.8cqw Use for small subsections or grouped points.
H4–H6 about 1.25–1.5cqw Use sparingly; body text, lists, or callouts are often clearer.

The first heading in a Markdown block has no top margin. Later headings receive a section gap. A heading immediately after @col-break also starts without a top margin.

Practical ranges

Need Recommended starting point Notes
Normal content width @set-width 100% Default in every panel; @width 100% is a one-block override.
Readable text measure @set-width 55%–75%, or one-off @width 60% Use persistent width for several blocks, one-off width for a statement, quotation, or compact explanation.
Side visual with flowing text `@float left right 30%–45% 2`
Deliberate vertical space @gap 2–6 Use negative values only for small optical corrections, such as @gap -1 or @gap -2.
Default gap between content blocks @set-gap 1–3 Do not use a large panel-wide gap if only one relationship needs space; prefer @gap.
Two text columns @columns 2 2–4 Best on a wide, single-panel slide; avoid columns in narrow grid panels.
Image/video ratio 16:9, 4:3, or 1:1 Choose a ratio that matches the source. Use @cover for edge-to-edge media and @contain for an uncropped full-panel diagram or SVG.
Dense material @set-scale 90% or one-off @scale 80%–90% Reduce scale before adding too much content, but avoid making presentation text document-sized.

Authoring rules for AI

  1. Treat each panel as one visual idea. A multi-panel slide needs correspondingly shorter content per panel.
  2. Start with one # heading or a short H2-level label; do not stack several large headings unless demonstrating typography.
  3. Prefer 3–6 short list items over a long paragraph. Keep nested lists shallow.
  4. Use @columns for parallel, scannable material—not to fit more prose. @col-break is for intentional column starts.
  5. Use persistent @set-width or one-off @width, @float, @cover, and @contain to establish hierarchy before changing text scale.
  6. Leave room for headings, images, tables, and reveal steps. Hidden reveal content still reserves its layout space.
  7. Check the result at the intended aspect ratio and screen size; cqw preserves proportions, but it cannot make overloaded content readable.