Extensions: templates, themes and palettes

This section is for people comfortable with code. You can make and present slides without it.

mdeck can be extended in three ways, and all three follow the same rules.

  • A template is a slide layout: which content areas a slide has, which settings it accepts, and how it is arranged. Built-in layouts such as title and split are templates too.
  • A theme is the overall look: fonts, spacing, the slide frame and the default colours. A deck picks one with design:.
  • A palette is a set of colours that repaints any theme. A deck picks one with palette:.

Every extension is a folder with an extension.toml file inside. The manifest says which kind it is and describes its supporting files and settings. The folder name is the identifier used in slide files.

Example
extensions/
  comparison/          a template
    extension.toml
    layout.jsx
    styles.css
    starter.md
  my-theme/            a theme
    extension.toml
    styles.css
  my-colors/           a palette
    extension.toml

mdeck looks in two places, in this order: its own built-in collection under assets/extensions/ and an extensions/ folder beside the slide file. Inside either place, a folder that contains extension.toml is an extension; any other folder is simply a group and is searched further, so extensions/colors/ocean/ works just as well as extensions/ocean/. Identifiers must be unique within their kind across both places. A local extension cannot quietly replace a built-in one; a duplicate stops the command with a message naming both files.

The same registry backs mdeck check, mdeck extensions, mdeck templates, the mdeck new wizard, the dev server and builds, so what a check accepts is what a build can load.

Shared settings#

Example
schema = 1              # manifest format version; always 1 for now
kind = "palette"        # template, theme or palette
id = "ocean"            # must equal the folder name
title = "Ocean"         # readable name shown in lists and controls
description = "Deep blue with a warm highlight."   # optional
  • id uses lowercase letters, digits and hyphens and starts with a letter.
  • Unknown settings are errors, so a typo is reported rather than ignored.
  • File references are relative to the extension folder and may not leave it.
  • Manifests are TOML 1.0. CSS custom property names start with dashes, so quote them as keys: "--accent" = "#ff0000".

Problems are reported with the file, the setting and, for syntax errors, the line and column:

Example
extensions/ocean/extension.toml: tokens.accent: token names look like "--accent"
extensions/ocean/extension.toml:7:12: incomplete declaration: value expected

Palette#

Example
schema = 1
kind = "palette"
id = "ocean"
title = "Ocean"
description = "Deep blue with a warm highlight."
dark = true

[tokens]
"--bg" = "#102030"
"--surface" = "#1c2a3c"
"--ink" = "#ffffff"
"--ink-soft" = "#d8e0ea"
"--muted" = "#8ea0b4"
"--rule" = "#2c3c50"
"--accent" = "#ffbd69"
"--accent-2" = "#7fd1c8"
"--on-accent" = "#102030"

tokens lists the CSS custom properties the palette overrides. The nine tokens above are the shared vocabulary every theme uses; see palettes for what each one does. dark = true marks a dark palette so code colours and the logo are adjusted for a dark background.

Template#

Example
schema = 1
kind = "template"
id = "comparison"
title = "Side-by-side comparison"
description = "Two options next to each other."
frame = "standard"          # standard, title, chapter or none

[files]
layout = "layout.jsx"       # default; may be omitted
styles = "styles.css"       # optional; picked up automatically when present
starter = "starter.md"      # optional; picked up automatically when present

[regions.body]
description = "Heading and introduction"

[regions.left]
required = true

[regions.right]
required = true

[properties.emphasis]
type = "string"
enum = ["none", "left", "right"]
default = "none"

regions must include body. properties describe values under a slide's props: and support type (string, number, integer, boolean, array, object), default, enum, required, minimum, maximum, minItems, maxItems, items, plus title and description for editors. Nested settings use TOML sub-tables:

Example
[properties.ratio]
type = "array"
minItems = 2
maxItems = 2
default = [1, 1]

[properties.ratio.items]
type = "number"
minimum = 0.01

The layout file is Preact JSX that imports from mdeck/template-api. See templates for the renderer contract. Layout code runs as part of the deck: it is trusted code, not sandboxed data.

Theme#

Example
schema = 1
kind = "theme"
id = "my-theme"
title = "My theme"
description = "Calm sans-serif slides."
dark = false
accent2 = false              # true when the theme uses --accent-2
fonts = [
  "https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap",
]

[files]
styles = "styles.css"        # one stylesheet or a list of them

[tokens]
"--bg" = "#ffffff"
"--surface" = "#f4f4f2"
"--ink" = "#111111"
"--ink-soft" = "#333333"
"--muted" = "#6b6b6b"
"--rule" = "#e2e2de"
"--accent" = "#2455c7"
"--fs-body" = "34px"
"--font-body" = "\"Inter\", system-ui, sans-serif"

[params.primaryColor]
token = "--accent"
title = "Primary color"

[params.fontBody]
token = "--font-body"
title = "Body font"
  • tokens are the theme's default custom-property values. mdeck generates the :root block from them, so the stylesheet only contains rules, and the presenter's colour controls show the same defaults that are rendered.
  • params name the settings authors may change under params: in the deck. Each points at a token; its default is the token's value, so nothing is written twice.
  • fonts are stylesheet URLs loaded in normal builds. Self-contained builds skip them and use the fallbacks named in the token values.
  • dark = true makes the theme dark by default. accent2 = true shows the second accent control; add accent2Preview when the --accent-2 token is a CSS expression rather than a colour the control can display.

Values are applied in this order: theme tokens, palette tokens, deck params, then the accent and accent2 shorthands.

Editing in the browser#

mdeck edit my-talk.md includes editors for all three kinds under Palettes, themes & templates. Palettes and theme tokens are forms with live preview; theme stylesheets and template layouts are text areas. Built-in extensions are read-only there; copy one into the deck under a new id to change it. The editor writes the same files described above.

Listing what is available#

In your terminal
mdeck extensions my-talk.md
mdeck extensions my-talk.md --json

The JSON form carries every manifest's title, description, tokens, parameters, region requirements and property definitions, so other tools can build controls from the same data mdeck uses.