# Technical Documentation: jupyter-book/mystmd

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/jupyter-book/mystmd)

### Overview (`README.md`)

# MyST Markdown Command Line Interface, `mystmd`

[](https://github.com/jupyter-book/mystmd/blob/main/LICENSE)

[](https://discord.mystmd.org)

`mystmd` is a set of open-source, community-driven tools designed for scientific communication, including a powerful authoring framework that supports blogs, online books, scientific papers, reports and journals articles.

## Overview

The `mystmd` project provides a command line tool (`mystmd`) for working with MyST Markdown projects.

- Provides functionality for cross-referencing, external structured links, and scientific citations
- Translate and render MyST Markdown into:
  - HTML for static websites, and modern React for interactive websites (like this website!)
  - PDFs and LaTeX documents, with specific templates for over 400 journals
  - Microsoft Word export
- Parse MyST into a standardized AST, that follows the MyST Markdown Spec

See the [documentation](https://mystmd.org/guide).

## Get Started

Ensure that you have an updated version of Node installed (<https://nodejs.org/>):

```bash
node -v
>> v20.4.0
```

The MyST Markdown CLI is available through NPM, PyPI and Conda:

```bash
# Using npm, yarn, or pnpm
npm install mystmd
# Or using PyPI
pip install mystmd
# Or using Conda / Mamba
conda install mystmd -c conda-forge
```

Usage:

```bash
myst init
myst start
myst build my-doc.md --tex
```

# Development

See [the Contribution Guide](CONTRIBUTING.md) for information on setting up a development environment.

---

As of v1.0.0 this package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).

---

---

### Overview (`.changeset/README.md`)

# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

---

### Overview (`docs/README.md`)

# Contribute to the documentation

This folder contains the content for the [MyST Guide at mystmd.org/guide](https://mystmd.org/guide).

See [the documentation contribution guide for more information](contribute-docs.md).

---

### Overview (`packages/jats-to-myst/README.md`)

# jats-to-myst

Convert a JATS XML document to MyST AST

---

### Overview (`packages/jtex/README.md`)

# jtex

`jtex` is a command line tool (CLI) for rendering LaTeX documents from jinja-style templates. This package uses Jinja2 as the template engine with a modified environment and syntax that plays well with LaTeX's markup.

## Installation

Install the package into your virtual environment using pip:

```bash
npm install jtex
```

and confirm correct installation by typing:

```bash
jtex --version
```

---

### Overview (`packages/myst-cli-utils/README.md`)

# myst-cli-utils

Simple utilities for myst CLI tools.

---

### Overview (`packages/myst-cli/README.md`)

# myst-cli

See the [docs](https://mystmd.org/cli).

---

### Overview (`packages/myst-common/README.md`)

# myst-common

Common utilities and types for MyST.

---

### Overview (`packages/myst-directives/README.md`)

# myst-directives

Default directive definitions for MyST parser.

## Directives

These directives are ported from `markdown-it-docutils`:

- `admonitions`
- `code` / `code-block`
- `math`
- `image`
- `list-table`
- `figure`

---

### Overview (`packages/myst-execute/README.md`)

# MyST Execute

Kernel execution of code and inline expressions using Jupyter.

This package provides a transform that takes a MyST tree, computes the executable content, and stores the results in the AST. It provides basic support for caching of outputs to avoid needless computation.

---

### Overview (`packages/myst-ext-button/README.md`)

# myst-ext-button

`mystmd` extension for `button` role

---

### Overview (`packages/myst-ext-card/README.md`)

# myst-ext-card

`mystmd` extension for `card` directive

---

### Overview (`packages/myst-ext-exercise/README.md`)

# myst-ext-exercise

`mystmd` extension for `exercise` directive

---

### Overview (`packages/myst-ext-grid/README.md`)

# myst-ext-grid

`mystmd` extension for `grid` directive

---

### Overview (`packages/myst-ext-icon/README.md`)

# myst-ext-icon

`mystmd` extension for `icon` role

---

### Overview (`packages/myst-ext-proof/README.md`)

# myst-ext-proof

`mystmd` extension for `proof` directive

---

### Overview (`packages/myst-ext-reactive/README.md`)

# myst-ext-card

`mystmd` extension for `card` directive

---

### Overview (`packages/myst-ext-tabs/README.md`)

# myst-ext-tabs

`mystmd` extension for `tab-set` and `tab-item` directives

---

### Overview (`packages/myst-migrate/README.md`)

# myst-migrate

Utilities for upgrading and downgrading MyST ASTs

---

### Overview (`packages/myst-parser/README.md`)

# myst-parser

MyST (Markedly Structured Text) is designed to create publication-quality documents written entirely in Markdown. The main use case driving the development and design of MyST is [JupyterBook](https://jupyterbook.org/), which helps you create educational online textbooks and tutorials with Jupyter Notebooks and narrative content written in MyST. `myst-parser` is a javascript parser for MyST markdown that brings these capabilities into a web-native environment.

## Goals

- Provide a Javascript implementation of MyST markdown
- Parse MyST into a standardized AST, based on [mdast](https://github.com/syntax-tree/mdast).
- Serialize `mdast` into a default HTML for all known roles and directives
- Expose an opinionated set of `markdown-it` plugins, to be used in ecosystems that require `markdown-it` (e.g. vscode)
- Expose extension points in MyST for new roles/directives
- Provide functionality for cross-referencing that is usually completed by Sphinx (e.g. in the [Python implementation](https://github.com/executablebooks/MyST-Parser))

## Usage

```bash
npm install myst-parser
```

In a node environment:

```javascript
import { mystParser } from 'myst-parser';
import { State, transform, mystToHast, formatHtml } from 'myst-to-html';
import rehypeStringify from 'rehype-stringify';
import { unified } from 'unified';

const pipe = unified()
  .use(mystParser)
  .use(transform, new State())
  .use(mystToHast)
  .use(formatHtml)
  .use(rehypeStringify);

const file = pipe.processSync(':::{important}\nHello to the world!\n:::');
console.log(file.value);
>> <aside class="admonition important"><p class="admonition-title">Important</p><p>Hello to the world!</p></aside>
```

In a browser:

```html
<html>
  <head>
    <script src="https://unpkg.com/myst-parser"></script>
  </head>
  <body onload="init();">
    <div id="output"></div>
    <script>
      function init() {
        const pipe = unified()
          .use(mystParser)
          .use(transform, new State())
          .use(mystToHast)
          .use(formatHtml)
          .use(rehypeStringify);
        const result = pipe.runSync('# Hello to the world!');
        const html = pipe.stringify(result);
        document.getElementById('output').innerHTML = html;
      }
    </script>
  </body>
</html>
```

## `myst-parser` Features

- CommonMark
- Admonitions
- Figures
- Images
- Math
  - role
  - directive (equations)
  - dollar math
  - amsmath
- Tables
  - GFM
  - List Tables
- References
  - ref
  - numref
  - eq
  - links
  - Including numbering (single document)
- Code Directives
  - Code
  - Code blocks
  - Code cell
- Blocks
- Comments
- Targets
- HTML:
  - `sub`
  - `sup`
  - `abbr`
- Definition List
- Footnotes

Not yet complete:

- div
- proof
- margin
- sidebar
- colon fence
- Citations
- Bibliography
- Epigraph
- Glosary
- Terms
- Tabs
- Panels
- CSV Tables
- Multi-document

## Developer Install

For installing the package locally, you will need [node](https://nodejs.org/) and [npm](https://docs.npmjs.com/about-npm), both can use a global install on your system.

Once you have `npm` installed globally, navigate into this project folder and install the dependencies:

```bash
cd myst-parser
npm install
npm run start  # Start a development server to play with the library! 🚀
```

The scripts for building, testing, and serving the project are in the [package.json](package.json), the main ones to use are
`npm run test`, `npm run build`, and `npm run start`.

### `npm run build`

Builds the library, including compiling the typescript and bundling/minification to create `myst.min.js` which can be used in the browser directly.
This outputs to the `dist` folder, and also includes all type definitions (`*.d.ts`) in the types folder.

### `npm run test`

Run the tests, these are mostly based on the [fixtures](fixtures) folder. You can also use `npm run test:watch` to run on any file changes.

### `npm run start`

Starts a server for manually testing and playing with `myst-parser`, this uses a in-memory bundle of what would go in the `dist` folder.
Note that this does not actually build the library!

---

### Overview (`packages/myst-roles/README.md`)

# myst-roles

Default role definitions for MyST parser.

## Roles

These roles are ported from `markdown-it-docutils`:

- `sup`/`superscript`
- `sub`/`subscript`
- `abbr`/`abbreviation`
- `eq`
- `ref`
- `numref`
- `math`

---

### Overview (`packages/myst-spec/README.md`)

# MyST Spec

> :warning: The MyST AST specification is still in dev; any structures or features present in the JSON schema may change at any time without notice.

MyST (Markedly Structured Text) is designed to create publication-quality, computational documents written entirely in Markdown. The main use case driving the development and design of MyST is [JupyterBook](https://jupyterbook.org/), which creates educational online textbooks and tutorials with Jupyter Notebooks and narrative content written in MyST.

MyST is a superset of [CommonMark](https://commonmark.org/) (a standard form of Markdown) and allows you to directly create “directives” and “roles” as extension points in the language. These extensions points are influenced by [ReStructured Text (RST)](https://en.wikipedia.org/wiki/ReStructuredText) and [Sphinx](https://www.sphinx-doc.org/) -- pulling on the nomenclature and introducing additional standards where appropriate. `directives` are block-level extension points, like callout panels, tabs, figures or embedded charts; and `roles` are inline extension points, for components like references, citations, or inline math.

````md
```{directive} Argument
The *content* of a directive can have {role}`with content`
```
````

## Goals

`myst-spec` is designed to standardize implementations and extensions to MyST, with the goal of making the MyST ecosystem as rich and interoperable as possible. The spec formalizes three formats:

1. the MyST markup syntax, to ensure MyST works as expected across languages and implementations;
2. the MyST abstract syntax tree (AST), to promote an ecosystem of transformations and exports to diverse formats (e.g. latex/word/html/docutils/etc.); and
3. suggested semantic HTML output and CSS class structure, to promote web-accessibility and interoperability of themes.

The `myst-spec` will be improved overtime through enhancement proposals which can be submitted by our multi-stakeholder community. [IN PROGRESS]

## MyST Spec

This repository introduces tests to cover the MyST Spec. These tests cover three target formats: `myst`, `mdast`, and `html`. An simple example test case (in yaml) for a header looks like:

```yaml
cases:
  - title: CommonMark headers
    myst: |-
      # Heading!
    mdast:
      type: root
      children:
        - type: heading
          depth: 1
          children:
            - type: text
              value: Heading!
    html: |-
      <h1>Heading!</h1>
```

[TBD: Do we include latex here, maybe?]

### Markdown Abstract Syntax Tree, `mdast`

Markdown AST, or `mdast`, is an intermediate format that builds upon the existing [mdast spec](https://github.com/syntax-tree/mdast), which is used throughout the [unifiedjs](https://unifiedjs.com/) Javascript community with hundreds of [existing transformations](https://unifiedjs.com/explore/), [utilities](https://unifiedjs.com/explore/keyword/unist-util/) and [serializers](https://unifiedjs.com/explore/keyword/rehype/). `mdast` is simple, with a `type` defining the node optional properties on the node and optional `children` (a leaf node has a `value`).

Beyond CommonMark and GitHub Flavoured Markdown, MyST introduces new directives and roles (like admonitions, citations, equations) following existing standards where they are defined. `mdast` is serializable to JSON or YAML, and can be effectively shared between projects, languages and implementations. The output of this repository is a versioned JSON file that can be used in implementations of MyST.

---

### Overview (`packages/myst-to-docx/README.md`)

# `myst-to-docx`

Export a MyST document to a Microsoft Word file, using [docx](https://docx.js.org/).

## Overview

`myst-to-docx` has a `DocxSerializer` object that you write to as you walk the MyST document. It is a light wrapper around <https://docx.js.org/>, which actually does the export. `myst-to-docx` is write only (i.e. can export to, but can’t read from `*.docx`), and has all standard MyST nodes covered (see below).

`myst-to-docx` can be used in the browser or in node. This library currently only has dependence on `docx`, `myst-frontmatter` and `buffer-image-size` - and the serialization handlers can be edited externally (see `Extended Usage` below).

The AST should be transformed through `myst-transforms` to ensure that all nodes are enumerated.

## Basic usage in browser

The utility `fetchImagesAsBuffers` walks the AST and downloads images into buffers to be used by docx, it also figures out the size and returns an object with `getImageBuffer` and `getImageDimensions`, which need to be passed to the options. If your images are more complex (e.g. they are mermaid diagrams, or Jupyter Outputs), you will need to do more complex preprocessing to create these two functions.

A `Blob` is returned, which can be downloaded client side.

```typescript
import { unified } from 'unified';
import { mystToDocx, fetchImagesAsBuffers, DocxResult } from 'myst-to-docx';

const opts = await fetchImagesAsBuffers(tree);
const file = unified().use(mystToDocx, opts).stringify(tree);
const blob = await (file.result as DocxResult);
```

## Basic usage in node

In node, the image dimensions are discovered using a node-only package, and don't need to be provided. The result of the conversion in node is a `Buffer` as the `file.result`, which can be saved to disk.

```typescript
import { unified } from 'unified';
import { mystToDocx, DocxResult } from 'myst-to-docx';

const file = unified()
  .use(mystToDocx, {
    getImageBuffer(url) {
      return fs.readFileSync(url).buffer;
    };
  })
  .stringify(tree);
const buffer = await (file.result as DocxResult);
```

## Extended usage

Instead of using the `defaultDocxSerializer` you can override or provide cusome serializers.

```ts
import { DocxSerializer, defaultNodes, defaultMarks } from 'myst-to-docx';

const nodeSerializer = {
  ...defaultNodes,
  my_paragraph(state, node) {
    state.renderInline(node);
    state.closeBlock(node);
  },
};

export const myDocxSerializer = new DocxSerializer(nodeSerializer, defaultMarks);
```

The `state` is the `DocxSerializerState` and has helper methods to interact with `docx`.

## Supported Block Nodes

- text
- link
- paragraph
- heading (levels)
  - Including numbering of headings
- blockquote
- code
  - TODO: No styles supported
- thematicBreak
- break
- list
- listItem
- image
- math
  - Including numbering
- inlineMath
- crossReference
- abbreviation
- block
- definitionList
- definitionTerm
- definitionDescription
- container
- caption
- captionNumber
- tables

## Supported Style Nodes

- emphasis
- strong
- inlineCode
- subscript
- superscript
- delete (strikethrough)
- underline
- smallcaps

## Resources

- [docx](https://docx.js.org/)
- [myst-spec](https://github.com/jupyter-book/myst-spec)

---

### Overview (`packages/myst-to-html/README.md`)

# myst-to-html

Convert a MyST AST to HTML.

```typescript
import { u } from 'unist-builder';
import { mystToHtml } from 'myst-to-html';

const html = mystToHtml(u('root', [u('paragraph', [u('text', 'hello world')])]));
// '<p>hello world</p>'
```

---

### Overview (`packages/myst-toc/README.md`)

# myst-toc

Utilities to parse a MyST table of contents.

## Overview

The MyST ToC format is defined in `types.ts`, from which a JSON schema definition is compiled. The high-level description is as follows:

1. A TOC comprises of an array of TOC items
2. Each TOC item can be

- A file (document)
- A URL (document)
- A collection of child items

3. TOC items containing children _must_ have either a `title` or a document

## Example

Example `myst.yml` under the `toc:` key:

```yaml
toc:
  - title: Main
    file: main.md
  - title: Overview
    children:
      - file: overview-1.md
      - file: overview-2.md
  - url: https://google.com
  - file: getting-started.md
    children:
      - file: getting-started-part-1.md
      - file: getting-started-part-2.md
```

---

### Overview (`packages/myst-transforms/README.md`)

# myst-transforms

`unifiedjs` transforms for working with MyST Markdown documents.

## Overview

These transforms take AST from `mystmd` and turn it into usable forms, enforce document structure, or provide other utilities.

These utilities are available on npm:

```bash
npm install myst-transforms
```

You can use the plugins as follows:

```typescript
import { unified } from 'unified';
import { mathPlugin } from 'myst-transforms';

unified()
  .use(mathPlugin, { macros: {} }) // Add the plugin with any options
  .run(tree); // Run the AST through the set of plugins

// The AST has now been modified in place.
```

---

### Overview (`packages/mystmd-py/README.md`)

# MyST Markdown Command Line Interface, `mystmd`

[](https://github.com/jupyter-book/mystmd/blob/main/LICENSE)


`mystmd` is a set of open-source, community-driven tools designed for scientific communication, including a powerful authoring framework that supports blogs, online books, scientific papers, reports and journals articles.

> **Note**
> The `mystmd` project is in **beta**. It is being used to explore a full MyST implementation and will change significantly and rapidly.
> The project is being developed by a small team of people on the Executable Books Project, and may make rapid decisions without fully public/inclusive discussion.
> We will continue to update this documentation as the project stabilizes.

## Overview

The `mystmd` project provides a command line tool (`mystmd`) for working with MyST Markdown projects.

- Provides functionality for cross-referencing, external structured links, and scientific citations
- Translate and render MyST Markdown into:
  - HTML for static websites, and modern React for interactive websites (like this website!)
  - PDFs and LaTeX documents, with specific templates for over 400 journals
  - Microsoft Word export
- Parse MyST into a standardized AST, that follows the MyST Markdown Spec

See the [documentation](https://mystmd.org/guide).

## Get Started

The MyST Markdown CLI is available through PyPI:

```bash
pip install mystmd
myst init
myst build my-doc.md --tex
```

and Conda:

```bash
conda config --add channels conda-forge
conda config --set channel_priority strict
conda install mystmd
myst init
myst build my-doc.md --tex
```

---

### Overview (`packages/mystmd/README.md`)

# mystmd

The MyST Markdown Command Line interface.

See <https://mystmd.org>

---

### Overview (`packages/simple-validators/README.md`)

# simple-validators

Schema validation functions and error reporting framework

## Scope

This package provides basic validation functions for building more complex schema validation. It is explicit and verbose with no magic to infer anything from existing types. Rather than throwing validation errors, these functions pass error/warning messages out as options and return `undefined`; the consumer may then choose how to handle error reporting.

## Usage

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Overview (`packages/tsconfig/README.md`)

# `tsconfig`

These are base shared `tsconfig.json`s from which all other `tsconfig.json`'s inherit from.

---

### Overview (`packages/myst-common/scripts/README.md`)

# MyST Scripts

This directory contains utility scripts for maintaining the MyST codebase.

## generate-rule-severities.mjs

Automatically generates `packages/myst-common/src/rule-severities.ts` by analyzing the codebase for rule usage patterns.

### What it does

The script:

1. Scans all TypeScript files in the `packages` directory
2. Searches for patterns like:
   - `fileError(..., { ruleId: RuleId.* })` → **error** severity
   - `fileWarn(..., { ruleId: RuleId.* })` → **warn** severity
   - `addWarningForFile(..., 'error', { ruleId: RuleId.* })` → **error** severity
   - `addWarningForFile(..., 'warn', { ruleId: RuleId.* })` → **warn** severity
   - `*ValidationOpts(..., RuleId.*)` → **error** severity (uses both, but errors are critical)
3. Aggregates the severities for each rule
4. Generates the `rule-severities.ts` file with:
   - Default severity for each rule
   - Comments explaining where each rule is used
   - Proper categorization matching the RuleId enum

### Usage

```bash
# From the repository root
node scripts/generate-rule-severities.mjs
```

---

### Overview (`packages/mystmd/tests/url-folders/readme.md`)

# Readme

[xref to subfolder](#my-thing)

[explicit xref to subfolder](two/page.md#my-thing)

---

### Index (`docs/index.md`)

---
title: MyST Markdown Tools
description: MyST (Markedly Structured Text) is designed to create publication-quality documents written entirely in Markdown.
---

{abbr}`MyST (Markedly Structured Text)` is an [ecosystem of open-source, community-driven tools](./overview.md) designed to revolutionize scientific communication. Our powerful authoring framework supports blogs, online books, scientific papers, reports and journals articles.

:::{card} Get Started With MyST 👩‍💻
:link: ./quickstart.md
Start here to get up and running with the `myst` command-line tools.
:::

## Cool MyST Features 🪄

We think {abbr}`MyST (Markedly Structured Text)` is really cool, some of the features that we think stand out are highlighted below with links to places in the documentation where you can reproduce them!

---

🪄🐰 **Rabbit-hole links** allow you to get information to your reader as fast as possible, and they can deep-dive all the way to computations, code and interactive figures. You can play with this demo yourself in [](./quickstart-myst-markdown.md).

:::{figure} ./videos/links.mp4
:class: framed
:::

🪄📊 **Live graphs** can be embedded directly in your documentation or articles with computation backed by Jupyter or JupyterLite – running locally, on Binder, or directly in your browser. Get up and running with Thebe in [](./in-page-execution.md)

:::{figure} ./videos/thebe.mp4
:class: framed
:::

🪄🪐 **JupyterLab support** for MyST comes with inline computations, support for `ipywidgets`, matplotlib sparklines, editable task-lists, rich frontmatter, and beautiful typography and other elements like dropdowns, grids and cards. Install [`jupyterlab-myst`](./quickstart-jupyter-lab-myst.md) today!

:::{figure} ./videos/jupyterlab-myst.mp4
:class: framed
:::

🪄📜 **Export to PDF** is easy with MyST, and we support hundreds of different journals out of the box, see [myst-templates](https://github.com/myst-templates)! You can also export to Microsoft Word or even JATS, which is used in scientific publishing. See the [](./quickstart-myst-documents.md)!

:::{figure} ./images/myst-build.png
:class: framed
:::

---

## Quickstart Tutorials



:::{seealso}
:class: dropdown

# Coming from Jupyter Book V1 or Sphinx?

👋 We are glad you are here! 💚

There are many ways that `mystmd` can be used with Jupyter Book and Sphinx. We recommend that you read [a high-level overview of MyST](./overview.md) as well as [the project background](./background.md), which goes over how these projects overlap and work together!

TL;DR
: **Yes**, you can use `mystmd` with your Jupyter Book! `mystmd` can create [scientific PDFs](./creating-pdf-documents.md) and can natively read the [`_toc.yml`](./table-of-contents.md) as well as all of your existing MyST Markdown content and [Jupyter Notebooks](./interactive-notebooks.ipynb).
: **Yes**, `mystmd` is compatible with [intersphinx](#intersphinx) even though it is written in JavaScript not Python!
: Jupyter Book and `mystmd` have **overlap** in the ability to create online books like this one. `mystmd` has some extra capabilities for [cross-references](./cross-references.md), interactivity and [performance](./accessibility-and-performance.md).
: For more information see this [upgrade guide from Jupyter Book v1 to v2](https://next.jupyterbook.org/upgrade/).
:::

## Cite `mystmd`

To cite or read more references about the `mystmd` project and related tools, see [](./cite.md).

## Project Goals

MyST is part of the [Project Jupyter](https://jupyter.org/) organization, and is an open-source, community-driven project to improve scientific communication, including integrations into Jupyter Notebooks and computational results.

::::{grid} 1 1 2 3

:::{card}
:link: ./citations.md

**Built for Science** 👩‍🔬
^^^

Extend Markdown with equations, cross-references, citations, and export to a preprint or rich, interactive website or book.
+++
MyST for Science »
:::

:::{card}
:link: ./interactive-notebooks.ipynb

**Dynamic Documents** 📈
^^^

Make your pages interactive by connecting to custom JupyterHubs, public Binders or even Python running directly in your browser.
+++
Bring your pages to life »
:::

:::{card}
:link: ./accessibility-and-performance.md

**Fast & Accessible** ⚡️
^^^
Publish next-generation articles and books that are beautifully designed, without compromising on accessibility or performance.
+++
Read about performance »
:::

::::

**Technical Goals**

- `mystmd` is a JavaScript parser and command line tool for working with MyST Markdown
- Parse MyST into a standardized [AST](wiki:Abstract_Syntax_Tree), that follows [the MyST Spec](https://mystmd.org/spec)
- Translate and render MyST into:
  - Modern [interactive websites](./quickstart-myst-documents.md), using React (like this website!)
  - PDFs and $\LaTeX$ documents, with [specific templates for over 400 journals](./creating-pdf-documents.md)
  - Microsoft Word [export](./creating-word-documents.md)
- Provide functionality for [cross-referencing](./cross-references.md), [external structured links](./external-references.md), and [scientific citations](./citations.md)

**Architecture**

The `mystmd` command line tool can be used to parse MyST Markdown and Jupyter Notebooks into an AST. This data can be saved as JSON, or rendered to a website (like this one!) or any number of formats including [PDF & $\LaTeX$](./creating-pdf-documents.md), [Word](./creating-word-documents.md), [React](./quickstart-myst-documents.md), or [JATS](./creating-jats-xml.md).

```{mermaid}
flowchart LR
  A[Jupyter Notebook] --> C
  B[MyST Markdown] --> C
  C(mystmd) --> D{AST}
  D <--> E[LaTeX]
  E --> F[PDF]
  D --> G[Word]
  D --> H[React]
  D --> I[HTML]
  D <--> J[JATS]
```

```{important .dropdown} Using Sphinx or Python?

For integration with **Sphinx**, use the Python implementation for MyST or Jupyter Book V1, which can be found at:

- [MyST Python Parser for Sphinx](https://myst-parser.readthedocs.io/en/latest/)
- [Jupyter Book](https://jupyterbook.org/)

Although many tools in the [MyST Ecosystem](https://mystmd.org) follow the same conventions and [specification](https://mystmd.org/spec), the following documentation refers only to the `mystmd` CLI.
```

---

### Overview (`docs/overview.md`)

# Overview of the MyST stack

This section provides a high-level overview of the main concepts and tools in the MyST ecosystem. See the [guiding principles of the MyST ecosystem](./guiding-principles.md) for some more high-level context.

(overview-build-process)=

## Overview of the MyST build process

The MyST Build process takes input documents from authors and converts them into outputs that are meant for consumption by readers. The [MyST CLI](https://mystmd.org) contains logic to use the MyST Document Engine, renderers, and themes to carry out this entire process. Here's a high-level breakdown of the major steps of that process:

```{list-table}
:header-rows: 1
- - Phase
  - Input
  - Output
- - (1) **Writing**: An author writes content with {term}`MyST Markdown` in a file.
  - Ideas
  - Content (`.md`, `.ipynb`, `.tex`, etc)
- - (2) **Parsing**: A {term}`MyST Document Engine` parses content into structured data called the {term}`MyST AST`. See [](#overview-parsing).
  - Raw content (`.md`, `.ipynb`, etc)
  - Raw MyST AST
- - (3) **Resolving**: Transform raw MyST AST into AST that can be rendered. See [](#overview-transformers).
  - Raw MyST AST
  - Resolved / Processed MyST AST
- - (4) **Rendering**: A {term}`MyST Renderer` transforms the {term}`MyST AST` into components that can be used by a {term}`MyST Theme`.
  - Resolved MyST AST
  - Components that can be rendered into a final output with a _template_ and/or _theme_ (e.g., LaTeX, React, etc).
- - (5) **Theming / templating**: Rendered components are used by a {term}`MyST Theme` to generate final artifacts. See [](#overview-themes).
  - Template components that have been rendered by a MyST renderer.
  - Output formats that are ready for final consumption (e.g., a website or PDF).
```

Here is a brief overview of these steps:

% NOTE: This is an excalidraw SVG. You can edit it directly in Excalidraw.
% See the contributing docs for a short guide.
:::{figure} images/overview-diagram-build.svg
An overview of the "Parsing and Resolving" phase using the MyST Document Engine.
In this stage, a text file written in MyST Markdown is parsed by the {term}`MyST Document Engine` which outputs {term}`MyST AST` that follows the {term}`MyST Specification`. This file undergoes a number of transformations to add metadata, resolve links, and enrich the document. The final output is MyST AST (usually a `.json` file) that can be rendered into many different kinds of outputs.
:::

:::{figure} images/overview-diagram-render.svg
An overview of the "Rendering and Theming" phase using one or more MyST renderers / themes. In this stage, a resolved MyST AST is rendered into multiple components by a MyST renderer. These are building blocks that a theme knows how to convert into a final output. For example, the [MyST React Renderer](https://github.com/jupyter-book/myst-theme/tree/main/packages/myst-to-react) and the [MyST React Themes](https://github.com/jupyter-book/myst-theme/tree/main/themes) know how to use these React components to create a final website.
:::

(overview-parsing)=

## How does parsing work?

The MyST Document engine knows how to parse many kinds of documents into {term}`MyST AST`. This is most-commonly done with Markdown files (`.md`) or Jupyter Notebooks (`.ipynb`) written in {term}`MyST Markdown`, a flavor of Markdown that was designed for the MyST Document Engine.

However, the MyST Engine knows how to parse other kinds of syntax into MyST AST as well. For example, [for admonition compatibility with GitHub Markdown](#admonition-github-compatibility). This is because we see the {term}`MyST AST` as the primary point of _standardization_ for the MyST ecosystem, not the Markdown flavor. Input documents may have many different forms, but once it is parsed into {term}`MyST AST`, the document should have a standardized structure defined by the {term}`MyST Specification`.

## What is the MyST AST and Specification?

The {term}`MyST AST` is a version of parsed MyST content that follows a specific structure so that Renderers can convert into different outputs. MyST AST conforms to the {term}`MyST Specification`. The {term}`MyST Specification` is a superset of [the `mdast` specification](https://github.com/syntax-tree/mdast) (meaning that MyST includes all of the syntax that `mdast` supports, plus some extra ones like Directives).

Here's an example of MyST content, and the same content parsed as MyST AST:

````{list-table}
:header-rows: 1
- - Content
  - AST
- - `**Hello there!**`
  - ```yaml
    - type: block
    children:
      - type: paragraph
        children:
          - type: strong
            children:
              - type: text
                value: Hello there!
    ```
````

The easiest way to understand how {term}`MyST Markdown` gets converted to {term}`MyST AST` is to [explore the MyST Sandbox](https://mystmd.org/sandbox). Click the {kbd}`AST` tab to see the underlying AST structure for anything that you type. The {kbd}`PRE` tab represents the initial parsing phase, and the {kbd}`POST` tab represents the AST after the resolving phase.

If you're building your own renderer or parser, start with the [AST primer](xref:spec/ast-primer). It walks through the node structure, the PRE/POST distinction, and what the spec formalizes vs. what's implementation-specific.

(overview-transformers)=

## How do MyST Transformers work?

MyST Transformers are a way to convert a {term}`MyST AST` node into another type of node. Transformers operate on AST rather than on raw Markdown because AST has more standardized structure to work with.

For example, consider a Markdown link like `[some text](#a-label)`. In MyST Markdown, this defines a **cross-reference** to `#a-label`, but it uses Markdown link syntax. We use a **MyST Transformer** to convert that Markdown to a cross-reference AST node like so:

- First parse the Markdown `[some text](#a-label)`.
- The result is a MyST AST node for a **Markdown link**.
- Next, search the document AST for any Markdown link nodes with a target that starts with `#`. Check if there's [a target](./cross-references.md) for the link. If so, it is meant to be a cross reference.
- If so, converts the Markdown Link node into a Cross Reference node.

Some other uses for Transformers include:

- Lifting metadata from `code-cells` to their parent structures
- Check that figures have alt-texts
- Convert non-standard AST nodes (e.g., ones generated from a custom user directive) into ones that MyST knows how to render[^ex-transform-node].

[^ex-transform-node]: For example, see [this Executable Transform example from Project Pythia](https://github.com/projectpythia-mystmd/cookbook-gallery/blob/main/pythia-gallery.py). It is an example of an [`executable transform`](#executable-plugins), which takes custom `pythia-cookbooks` nodes and converts them (via some HTTP fetches) to a grid of cards by outputting the relevant grid and card AST nodes.

See [](#develop:transforms) for more details about how transforms operate on an AST and what intermediate steps look like.

(overview-themes)=

## How do MyST themes and templates work?

MyST {term}`themes` and MyST {term}`templates` are both related to _exporting_ a resolved MyST AST into one or more final output formats. They differ in the amount of _customizability_ that a user has in altering their behavior, but the end-result is the same (generating an export artifact).

```{glossary}
Templates
: Templates are usually used for [static exports](./documents-exports.md) (like LaTeX or Typst). The are structured like a final document (e.g., a LaTeX template for a specific journal), but with fields that MyST uses to insert document metadata at export time (e.g., a `doc.author` field if you want to insert the author name). See [the `myst-templates` GitHub repository](https://github.com/myst-templates) for a list of templates that you can use and contribute to.

Themes
: Themes expose more customizability than a template (which simply generates static outputs via a Jinja-like filter), but they function similar to a template because they take rendered components as inputs and export a final output. Themes are usually meant for _websites_, because there is a lot more control a website exposes compared to a static document like LaTeX. Themes have more complex logic, and thus their source-code is often in a dedicated repository. For examples, see the [build outputs of the `book` and `article` web themes are `myst-templates`](https://github.com/myst-templates#templates), but their [source code is in `myst-theme`](https://github.com/jupyter-book/myst-theme/tree/main/themes).
```

For a more technical explanation see [the developer guide on themes, templates, and renderers](#develop-renderers-themes).

## Are there other MyST engines?

The [MyST Specification](https://mystmd.org/spec) and [MyST Markdown Syntax](https://mystmd.org/guide) was designed so that others could implement their own parsers, document engines, and renderers using MyST. Although there are presently no independent examples of a true {term}`MyST Document Engine`, the MyST Parser for Sphinx project fulfills a similar role in the Sphinx ecosystem.

The [MyST Parser for Sphinx](https://myst-parser.readthedocs.io) is an extension for [Sphinx](https://sphinx-doc.org) that can parse MyST Markdown into Sphinx's internal document structure. It was created to allow users to parse MyST Markdown syntax into Sphinx for [V1 of Jupyter Book](https://jupyterbook.org). It now exists as an independent extension for the Sphinx community, as Jupyter Book V2 now uses the MyST Document Engine.

:::{note} MyST Parser for Sphinx Compatibility
As the MyST Parser for Sphinx does not support all of the syntax defined in the MyST Guide, or output {term}`MyST AST`, it's not a true {term}`MyST Document Engine` as defined by this project. That's OK! Its goal is to be a useful tool for the Sphinx community that only leverages parts of the MyST ecosystem (the Markdown flavor), which for many people is "good enough."
:::

## How does Jupyter Book relate to MyST?

The MyST Markdown Syntax was originally created to allow [Jupyter Book V1](https://jupyterbook.org) to use the [Sphinx Document engine](https://sphinx-doc.org) with Markdown content[^md], rather than the less well-known <wiki:ReStructuredText> language.

[^md]: Specifically, the [MyST Parser for Sphinx](https://myst-parser.readthedocs.io) was created to move beyond the functionality of the [`recommonmark` project](https://github.com/readthedocs/recommonmark) in order to natively support docutils `roles` and `directives` in Markdown.

Over time, the Jupyter Book team decided that the most sustainable path forward was to maintain its own document engine, the [MyST Document Engine](https://mystmd.org/guide). An early version of the MyST Document Engine was created by [Curvenote](https://curvenote.com). To promote its long-term sustainability, the project was open sourced and further developed in collaboration with the Jupyter Book team. It serves as the engine behind Jupyter Book V2.

You can think of Jupyter Book as a _distribution of the MyST Document Engine_. In other words, Jupyter Book wraps the MyST Document Engine application, with out-of-the-box configuration that supports a multi-page community knowledge base or documentation site. MyST is created and maintained by the [Jupyter Book team](https://compass.jupyterbook.org).

Currently, Jupyter Book and the MyST Document Engine share much of the same functionality. Over time, we imagine that the MyST Document Engine will be a more flexible tool that makes fewer assumptions about the end use-case that it's being used for. Jupyter Book will then have "more opinions" above the base configuration of the MyST Document Engine. That said — we are still figuring this out! We aren't sure the exact relationship the two will have, and will revisit this as we learn more. See [next.jupyterbook.org](https://next.jupyterbook.org) for Jupyter Book V2 documentation, and [see this section of the Contributing Guide](#jb-vs-md) for our approach to documenting the two projects.

## How do MyST and Sphinx compare?

[Sphinx] is an open-source documentation system used in many software projects, especially in the Python ecosystem. It builds an internal representation of technical documents as a tree (see [docutils]) similar to the {term}`MyST AST`. Whilst Sphinx partially defines a specification of sorts[^docutils], a {term}`MyST Document Engine` explicitly publishes its {term}`MyST AST` for other tools to consume.

The Sphinx ecosystem has excellent support for Python documentation, referencing content, as well as externally providing an inventory of references known as [intersphinx]. You can link to Sphinx documentation with a {term}`MyST Document Engine` by using [intersphinx references](#intersphinx), and the official {term}`MyST Document Engine` automatically exposes the information required to allow Sphinx documentation to reference your MyST project.

At this time, the official {term}`MyST Document Engine` does not support the authoring of software API documentation[^api-docs]. As such, if your project is documenting Python software we suggest that you use Sphinx. If your project is primarily tutorials, educational textbooks (including with Jupyter Notebooks), a presentation, or scientific paper, we hope that you find a better fit with the MyST stack!

Sphinx and MyST take very different approaches to publishing to the web. In Sphinx, themes are used to customize the generation of HTML and JavaScript. Sites built using these themes can be deployed to static web servers like [ReadTheDocs](https://readthedocs.com/). In the MyST world, the equivalent to a Sphinx theme is a {term}`MyST Renderer` that consumes the {term}`MyST AST` and outputs HTML and JavaScript for your browser. Formally separating the {term}`MyST Document Engine` that generates {term}`MyST AST` and the {term}`MyST Renderer` that consumes it makes it possible to create rich new experiences with MyST, such as the [SciPy Conference Proceedings](https://proceedings.scipy.org/) website that renders {term}`MyST AST` on the fly.

Although the official engine also supports static HTML outputs, implementing themes as applications makes it easier to build more powerful MyST viewing experiences.

[^api-docs]: In the future, `mystmd` may offer support for Python and JavaScript documentation, and if you want to contribute please discuss on [#1259](https://github.com/jupyter-book/mystmd/issues/1259) and this [video](https://www.loom.com/share/589a947389fb49829c9b712b796d8a7d).
[^docutils]: The Docutils source-code _is_ the specification.

[docutils]: https://docutils.sourceforge.io/
[sphinx]: https://www.sphinx-doc.org/
[intersphinx]: https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html

---

### Quickstart (`docs/quickstart.md`)

---
title: Get Started
subtitle: Your first steps with MyST
subject: MyST Quickstart Tutorial
description: Get up and running with the MyST (Markedly Structured Text) command line interface. MyST is designed to create publication-quality documents written entirely in Markdown.
---

These quickstart tutorials are here to get you up and running on your local computer 👩‍💻.
See [this overview of the MyST ecosystem](./overview.md) for a more conceptual introduction. In this tutorial, you will get up and running from scratch. You will learn how to:

- **write** MyST Markdown 🖊
- **export** PDF, Word and $\LaTeX$ documents 📑
- **create** a website like this one 🌎

:::{note} Goals and Prerequisites
**Goal**: The goal of this tutorial is to help you **install MyST** on your local computer 👩‍💻, create a local website 🌎, and edit elements of the theme to improve the website style 🎨.

**Skills**: It is helpful if you have some familiarity with using the command line, as well as using a text editor and/or JupyterLab.

**Tools**: You'll need a code and notebook editor ([VSCode](https://code.visualstudio.com/) is great, and we recommend [Jupyter Lab](https://jupyter.org/install) for notebooks) as well as access to a CLI.
:::

(lookout-for-tutorial-actions)=

> 🛠 Throughout the tutorial, whenever you're supposed to _do_ something you will see a 🛠

## Install the MyST Markdown CLI

🛠 Install MyST using your preferred packaging ecosystem. (See [](./installing.md) for more details).

:::{tip} Not sure which to pick?
:class: dropdown

The easiest way to install MyST is with the `mamba` package manager. `mamba` is a cross-platform language-agnostic package manager that is useful for users across many data science languages like Python, R, Julia, and JavaScript.
:::

:::{embed} #installing-myst-tabs
:::

🛠 Then, check that MyST has successfully been installed:

```shell
$ myst -v
v1.3.4
```

## Build your first MyST site

Next we'll download some sample content and use MyST to render it as a local web server!

### Download example content

We provide an example project that includes a few simple Markdown files and some Jupyter Notebooks.
Through the course of the tutorials we will add content to these documents that show off some of the features of MyST.

🛠 Download the example content[^no-git], and navigate into the folder:

```bash
git clone https://github.com/jupyter-book/mystmd-quickstart.git
cd mystmd-quickstart
```

[^no-git]: If you aren't familiar with git, it isn't required for this tutorial, you can download the zip file with the contents from the [quickstart repository](https://github.com/jupyter-book/mystmd-quickstart).

### Initialize MyST in the content folder 🚀

Next we will create a `myst.yml` configuration file that is required to render your project.

🛠 Run `myst`

The `myst` command is a shortcut for `myst init`, which has a few more options for writing specific parts of the configuration file and a table of contents for your site.

```shell
$ myst

Welcome to the MyST Markdown CLI!! 🎉 🚀

myst init walks you through creating a myst.yml file.

You can use myst to:

 - create interactive websites from Markdown and Jupyter Notebooks 📈
 - build & export professional PDFs and Word documents 📄

Learn more about this CLI and MyST Markdown at: https://mystmd.org

💾 Writing new project and site config file: myst.yml
```

### Preview your MyST site locally

Preview a rendered version of the quickstart content to make sure that MyST is working properly.

🛠 When prompted, type `Yes` to install and serve your MyST content locally:

```bash
? Would you like to run "myst start" now? Yes
```

or manually serve the quickstart content with the following command:

```bash
myst start
```

Starting the server requires a theme, this will download the default `book-theme` from [the MyST themes](./website-templates.md).
This can take **up to a minute** the first time, and then will be cached in the `_build/templates` directory.

```text
🐕 Fetching template metadata from https://api.mystmd.org/templates/site/myst/book-theme
💾 Saved template to path _build/templates/site/myst/book-theme
⤵️ Installing web libraries (can take up to 60 s)
📦 Installed web libraries in 13 s
📖 Built interactive-graphs.ipynb in 21 ms.
📖 Built paper.md in 32 ms.
📖 Built README.md in 35 ms.
📚 Built 3 pages for myst in 82 ms.

  ✨✨✨  Starting Book Theme  ✨✨✨

⚡️ Compiled in 524ms.

🔌 Server started on port 3000!  🥳 🎉

  👉  http://localhost:3000  👈
```

🛠 Open your web browser to `http://localhost:3000`[^open-port]

[^open-port]: If port `3000` is in use on your machine, an open port will be used instead, follow the link provided in the terminal.

The example site in this tutorial only has three pages and by default the `01-paper.md` page is seen in [](#frontmatter-before), which has minimal styles applied to the content.

:::{figure} ./images/frontmatter-before.png
:width: 50%
:label: frontmatter-before
:class: framed

The myst theme for the `01-paper.md` page without any changes made.
:::

🎉 **Congratulations**, you just built your first MyST site!

## Configuration and structure

The final section of this tutorial takes a closer look at the files that we just created, and aspects of your MyST project that can be customized.

### Folder Structure

If you are using a text editor, for example [VSCode](https://code.visualstudio.com/), open up the folder to explore the files:

```text
quickstart/
  ├── 🆕 _build
  │   ├── exports
  │   ├── site
  │   │   ├── content
  │   │   ├── public
  │   │   └── config.json
  │   ├── temp
  │   └── templates
  │       ├── site/myst/book-theme
  │       └── tex/myst/arxiv_two_column
  ├── images
  │   ├── image.png
  │   └── image.gif
  ├── 01-paper.md
  ├── 02-notebook.ipynb
  ├── README.md
  └── 🆕 myst.yml
```

Running `myst init` added:

- `myst.yml` - the configuration file for your myst project and site
- `_build` - the folder containing the processed content and other `site` assets, which are used by the local web server.

The `_build` folder also contains your templates (including the site template you installed) and any exports you make (when we build a PDF the exported document will show up in the `_build/exports` folder). You can clean up the built files at any time using `myst clean`[^clean-all].

[^clean-all]:
    By default the `myst clean` command doesn't remove installed templates or cached web responses; however, the function can with a:\
    `myst clean --all`, or\
    `myst clean --templates --cache`.

    Before deleting any folders `myst` will confirm what is going to happen, or you can bypass this confirmation with the `-y` option. For example:

    ```text
    Deleting all the following paths:

      - _build/site
      - _build/templates

    ? Would you like to continue? Yes

    🗑 Deleting: _build/site
    🗑 Deleting: _build/templates
    ```

### Configure site and page options

If we open and look inside our `myst.yml` we will see a basic configuration like this:

```yaml
# See docs at: https://mystmd.org/guide/frontmatter
version: 1
project:
  # title:
  # description:
  keywords: []
  authors: []
  # github:
  # bibliography: []
site:
  template: book-theme
  # title:
  # options:
  #   logo: my_logo.png
  nav: []
  actions:
    - title: Learn More
      url: https://mystmd.org/guide
  domains: []
```
:::{note}
As this is a rapidly-evolving project, the actual generated `myst.yml` file that you will see may look a bit different.
:::

There are two important parts to the `myst.yml`:

`project:`
: The project holds metadata about the collection of files, such as authors, affiliations and licenses for all of the files, any of these values can optionally be overridden in a file. To see all of the options see [](./frontmatter.md), which includes which fields can be overridden by files in the project.

`site:`
: The site holds template information about the website, such as the logo, navigation, site actions and which template to use.

🛠 In `myst.yml`: Change the "`# title:`" comment in **site** to "`title: Fancy Title 🎩`" and save

Saving the `myst.yml` will have triggered a "full site rebuild"[^myst-start].
Take a look at the browser tab and you'll see that it has updated:

:::{figure} ./images/frontmatter-site-title.png
:width: 50%
:label: frontmatter-site-title

The site title will control site meta tags, and the browser-tab title, which is appended to each page title in the `book-theme`.
:::

[^myst-start]: If the server stopped, you can restart the server using `myst start`.

:::{seealso} See all Frontmatter options
To see all of the options see [](./frontmatter.md), which includes which fields can be overridden by files in the project.
:::

---

## Next steps ➡️

That's it for this quickstart tutorial!
You've now got MyST installed locally, and the basic structure of a MyST project ready to improve.
You are well on your way to getting started with `myst`.

Here are some things to try for next steps:

- Organize a [Table of contents](./table-of-contents.md)
- Configure [website downloads](./website-downloads.md)
- [Choose a website template](./website-templates.md)
- [Customize logos and favicons](#site-options)

(quickstart-cards)=
+++
Check out the following tutorials for more step-by-step guides:

::::{grid} 1 1 2 2
:::{card} Author enriched MyST articles ✨
:link: ./quickstart-myst-documents.md
Write scientific articles using MyST Markdown with easy-to-use citations, metadata, and cross-references.
:::

:::{card} Executable Documents with MyST 🐍
:link: ./quickstart-executable-documents.md
Learn how to use computation and execution with Jupyter in MyST.
:::

:::{card} Export to static documents 📑
:link: ./quickstart-static-exports.md
Export MyST documents to a Word document, PDF, and $\LaTeX$!
:::

:::{card} MyST Markdown Guide 📖
:link: ./quickstart-myst-markdown.md
See an overview of MyST Markdown syntax with inline demos and examples.
:::

:::{card} Use MyST in Jupyter Interfaces 🌕
:link: ./quickstart-jupyter-lab-myst.md
Learn how to use MyST in Jupyter Interfaces.
:::
::::

---

### Syntax Overview (`docs/syntax-overview.md`)

---
title: MyST Syntax Overview
description: MyST (Markedly Structured Text) is designed to create publication-quality documents written entirely in Markdown.
---

MyST (Markedly Structured Text) is designed to create publication-quality documents written entirely in Markdown. The extensions and design of MyST is inspired by the [Sphinx](https://www.sphinx-doc.org/) and [reStructuredText](https://docutils.sourceforge.io/rst.html) (RST) ecosystems.

MyST is a superset of [CommonMark](./commonmark.md), the standard form of Markdown, and allows you to directly create “directives” and “roles” that extend Markdown to support technical and scientific documents. `directives` are block-level extension points, like [callout panels](./admonitions.md), [tabs](./dropdowns-cards-and-tabs.md), [figures](./figures.md) or [embedded charts](./interactive-notebooks.ipynb); and roles are inline extension points, for components like [cross-references](./cross-references.md), [external references](./external-references.md), [citations](./citations.md), or [inline math](./math.md).

## Directives & Roles

Roles and directives are two of the most powerful parts of MyST. They are kind of like functions, but written in a markup language. They both serve a similar purpose, but roles are written in one line whereas directives span many lines. They both accept different kinds of inputs, and what they do with those inputs depends on the specific role or directive being used.

(syntax:directives)=

### Directives

Directives are multi-line containers that include an identifier, arguments, options, and content. Examples include [admonitions](./admonitions.md), [figures](./figures.md), and [equations](./math.md) (visit this page for the [full list of directives](#directives_list)). At its simplest, you can use directives using a "fence" (either back-ticks or colons[^colon-or-fence]) and the name of the directive enclosed in braces (`{name}`):

[^colon-or-fence]: Which fence type, colon or backtick, is up to you, and either will work. The colon-fence has better fallback when the contents of the directive includes Markdown in non-MyST renderers (like GitHub). The backtick-fence should be used when the contents of the directive is code-like (e.g. a diagram or math!).

(example-fence)=

``````{tab-set}
````{tab-item} Colon Fence
Use a colon fence (`:::`) when the contents of the directive is Markdown, such as [callouts](./admonitions.md) or  [theorems](./proofs-and-theorems.md) this will improve the processing in renderers that do not support MyST:

```{myst}

:::{note}
Here is a note!
:::
```
````
`````{tab-item} Backtick Fence
Use a backtick fence (`` ``` ``) when the contents of the directive is code-like, such as [math](./math.md) or a [diagrams](./diagrams.md), this will ensure any sort of auto-formatting will not attempt to reformat these sections:
````{myst}
```{math}
\mathbf{u} \times \mathbf{v}=\left|\begin{array}{ll}u_{2} & u_{3} \\ v_{2} & v_{3}\end{array}\right| \mathbf{i}+\left|\begin{array}{ll}u_{3} & u_{1} \\ v_{3} & v_{1}\end{array}\right| \mathbf{j}+\left|\begin{array}{ll}u_{1} & u_{2} \\ v_{1} & v_{2}\end{array}\right| \mathbf{k}
```
````
`````
``````

The {myst:directive}`note` directive above doesn't take any arguments, and we didn't add any options. In addition to the directive name and the directive content, directives allow two other configuration points:

1\) **directive arguments** - a list of words that come just after the `{directivename}`.

``````{tab-set}
````{tab-item} Colon Fence
```markdown
:::{directivename} arg1 arg2
My directive content.
:::
```
````
`````{tab-item} Backtick Fence
````markdown
```{directivename} arg1 arg2
My directive content.
```
````
`````
``````

2\) **directive options** - a collection of flags or key/value pairs that come just underneath `{directivename}`.

There are three ways to write directive options: as `:key: value`, as a YAML block, or directly inline.

``````{tab-set}
`````{tab-item} Key value pairs
Options can be included as `:key: val` pairs, which is the default way to include options.
````markdown
```{directivename}
:key1: metadata1
:key2: metadata2

My directive content.
```
````
`````
`````{tab-item} YAML
Options can also be included as `key: val` pairs enclosed by `---` lines, similar to document frontmatter.
This is parsed as YAML, and may be easier for listing many options.


````markdown
```{directivename}
---
key1: metadata1
key2: metadata2
---

My directive content.
```
````
`````
`````{tab-item} Inline Options
Options can be included inline. See [](./inline-options.md) for more information.
````markdown
```{directivename .class-name #label key="value"}
My directive content.
```
````
`````
``````

```{tip}
Specifying directive keywords with `:key:` or `---` will make no difference. Use the `:key: val` syntax as a shorthand for just one or two keywords. Use the `---` syntax if you have many keywords you wish to specify, or if some values will span multiple lines.
```

### Roles

Roles are very similar to directives, but they are written entirely in one line. The syntax of a role is:

```markdown
Some content {rolename}`and here is my role's content!`
```

Of course, roles will only work if `rolename` is a valid role name! The `abbr` role creates inline abbreviations, for example, `` {abbr}`MyST (Markedly Structured Text)` `` will become {abbr}`MyST (Markedly Structured Text)`! When you hover over[^1] the abbreviation you will see the `title` appear!

[^1]: Abbreviations are also great structured data for screen-readers!

Roles are defined inline, with an identifier and input. There are a number of roles included in MyST, including abbreviations, subscript, and superscript, as well as inline [](./math.md). Unknown roles will still be parsed as well:

```{myst}
Here is an {abc}`unknown role`.
```

Options for roles can be included inline. See [](./inline-options.md) for more information.

```markdown
Here is my {span #label .class-name key="value"}`custom span`.
```

(nesting-content)=

## Nesting content blocks in Markdown

If you’d like to nest content blocks inside one another in Markdown (for example, to put a `{note}` inside of a `{margin}`), you may do so by adding extra backticks (`` ` ``)[^colon] to the outer-most block.
For example, two [admonitions](./admonitions.md) nested in side of each other:

`````{myst}
````{important}
```{note}
Here's my `important`, highly nested note! 🪆
```
````
`````

[^colon]: You can also use this same technique and add colons to the initial directive or fence. See an [example](#example-fence) of when to use each syntax.

This works for literal code blocks as well. For example, to show triple-backticks on this page we are using following syntax:

`````{myst}
````
```
```
````
`````

---

### Packages Jtex Docs Index (`packages/jtex/docs/index.md`)

---
title: jtex
description: jtex is a command line tool and library for rendering LaTeX documents from Jinja-style templates.
---

`jtex` is a command line tool (CLI) for rendering $\LaTeX$ documents from Jinja-style templates. This package uses [nunjucks](https://mozilla.github.io/nunjucks/) (a port of Jinja) as the template engine with a modified environment and syntax that plays well with $\LaTeX$'s markup.

::::{grid} 1 1 2 3

:::{card}
:link: ./create-a-latex-template.md

**Create a Template** 🆕
^^^
Learn how to create a $\LaTeX$ template for a scientific journal article or Beamer presentation using `jtex` and MyST Markdown.
:::

:::{card}
:link: https://github.com/myst-templates

**Browse Templates** 🚀
^^^
Our $\LaTeX$ templates are curated by the MyST community and include templates to render over 400 journals!
:::

:::{card}
:link: ./command-line.md

**Command Line Interface** ✨
^^^
Use `jtex` to list templates, quickly render content, or fix your `template.yml`, or parse your $\LaTeX$ files for used packages.
:::
::::

```{important}
:class: dropdown
# Looking for Templates?

MyST Templates are available in the [myst-templates organization](https://github.com/myst-templates) on GitHub. You can also see all listed community templates using `myst templates list`, or browse the [api](https://api.mystmd.org/templates/tex) if you are into JSON.

To create your own template see [](./create-a-latex-template.md).
```

## Project Goals

- Provide a data-driven templating markup for $\LaTeX$
- Provide validation of templates and supplied options when rendering a template
- Work with standardized frontmatter to make authors, affiliations, etc. easy to template
- Work with the MyST ecosystem of tools
- Support many user supplied templates, local templates, etc.

**Not Goals**

- Translation of MyST to $\LaTeX$, instead see `myst-to-tex` or [using pandoc with `jtex`](pandoc-comparison.md)

## Installation

Install the package globally using npm:

```bash
npm install jtex
```

and confirm correct installation by typing:

```bash
jtex --version
```

## Usage with MyST

The main usage for `jtex` is with `myst` and `curvenote` command line tools,
both of which can compile markdown into $\LaTeX$ for templating with `jtex`.

## Simple Example

A document can be used very simply with the document as `doc`, the contents of which are
documented in [](document.md). Be sure to include the `[-IMPORTS-]` and the `[-CONTENT-]`.

```latex
% template.tex
\documentclass{article}

[-IMPORTS-]

\title{[-doc.title-]}
\author{[-doc.authors[0].name-] ([-doc.authors[0].email-])}

\begin{document}
\maketitle

[-CONTENT-]

The End!
\end{document}
```

---

### Packages Myst Cli Docs Index (`packages/myst-cli/docs/index.md`)

---
title: myst-cli
description: myst-cli is a command line tool for processing MyST markdown files
---

[](https://www.npmjs.com/package/myst-cli)

`myst-cli` is a command line tool for processing MyST markdown files

---

### Packages Myst Parser Docs Index (`packages/myst-parser/docs/index.md`)

# myst-parser

[](https://www.npmjs.com/package/myst-parser)
[](https://github.com/jupyter-book/mystmd/blob/master/LICENSE)
[](https://github.com/jupyter-book/mystmd/actions)
[](https://executablebooks.github.io/myst-parser)

{abbr}`MyST (Markedly Structured Text)` is a flavor of markdown inspired from the Sphinx ecosystem and {abbr}`RST (reStructuredText)`.

Any [CommonMark](https://commonmark.org/) markdown (such as [Jupyter Notebook](https://jupyter.org) markdown) is natively supported by the MyST parser. The goal of MyST _javascript_ parser ([myst-parser](https://github.com/jupyter-book/mystmd)) is to have overlap with Sphinx ecosystem and {abbr}`RST (reStructuredText)` and provide a flexible parser and renderer that can be used with other content workflows.

```{important}
For integration with **Sphinx**, use the Python reference implementation for MyST parser, which can be found at:

<https://myst-parser.readthedocs.io/en/latest/>

The following documentation refers only to the Javascript MyST parser.
```

The focus of `mystmd` is on components that are useful in rendering books, papers & reports. This project is associated with [JupyterBook](https://jupyterbook.org/) and maintained by the [Executable Books Community](https://executablebooks.org/).

## Package Responsibilities

The `myst-parser` package provides a Javascript implementation of the [MyST](https://myst-parser.readthedocs.io) parser, with the many of the standard directives and roles included.

- Parse MyST flavored markdown, which includes directives, roles, and block elements
- Export a Markdown Abstract Syntax Tree (`mdast`) that is tested against the MyST specification
- Provide extension point for additional directives and roles to be added
- Provide a serializer into standard html for all known roles and directives
  - CSS styling will not be enforced or provided by this repository
- Provide extension point for cross-referencing between multiple documents

## Supported Syntax

- CommonMark Markdown
- Admonitions (callouts)
- References and citations
- Figures, with cross-references
- Math & equations, with cross-references
- Common roles and directives that constitute "Core MyST"

## Design Choices and Related Packages

The `myst-parser` package currently uses `markdown-it` for parsing markdown. This includes packages that are elsewhere in the executablebooks community including:

- [markdown-it-dollarmath](https://github.com/executablebooks/markdown-it-dollarmath) - Math extensions to support inline $\LaTeX$ math surrounded by `$`
- [markdown-it-amsmath](https://github.com/executablebooks/markdown-it-amsmath) - Support math that starts with `\begin{equation}`, etc. directly in the content

The package also includes community supported markdown-it plugins (e.g. `markdown-it-footnote`, and others as necessary).

```{note}
`myst-parser` may adopt portions of the [unified](https://unifiedjs.com/) ecosystem in the future, but will continue to support basic `markdown-it` parsing as this is required in extending markdown parsers in, for example, [VSCode](https://github.com/executablebooks/myst-vs-code).
```

---

### Packages Myst Spec Docs Index (`packages/myst-spec/docs/index.md`)

# MyST Specification

MyST (Markedly Structured Text) is designed to create publication-quality, computational documents written entirely in Markdown. The main use case driving the development and design of MyST is [JupyterBook](https://jupyterbook.org/), which creates educational online textbooks and tutorials with Jupyter Notebooks and narrative content written in MyST.

## Overview

There are three components that this documentation and repository aims to formalize:

1. the MyST markup language, which is a superset of [CommonMark](https://commonmark.org/) (a standard form of Markdown);
2. the MyST abstract syntax tree (AST), which is the datastructure of a document after it has been parsed, and can be used in transforming and rendering content; and
3. a set of unit-tests that can be used to test implementations of MyST (e.g. in Python and Javascript).

## MyST Markup Language

MyST is a superset of [CommonMark](https://commonmark.org/) (a standard form of Markdown) and allows you to directly create “directives” and “roles” as extension points in the language. These extension points are influenced by [ReStructured Text (RST)](https://en.wikipedia.org/wiki/ReStructuredText) and [Sphinx](https://www.sphinx-doc.org/) -- pulling on the nomenclature and introducing additional standards where appropriate. `directives` are block-level extension points, like callout panels, tabs, figures or embedded charts; and `roles` are inline extension points, for components like references, citations, or inline math.

## MyST Abstract Syntax Tree

Fundamentally, the specification for MyST documents can be broken down into abstract syntax tree (AST) node types and their document-level counterparts. The `myst-spec` AST builds on [Markdown AST, or `mdast`](https://github.com/syntax-tree/mdast), an intermediate format that in turn builds upon the existing [Universal Syntax Tree, or `unist` spec](https://github.com/syntax-tree/unist). `unist` is used throughout the [unifiedjs](https://unifiedjs.com/) Javascript community with hundreds of [existing transformations](https://unifiedjs.com/explore/), [utilities](https://unifiedjs.com/explore/keyword/unist-util/) and [serializers](https://unifiedjs.com/explore/keyword/rehype/). `unist` has a simple format, with a `type` defining the node optional properties on the node and optional `children` (a leaf node has a `value`).

The MyST AST introduces nodes for directives and roles, as well as numerous new features, like admonitions, citiations, and equations, all of which build upon `mdast` and other existing standards and nomenclature. The MyST AST, like `mdast`, is serializable to JSON or YAML, and can be effectively shared between projects, languages, and implementations.

## MyST Test Cases

To validate implementations of the MyST spec, a suite of test cases is provided [here in `myst.tests.json`](https://unpkg.com/browse/myst-spec/dist/). This file is a JSON list of test cases with MyST markup, MyST AST, and example HTML in some cases. The cases are similar to [CommonMark test cases](https://spec.commonmark.org/) with the addition of the AST representation. The MyST test cases include all the CommonMark examples as well as many MyST specific examples.

```{note}
These test cases are still being expanded as the spec is developed.  They do not yet include all edge cases and are also subject to change as the spec is developed.
```

```{attention}
**Test Cases**

Test cases are available for download here: https://unpkg.com/browse/myst-spec/dist/
```

## Working with the MyST AST

```{warning}
The `myst-spec` AST is in development; any structures or features present in the JSON schema may change at any time without notice.
```

This documentation contains all the node types used to construct a MyST document. Conventionally, the AST representation of a MyST document represents the state immediately after parsing. This means, for example, references are not resolved, directive/role structures are still present, etc. You may work with AST nodes by either modifying or adding to them to modify and update the corresponding MyST document, or you may transform and reduce them into a simpler structure to consume in other contexts.

---

### Packages Myst To Jats Docs Index (`packages/myst-to-jats/docs/index.md`)

---
title: myst-to-jats
description: myst-to-jats is library for converting MyST documents to JATS XML.
---

[](https://www.npmjs.com/package/myst-to-jats)

`myst-to-jats` is a library for converting MyST documents into JATS.

**Goals**

- Convert from `myst-spec` AST documents into JATS XML

**Not Goals**

- Read JATS, this package is for serialization only - see `jats-to-myst`

## Installation

Install the package into your virtual environment using npm:

```bash
npm install myst-to-jats
```

## Simple example

Below we construct a AST tree using `unist-builder`, use the `mystToJats`
plugin in a `unified` pipeline and `stringify` the document into a $\LaTeX$ file.

```typescript
import { unified } from 'unified';
import { u } from 'unist-builder';
import mystToJats from 'myst-to-jats';

// Create a AST document, or parse using mystmd
const tree = u(
  'root',
  u('paragraph', [
    u('text', { value: 'This is a unicode “fraction”: ' }),
    u('inlineMath', { value: '½' }),
  ]),
);
// Use the plugin, and stringify the tree
const file = unified().use(mystToJats).stringify(tree);
// Log the results
console.log(file.result.value);
```

The document that we fed in was quite simple, and the `½` unicode characters as well as the quotes are nicely transformed into the appropriate $\LaTeX$:

```latex
This is a unicode ``fraction'': $\frac{1}{2}$
```

## Overview

The `myst-to-jats` library aims to translate all standard MyST syntax to sensible $\LaTeX$ syntax, as well as be extensible to other plugins.

---

### Packages Myst To Md Docs Index (`packages/myst-to-md/docs/index.md`)

---
title: myst-to-md
description: myst-to-md is library for converting MyST abstract syntax trees to markdown.
---

[](https://www.npmjs.com/package/myst-to-md)

`myst-to-md` is a library for converting MyST abstract syntax trees to markdown.

**Goals**

- Convert from `myst-spec` AST documents into markdown
- Work as a `unifiedjs` plugin and in the `mystmd` ecosystem

**Not Goals**

- Read Markdown, this package is for serialization only

## Installation

Install the package into your virtual environment using npm:

```bash
npm install myst-to-md
```

## Simple example

Below we construct a AST tree using `unist-builder`, use the `mystToMd`
plugin in a `unified` pipeline and `stringify` the document into a Markdown file.

```typescript
import { unified } from 'unified';
import { u } from 'unist-builder';
import mystToMd from 'myst-to-md';

// Create a AST document, or parse using mystmd
const tree = u(
  'root',
  u('paragraph', [
    u('text', { value: 'This is a unicode “fraction”: ' }),
    u('inlineMath', { value: '½' }),
  ]),
);
// Use the plugin, and stringify the tree
const file = unified().use(mystToMd).stringify(tree);
// Log the results
console.log(file.result.value);
```

## Overview

The `myst-to-md` library aims to translate all standard MyST syntax to markdown, as well as be extensible to other plugins.

---

### Packages Myst To Tex Docs Index (`packages/myst-to-tex/docs/index.md`)

---
title: myst-to-tex
description: myst-to-tex is library for converting MyST documents to LaTeX.
---

[](https://www.npmjs.com/package/myst-to-tex)

`myst-to-tex` is a library for converting MyST documents into LaTeX.

**Goals**

- Convert from `myst-spec` AST documents into $\LaTeX$ markup
- Work with [jtex](xref:jtex) to template documents
- Work as a `unifiedjs` plugin and in the `mystmd` ecosystem

**Not Goals**

- Read LaTeX, this package is for serialization only

## Installation

Install the package into your virtual environment using npm:

```bash
npm install myst-to-tex
```

## Simple example

Below we construct a AST tree using `unist-builder`, use the `mystToTex`
plugin in a `unified` pipeline and `stringify` the document into a $\LaTeX$ file.

```typescript
import { unified } from 'unified';
import { u } from 'unist-builder';
import mystToTex from 'myst-to-tex';

// Create a AST document, or parse using mystmd
const tree = u(
  'root',
  u('paragraph', [
    u('text', { value: 'This is a unicode “fraction”: ' }),
    u('inlineMath', { value: '½' }),
  ]),
);
// Use the plugin, and stringify the tree
const file = unified().use(mystToTex).stringify(tree);
// Log the results
console.log(file.result.value);
```

The document that we fed in was quite simple, and the `½` unicode characters as well as the quotes are nicely transformed into the appropriate $\LaTeX$:

```latex
This is a unicode ``fraction'': $\frac{1}{2}$
```

## Overview

The `myst-to-tex` library aims to translate all standard MyST syntax to sensible $\LaTeX$ syntax, as well as be extensible to other plugins.

---

### Packages Myst Transforms Docs Index (`packages/myst-transforms/docs/index.md`)

---
title: myst-transforms
description: myst-transforms contains a number of transformations for MyST ASTs
---

[](https://www.npmjs.com/package/myst-transforms)

`myst-transforms` is a library for transforming `myst` markdown documents.

## Overview

These transforms take AST from `mystmd` and turn it into usable forms, enforce document structure, or provide other utilities.

These utilities are available on npm:

```bash
npm install myst-transforms
```

You can use the plugins as follows:

```typescript
import { unified } from 'unified';
import { mathPlugin } from 'myst-transforms';

unified()
  .use(mathPlugin, { macros: {} }) // Add the plugin with any options
  .run(tree); // Run the AST through the set of plugins

// The AST has now been modified in place.
```

---

### Packages Myst Transforms Docs Overview (`packages/myst-transforms/docs/overview.md`)

---
title: What's in store
description: List of transforms included in the myst-transforms package.
---

## List of Transforms

Admonitions
: Add headers to each admonition (callout), such as `Note` or `Important`.
: Optionally replace the header with the first paragraph of text if it is all bold.

Blocks
: Ensure that all blocks in a document are not nested.

Blockquotes
: Change attributed blockquotes, those that include a single list item to a figure of `kind` quote, and add the attribution as a figure caption.

Caption
: Ensure that figure captions are in paragraphs

Code
: Audit code to ensure that languages are specified, or provide a default language
: Ensure that `python` as a language is replaced from `IPython3` or other kernal-like language specifiers.

CodeBlock
: Codeblocks can live inside of figures, have captions and be references. Transformation ensures that this information isn't lost from the original parsing of AST.
: Note: this should move into the parser in the future.

Footnotes
: Pull the footnote definitions into a reference object.

HTML
: Parse HTML nodes and replace their contents.

HTML Ids
: Ensure that referenceable nodes have proper HTML Ids (start with a letter, no spaces or fancy characters)
: HTML Ids are more strict than the internal labels used for cross-references, and this is up to the transform to provide, not the renderer.

Images
: Add alt text to images if it is not defined, from the captions.

Keys
: Add unique identifiers to each node, helpful for rendering as well as referring to a document in the wild. These are not aiming to be persisted across multiple builds of the document, for that you should use a label (and associated HTML Id).

Math
: Use KaTeX to create and provide errors/warnings about math rendering.

Math Label
: Parse latex to strip \label and simple equation environments from math, and put this in AST directly.

MyST Cleanup
: A few utilities for lifting children and getting rid of some information about the parsed document from MyST. For example, the `mystDirective` and `mystRole` wrapper nodes are removed.

Targets
: Propagate targets (i.e. `(my-id)=`) to the following node
: Add HTML friendly identifiers to headings.

## Plugin Collections

A few of the plugins are exposed in a `basicTransformationsPlugin` that does a number of the expected transformations without any user supplied options.  
See the code (look for function `basicTransformations` in file `packages/myst-transforms/src/basic.ts`) for exactly which plugins are included.

If you are depending on this, ideally use the individual plugins directly, which will always provide options.

---

### Packages Myst Spec Docs Features Overview (`packages/myst-spec/docs/features/overview.md`)

# Overview

MyST (Markedly Structured Text) is designed to create publication-quality documents written entirely in Markdown. The main use case driving the development and design of MyST is [JupyterBook](https://jupyterbook.org/), which helps you create educational online textbooks and tutorials with Jupyter Notebooks and narrative content written in MyST. The extensions and design of MyST is inspired by the [Sphinx](https://www.sphinx-doc.org/) and [ReStructured Text](https://docutils.sourceforge.io/rst.html) (RST) ecosystems.

> MyST is designed to harness the extensibility and community of RST and bring these super-powers into Markdown.

MyST is a superset of [CommonMark](./commonmark.md) (the standard form of Markdown) and allows you to directly create “directives” and “roles” as extension points in the language. `directives` are block-level extension points, like [callout panels](./admonitions.md), tabs, [figures](./figures.md) or embedded charts; and roles are inline extension points, for components like [references](./references.md) or [inline math](./math.md).

## Directives & Roles

Roles and directives are two of the most powerful parts of MyST. They are kind of like functions, but written in a markup language. They both serve a similar purpose, but roles are written in one line whereas directives span many lines. They both accept different kinds of inputs, and what they do with those inputs depends on the specific role or directive being used.

### Directives

Directives are multi-line containers that include an identifier, arguments, options, and content. Examples include [admonitions](./admonitions.md), [figures](./figures.md), and [equations](./math.md).

#### Specification

```{include} ../nodes/directive.md

```

#### Example

```{include} ../examples/directive.md

```

In addition to the directive name and the directive content, directives allow two other configuration points:

1\) **directive arguments** - a list of words that come just after the `{directivename}`.

````
```{directivename} arg1 arg2
My directive content.
```
````

2\) **directive options** - a collection of flags or key/value pairs that come just underneath `{directivename}`.

There are two ways to write directive options

`````{list-table}
* - 2a) Options as `:key: val` pairs.\
    Great for a few options.
  - 2b) Options as `key: val` pairs enclosed by `---` lines.\
    This is parsed as YAML, and easier for listing many options.
* - ````
    ```{directivename}
    :key1: metadata1
    :key2: metadata2

    My directive content.
    ```
    ````
  - ````
    ```{directivename}
    ---
    key1: metadata1
    key2: metadata2
    ---

    My directive content.
    ```
    ````
`````

```{tip}
Remember, specifying directive keywords with `:key:` or `---` will make no difference. We recommend using `---` if you have many keywords you wish to specify, or if some values will span multiple lines. Use the `:key: val` syntax as a shorthand for just one or two keywords.
```

### Roles

Roles are very similar to directives, but they are written entirely in one line.

#### Specification

```{include} ../nodes/role.md

```

#### Example

```{include} ../examples/role.md

```

Of course, roles will only allow custom behavior work if `name` is a valid role name! The `abbr` role creates inline abbreviations, for example, `` {abbr}`MyST (Markedly Structured Text)` `` will become {abbr}`MyST (Markedly Structured Text)`! When you hover over[^1] the abbreviation you will see the `title` appear!

[^1]: Abbreviations are also great structured data for screen-readers!

Roles are defined inline, with an identifier and input. There are a number of roles included in MyST, including abbreviations, subscript, and superscript, as well as inline [](./math.md).

## Nesting content blocks in Markdown

If you’d like to nest content blocks inside one another in Markdown (for example, to put a {note} inside of a {margin}), you may do so by adding extra backticks (`) to the outer-most block. This works for literal code blocks as well.

For example, the following syntax:

`````
````
```
```
````
`````

yields

````
```
```
````

Thus, if you’d like to nest directives inside one another, you can take the same approach. For example, the following syntax:

`````
````{important}
```{note}
Here's my `important`, highly nested note! 🪆
```
````
`````

produces a nested, `important` > `note`:

````{important}
```{note}
Here's my `important`, highly nested note! 🪆
```
````

---

### Abbreviations.Yml (`docs/abbreviations.yml`)

version: 1
project:

  abbreviations:
    # Alphabetical order
    AMS: American Mathematical Society
    API: Application Programming Interface
    AST: Abstract Syntax Tree
    CLI: Command Line Interface
    CRediT: Contributor Roles Taxonomy
    CSS: Cascading Style Sheet
    CSV: comma-separated values
    DOI: Digital Object Identifier
    ESM: ECMAScript Modules
    GPU: Graphics Processing Unit
    HTML: Hypertext Markup Language
    ID: Identifier
    ISNI: International Standard Name Identifier
    JATS: Journal Article Tag Suite
    JSON: JavaScript Object Notation
    LTS: Long Term Support
    MyST: Markedly Structured Text
    NISO: National Information Standards Organization
    OA: Open Access
    PDF: Portable Document Format
    PID: Persistent Identifier
    POSIX: Portable Operating System Interface
    REES: Reproducible Execution Environment Specification
    ROR: Research Organization Registry
    RRID: Research Resource Identifier
    RST: reStructuredText
    SPDX: Software Package Data Exchange
    TLA: Three Letter Acronym
    TOC: table of contents
    TPU: Tensor Processing Unit
    URL: Uniform Resource Locator
    VoR: Version of Record
    WASM: WebAssembly
    YAML: Yet Another Markup Language
    XML: Extensible Markup Language

---

### Accessibility And Performance (`docs/accessibility-and-performance.md`)

---
title: Accessibility and Performance
short_title: Accessibility & Performance
description: MyST builds documents and websites that are accessible to everyone and quick to load on any device.
---

## Accessibility

Most of the user-facing interface lives in [`myst-theme`](https://github.com/jupyter-book/myst-theme).
These default themes build on top of [Remix](https://remix.run/), which provides sensible accessibility defaults. This section describes the broader goals and considerations around accessibility for the MyST themes.[^scope]

[^scope]: **This page is scoped to the default MyST themes**

    This page describes the **default MyST website themes** (the Remix-based [`book` and `article` themes](https://github.com/jupyter-book/myst-theme) that ship with `mystmd`). Sites built with a custom theme or a different renderer may behave differently.

    For more information about accessibility across all of Jupyter, see the [Jupyter Accessibility Working Group](https://jupyter-accessibility.readthedocs.io).

:::{card} Open an a11y issue »
:link: https://github.com/jupyter-book/myst-theme/issues/new?labels=a11y
If you find a barrier on a MyST site, open an issue in `myst-theme`.
A clear way to reproduce helps even if you can't propose a fix.
:::

### Our accessibility goals

The [default MyST web themes](https://github.com/jupyter-book/myst-theme) aim to meet [WCAG 2.1 AA](https://www.w3.org/TR/WCAG21/), the level required of US public-sector and many private websites under [ADA Title II](https://www.ada.gov/resources/2024-03-08-web-rule/).

Accessibility bugs there are treated like any other bug.
See the [`a11y` issues label](https://github.com/jupyter-book/myst-theme/labels/a11y) for open accessibility issues.
Accessibility contributions follow the [normal contribution process](./contributing.md).


### How accessible is MyST today?

The MyST themes ship with these accessibility behaviors:

- Semantic HTML for articles, asides, figures, navigation, and captions.
- A skip-to-content shortcut and full keyboard navigation for menus, search, and the table of contents.
- Focusable, scrollable cell outputs so keyboard and screen-reader users can reach long stdout, stderr, and equation output.
- Color-contrast-aware defaults in the book and article themes, including code cells and error states.
- Pre-rendered math that ships as accessible HTML rather than images.
- Alt-text for images sourced from figure captions when present.
- `aria` labels and roles on interactive controls (theme toggle, document outline, search dialog, footnote return links).

In April 2026 we completed a focused round of work to [align with WCAG 2.1 AA](https://github.com/jupyter-book/mystmd/issues/2802). We know there is always ongoing work to be done to improve accessibility and welcome both guidance and contributions, see [](#a11y:contribute).

(a11y:monitor)=
### How we monitor accessibility

On every push to `main`, `myst-theme` runs an automated accessibility audit in CI.
It builds the current themes and runs [`berkeley-cdss/myst-a11y`](https://github.com/berkeley-cdss/myst-a11y) (which wraps [axe-core](https://github.com/dequelabs/axe-core)) against the [reference pages](https://myst-theme.netlify.app), checking WCAG 2.0 and 2.1 (A & AA).

Results are surfaced in a tracking issue with the [`a11y-audit` label](https://github.com/jupyter-book/myst-theme/labels/a11y-audit).
It summarizes the current issue counts broken down by rule (such as color-contrast, label, and image-alt) and by page.
If an issue with that label is already open, it will be updated on each new workflow run.
If there is no open issue, then a new one is created.

### Cell outputs are not under MyST's control

Many libraries emit interactive JavaScript or images as part of executing code (e.g., Plotly, ipywidgets, etc).
In these cases, MyST does not have control over the structure of what is created, and cannot guarantee their accessibility.
If you find a cell output that is not accessible, please report it in the repository for the tool that produced it.
The fix will most likely need to happen in that upstream tool rather than in the MyST theme.

(a11y:contribute)=
### Where can I follow along or contribute?

Open accessibility work is tracked under the [`a11y` label in `myst-theme`](https://github.com/jupyter-book/myst-theme/labels/a11y).
There's a thread for broader discussion and tracking in the [Accessibility Improvements tracking issue](https://github.com/jupyter-book/myst-theme/issues/238).

(a11y:check-your-site)=
### How can I check the accessibility of my own site?

A few tools that others in the community have found useful:

- The [Jupyter Accessibility Working Group](https://jupyter-accessibility.readthedocs.io) has a collection of accessibility resources for the broader Jupyter community.
- [berkeley-cdss/myst-a11y](https://github.com/berkeley-cdss/myst-a11y) is a GitHub Action built for MyST sites. It runs [axe-core](https://github.com/dequelabs/axe-core) checks against WCAG 2.0 and 2.1 (A and AA) on every push and reports results as a tracking issue. This is the same action MyST runs on its own themes, see [](#a11y:monitor). For a working example, see [data-8/textbook](https://github.com/data-8/textbook/blob/main/.github/workflows/a11y.yml).
- [Lighthouse](https://github.com/GoogleChrome/lighthouse) is built into Chrome DevTools and is useful for a quick audit of a single page.
- [JupyCheck](https://jupycheck.vercel.app/) checks accessibility of source notebooks in Jupyter interfaces. This is useful if you also want readers to launch Jupyter sessions from your MyST site.


## Performance

The [default MyST themes](https://github.com/jupyter-book/myst-theme) are built on [Remix](https://remix.run/) and [React](https://reactjs.org/). These provide link prefetching, smaller download sizes through modern bundlers, image optimization, and faster page transitions that update only the part of the page that changed.
We follow the [PRPL pattern](https://web.dev/apply-instant-loading-with-prpl/) where possible:

- **P**reload the most important resources.
- **R**ender the initial route as soon as possible.
- **P**re-cache remaining assets.
- **L**azy load other routes and non-critical assets.

Hover over a link in the navigation with your browser's developer tools open: the next page is fetched as soon as you hover, before you click. Only that page's content and metadata are downloaded, not a full HTML document, and shared assets like fonts and styles are reused across pages. Pages you've already visited are served from your browser's cache.

Locally, MyST rebuilds and rerenders in under 150ms and restores your scroll position, so you can preview changes without losing your place.

Performance of a deployed site depends on the infrastructure that serves it. See [deployment](./deployment.md) for options.

### Lighthouse

[Lighthouse](https://github.com/GoogleChrome/lighthouse) is a Chrome tool that measures performance, accessibility, and search-engine readiness. It flags asset, image, and crawler issues that affect both real-world load times and search rankings.

```{figure} ./images/lighthouse-2022_09_15.png
:label: lighthouse
A 2022 Lighthouse run on a deployed MyST site using Curvenote's global CDN.
```

```{warning}
Lighthouse scores depend on your network, machine, and the specific page measured; the figure above is a 2022 snapshot. If you find a place where MyST performance can be improved, please [open an issue](https://github.com/jupyter-book/mystmd/issues).
```

---

### Admonitions (`docs/admonitions.md`)

---
title: Callouts & Admonitions
description: Callout blocks or admonitions, like "notes" or "hints" are outlined or shaded areas of a document to bring attention to particular information.
thumbnail: ./thumbnails/admonitions.png
---

Callouts, or "admonitions", highlight a particular block of text that exists slightly apart from the narrative of your page, such as a note or a warning.


In MyST we call these kinds of directives {myst:directive}`admonitions <admonition>`, however, they are almost always used through their _named_ directives, like {myst:directive}`note` or {myst:directive}`danger`. There are ten kinds[^docutils-admonitions] of admonitions available by default, and others may be introduced by [plugins](./plugins.md):

```{list-table} Named admonitions that can be used as directives
:label: admonitions-list
* - 🔵 {myst:directive}`note`
  - 🟠 {myst:directive}`attention`
* - 🔵 {myst:directive}`important`
  - 🟠 {myst:directive}`caution`
* - 🟢 {myst:directive}`hint`
  - 🟠 {myst:directive}`warning`
* - 🟢 {myst:directive}`seealso`
  - 🔴 {myst:directive}`danger`
* - 🟢 {myst:directive}`tip`
  - 🔴 {myst:directive}`error`
```

[^docutils-admonitions]: These admonitions are the same as those used in [docutils](https://docutils.sourceforge.io/docs/ref/rst/directives.html#specific-admonitions) and Sphinx.

For example, try changing the following example of a `{tip}` admonition to a `{warning}`:

```{myst}
:::{tip}
Try changing `tip` to `warning`!
:::
```

See below for a demo of each admonition in the default theme.

`````{tab-set}

````{tab-item} Note
```{note}
This is an note admonition
```
````

````{tab-item} Important
```{important}
This is an important admonition
```
````

````{tab-item} Hint
```{hint}
This is an hint admonition
```
````

````{tab-item} See Also
```{seealso}
This is an seealso admonition
```
````

````{tab-item} Tip
```{tip}
This is an tip admonition
```
````

````{tab-item} Attention
```{attention}
This is an attention admonition
```
````

````{tab-item} Caution
```{caution}
This is an caution admonition
```
````

````{tab-item} Warning
```{warning}
This is an warning admonition
```
````

````{tab-item} Danger
```{danger}
This is an danger admonition
```
````

````{tab-item} Error
```{error}
This is an error admonition
```
````

`````

## Admonition Titles

All admonitions have a single argument ({myst:directive}`docs <admonition.arg>`), which is the admonition title and can use Markdown.
If a title argument is not supplied the first node of the {myst:directive}`admonition.body` is used if it is a `heading` or a paragraph with fully bold text; otherwise the name of the directive is used (e.g. `seealso` becomes `See Also`; `note` becomes `Note`).

```{myst}
:::{tip} Admonition _title_
Here is an admonition!
:::
```

(admonition-github-compatibility)=
:::::::{tip} Compatibility with GitHub
:class: dropdown
GitHub Markdown transforms blockquotes that start with a bold `Note` or text with `[!NOTE]` into a simple admonition (see [GitHub](https://github.com/community/community/discussions/16925)). This syntax only works for `note`, `important` or `warning`. MyST transforms these blockquotes into the appropriate admonitions with a `simple` {myst:directive}`admonition.class`.

```{myst}
> [!NOTE]
> Highlights information that users should take into account, even when skimming.

> [!IMPORTANT]
> Crucial information necessary for users to succeed.

> [!WARNING]
> Critical content demanding immediate user attention due to potential risks.

> **Note**
> This is a note

> **Warning**
> This is a warning
```

:::::::

::::{tip} Compatibility with Pandoc & Quarto
:class: dropdown
In Quarto/Pandoc Markdown admonitions are styled with special classes (like `{.callout-note}` or `{.callout-tip}`).
If you are using Jupyter Book V1 or Sphinx documentation, use an {myst:directive}`admonition` directive with the specific class, for example:

```{myst}
::: {.callout-tip}
## Tip with Caption
This is an example of a callout with a caption.
:::
```

::::

::::{warning} Compatibility with Sphinx
:class: dropdown
In Sphinx, all named admonitions (like `{note}` or `{tip}`), have **no arguments**.
If you place content on the first line it will instead be prepended to the admonition body.
If you are using Jupyter Book V1 or Sphinx documentation, use an {myst:directive}`admonition` directive with the specific class, for example:

```{myst}
:::{admonition} The Title
:class: hint
This is the body.
:::
```

::::

(admonition-dropdown)=

## Admonition Dropdown

To turn an admonition into a dropdown, add the `dropdown` {myst:directive}`admonition.class` to them.
Dropdown admonitions use the `<details>` HTML element (meaning they also will work without JavaScript!),
and they can be helpful when including text that shouldn't immediately visible to your readers.
To have a dropdown-style admonition start open, add the {myst:directive}`admonition.open` option.

```{myst}
:::{note} Click Me! 👈
:class: dropdown
👋 This could be a solution to a problem or contain other detailed explanations.
:::

:::{note} Hide Me! 👈
:class: dropdown
:open: true
👋 This is an admonition with a lot of text. The user can hide it if they want.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
:::
```

:::{seealso} You can also use a `{dropdown}`
:class: dropdown
You can also use a {myst:directive}`dropdown` directive, which provides a more compact writing experience and is simpler in the displayed style. See [](#dropdowns) for more information.
:::

## Simpler Admonitions

Admonitions can additionally be styled as `simple`, and can optionally hide the icon using the {myst:directive}`admonition.icon` option.

```{myst}
:::{important} Magic
:class: simple

This is a magic cat. It casts a luck spell on you that lasts an hour. \
**つ( ･ω･｡)つ━☆・*。**
:::
```

Removing the icon from an admonition allows using a custom emoji for style.

```{myst}
:::{danger} 🎤 Transcript. **Speaker:** John Smith
:icon: false
— To begin this lecture, I would like to ask the audience some questions.

...

— The next assignment has to be handed in by 01.05. Thanks everyone for attending.
:::
```

Multiple classes can be combined using, for example, [inline options](./inline-options.md):

```{myst}
:::{warning .simple .dropdown icon=false open=true} ✍️ NB
The proof of the lemma for $x \leqslant 0$ is left to the reader.
:::
```

---

### Analytics (`docs/analytics.md`)

---
title: Adding Analytics to your MyST Website
short_title: Analytics
description: Add Google Analytics or Plausible to your MyST website with a site configuration key.
thumbnail: ./thumbnails/analytics.png
---

By default, MyST sites contain no tracking cookies or analytics. 
However, we offer support for two analytics tracking systems:

1. [Google Analytics](https://marketingplatform.google.com/about/analytics/); and
2. [Plausible](https://plausible.io/), which is privacy-friendly alternative to Google.

These are set using template specific options in your site configuration using either an `analytics_google` or an `analytics_plausible` key.
See [](#site-options) for more on site options and how to set them.

## Google Analytics

Use the `site.options.analytics_google` configuration, with the contents being your **Measurement ID** (G-XXXXXX) or **Tracking ID** (UA-XXXXXX).

```yaml
version: 1
site:
  options:
    analytics_google: UA-XXXXX # Measurement ID or Tracking ID
```



See [Google Analytics docs](https://developers.google.com/analytics/devguides/collection/gtagjs) for more information on how to find this Measurement ID.

## Plausible

Use the `site.options.analytics_plausible` configuration, with the contents being the **domain** you are tracking.

```yaml
version: 1
site:
  options:
    analytics_plausible: mystmd.org # Domain(s) to track
```



See [Plausible docs](https://plausible.io/docs/plausible-script) for more information on how to find the domain. Note, you only copy in the contents of: `data-domain="COPY_THIS"`, which can be a comma-separated list for multiple domains.

## Testing your integration

Run `myst start` and view the page source. The analytics section should be in the `<head>` section of the HTML, you should also start to see real-time tracking in your dashboard.

---

### Asides (`docs/asides.md`)

---
title: Asides, Margin Content, and Sidebars
short_title: Asides & Margins
description: Asides provide an easy way to represent content that is only indirectly related to the article's main content, such as in the sidebar or margin.
---

Asides provide an easy way to represent content that is only indirectly related to the article's main content.
Where supported, MyST will attempt to display an {myst:directive}`aside` _as close as possible to_—but separate from—the main article, such as in the side-margin.

```{aside} Margin Content
Here’s some margin content! It was created by using the {myst:directive}`margin` directive in a Markdown, we can include images:



or any other sort of content!
```

```markdown
:::{aside} Margin Content
Here’s some margin content! It was created by using the {myst:directive}`margin` directive in a Markdown, we can include images:



or any other sort of content!
:::
```

You can also refer to this directive using {myst:directive}`margin` or {myst:directive}`sidebar`, which will have slightly different classes applied in the future.

:::{warning} Experimental

Many of the features on this page are experimental and may change at any time.

These elements can conflict with the document outline when they are both competing for the margin space (see [#170](https://github.com/jupyter-book/myst-theme/issues/170)).

There is, as yet, no plugin available for transforming this directive into Typst.
:::

% Using bold here, until we fix #170

**Topics**

A topic is like a block quote with a title, or a self-contained section.
Use the "topic" directive to indicate a self-contained idea that is separate from the flow of the document.
Semantically, this is an `<aside>`.

```markdown
:::{topic} This is an optional topic title
This is a topic, with standalone ideas.
:::
```

:::{topic} This is an optional topic title
This is a topic, with standalone ideas.
:::

---

### Authorship (`docs/authorship.md`)

# Authorship and attribution

A MyST project can include metadata about the authors of each page, such as institutional affiliations, funding sources, etc.

## How to set author information

Author information is set in the [MyST frontmatter](./frontmatter.md).
You can set this either in **`myst.yml`** (in which case, they will apply to all documents in a MyST project), or in the **page frontmatter** (in which case they'll just apply to that page).

For example, the examples below show frontmatter for authors and [author affiliations](#affiliations) in frontmatter of an `article.md` file, and in `myst.yml`:

::::{tab-set}
:::{tab-item} article.md

```yaml
---
title: My Article
authors:
  - name: Marissa Myst
    affiliation: ubc
  - name: Miles Mysterson
    affiliations: ubc; stanford
---

My article text begins here...
```

:::
:::{tab-item} myst.yml

```yaml
affiliations:
  - id: ubc
    institution: University of British Columbia
    ror: https://ror.org/03rmrcq20
    isni: 0000 0001 2288 9830
    department: Department of Earth, Ocean and Atmospheric Sciences
    address: 2020 – 2207 Main Mall
    city: Vancouver
    region: British Columbia
    country: Canada
    postal_code: V6T 1Z4
    phone: 604 822 2449
  - id: stanford
    name: ...
```

:::
::::

See [the `authors` frontmatter reference](#frontmatter:authors) for a list of all authorship metadata fields you can use.

### Re-use author information across repositories and projects

By [extending MyST configuration files](#composing-myst-yml) you can store author information in one place and re-use it across many other locations.
This allows you to define a source of truth for authorship and affiliations, and reference it over time. For example:

In one file, you'd define all the author affiliations that are relevant to your project:

```{code-block} yaml
:filename: authors.yml
version: 1
project:
  contributors:
    - id: person_a
      name: First Last
      email: person_a@org_a.org
      orcid: XXXX-XXXX-XXXX-XXXX
      github: person_a
      affiliations:
        - id: org_a
        - id: org_b
    - id: person_b
      name: First Last
      email: person_b@org_b.com
      orcid: XXXX-XXXX-XXXX-XXXX
      github: person_b
      affiliations:
        - id: org_b
  affiliations:
    - id: org_a
      name: Organization A Incorporated
    - id: org_b
      name: Org B Inc.
```

And in each of your project `myst.yml` files, you can extend this authorship file like so to include all the information:

```{code-block} yaml
:filename: myst.yml
version: 1
extends:
  - ./authors.yml  # Or, the URL of this file if not hosted locally
project:
  authors:
    - person_a
    - person_b
```

You could then also reference these authors in your page frontmatter like so:

```{code-block} markdown
:filename: mypage.md
---
authors:
- person_a
---

Page content...
```

(affiliations)=
## Affiliations

You can create an affiliation directly by adding it to an author.
It can be as simple as a single string.

```yaml
authors:
  - name: Marissa Myst
    affiliation: University of British Columbia
```

You can also add much more information to any affiliation, such as a ROR, ISNI, or an address.
A very complete affiliations list for an author at the University of British Columbia is:

```yaml
authors:
  - name: Marissa Myst
    affiliations:
      - id: ubc
        institution: University of British Columbia
        ror: https://ror.org/03rmrcq20
        isni: 0000 0001 2288 9830
        department: Department of Earth, Ocean and Atmospheric Sciences
        address: 2020 – 2207 Main Mall
        city: Vancouver
        region: British Columbia
        country: Canada
        postal_code: V6T 1Z4
        phone: 604 822 2449
        bluesky: '@eoas.ubc.ca'
  - name: Miles Mysterson
    affiliation: ubc
```

Notice how you can use an `id` to avoid writing this out for every coauthor.
Additionally, if the affiliation is a single string and contains a semi-colon `;` it will be treated as a list.

If you use a string that is not recognized as an already defined affiliation in the project or article frontmatter, an affiliation will be created automatically and normalized so that it can be referenced:

::::{tab-set}
:::{tab-item} Written Frontmatter

```yaml
authors:
  - name: Marissa Myst
    affiliations:
      - id: ubc
        institution: University of British Columbia
        ror: 03rmrcq20
        department: Earth, Ocean and Atmospheric Sciences
      - ACME Inc
  - name: Miles Mysterson
    affiliation: ubc
```

:::
:::{tab-item} Normalized

```yaml
authors:
  - name: Marissa Myst
    affiliations: ['ubc', 'ACME Inc']
  - name: Miles Mysterson
    affiliations: ['ubc']
affiliations:
  - id: ubc
    institution: University of British Columbia
    ror: https://ror.org/03rmrcq20
    department: Earth, Ocean and Atmospheric Sciences
  - id: ACME Inc
    name: ACME Inc
```

:::
::::

See [the frontmatter affiliations table](#table-frontmatter-affiliations) for a complete list of the affiliations metadata you can use.

(author:email)=
## Display author emails

An author's `email` is only shown if `corresponding: true` is also set.
If `corresponding` is unset, the first author in the list who has an email is chosen as the corresponding author.
To display the email icon for multiple authors, add `corresponding: true` to each one:

```yaml
authors:
  - name: Marissa Myst
    email: marissa@example.com
    corresponding: true
  - name: Miles Mysterson
    email: miles@example.com
    corresponding: true
```

## Add social media links

You can add social media links to authors and affiliations.
To do so, use the following fields in an entry for either `author` or the `affiliation`:



(credit-roles)=
## CRediT Contributor Roles

The [CRediT (Contributor Roles Taxonomy)](https://credit.niso.org/) is a standardized way to represent the contributions of each author to a scholarly work.
It defines 14 roles that describe common types of contributions, such as writing, data curation, and software development.

When you add roles to your authors, they are validated against the CRediT standard and included in the AST of your built projrect.

:::{warning} MyST will remove Credit roles that are not part of the standard
Similar to other unrecognized metadata, if MyST does does not recognize a role, it won't include it in the final AST and will issue a warning.
:::

### Example usage

You can define roles either at a project level or in [page frontmatter](./frontmatter.md).
It is particularly useful to use the [`extends:` key](#composing-myst-yml) for splitting author information into a [separate configuration file](#re-use-author-information-across-repositories-and-projects).

Below is an example of two authors that covers all 14 CRediT roles:

```yaml
authors:
  - name: Marissa Myst
    orcid: 0000-0000-0000-0001
    roles:
      - Conceptualization
      - Methodology
      - Software
      - Writing – original draft
      - Supervision
      - Project administration
      - Funding acquisition
  - name: Miles Mysterson
    orcid: 0000-0000-0000-0002
    roles:
      - Data curation
      - Formal analysis
      - Investigation
      - Resources
      - Validation
      - Visualization
      - Writing – review & editing
```

(other-contributors)=
## Reviewers, Editors, Funding Recipients

Other contributors besides authors may be listed elsewhere in the frontmatter.
These include `reviewers`, `editors`, and [funding](#frontmatter:funding) award `investigators` and `recipients`.
For all of these fields, you may use a full [author object](#frontmatter:authors), or you may use the string `id` from an existing author object defined elsewhere in your frontmatter.

---

### Background (`docs/background.md`)

---
title: History and background
description: High-level discussion of the MyST Markdown ecosystem, history of mystmd, other implementations like Jupyter Book and Sphinx, and explains past decisions.
---

This page discusses high-level questions about the MyST Markdown ecosystem, history of `mystmd`, various ecosystem implementations, and explains a few decisions made in the project.[^overview]

[^overview]: The [MyST ecosystem overview](./overview.md) is another excellent high-level source of information.

## History of MyST Markdown and `mystmd`

MyST Markdown (Markedly Structured Text) is a markup language that builds on standard Markdown and is designed to create publication-quality documents, books, presentations, and websites written entirely in Markdown. The [ExecutableBooks] team received a grant from the [Sloan Foundation](https://sloan.org) to build, enhance, and promote a new path to document creation and publishing for next-generation scientific textbooks and lectures ([Grant #9231](https://sloan.org/grant-detail/9231)).

The initial use case driving the development and design of MyST Markdown has been [Jupyter Book], which allows you to create educational online textbooks and tutorials with Jupyter Notebooks and narrative content written in MyST. The extensions and design of MyST is inspired by the [Sphinx] and [reStructuredText](https://docutils.sourceforge.io/rst.html) (RST) ecosystems. Jupyter Book V1 is considered a [distribution of Sphinx](xref:jupyterbook#explain/sphinx), and builds on the Sphinx and [Docutils] Python packages.

MyST Markdown enables rich content generation and is a powerful textual format for scientific and technical communication with potential for broad adoption in modern publishing workflows. In 2022, the Executable Books team started work to document the specification behind the markup language, called [myst-spec](https://github.com/jupyter-book/myst-spec), this work has enabled other tools and implementations in the scientific ecosystem to build on MyST Markdown (e.g. [scientific authoring tools](https://curvenote.com/for/writing), and [documentation systems](https://blog.readthedocs.com/jupyter-book-read-the-docs/)).

## What is the MyST Document Engine and Myst Markdown?

The `mystmd`[^naming] document engine and its ecosystem of tools were developed as a collaboration between [Curvenote], [2i2c] and the [ExecutableBooks] team. In addition to building websites, `mystmd` can also help you create scientific PDFs, Microsoft Word documents, and presentations.

`mystmd` uses existing, modern web-frameworks in place of the [Sphinx] build system. These tools come out-of-the-box with prefetching for faster navigation, smaller network payloads through modern web-bundlers, image optimization, partial-page refresh through single-page application. Many of these features and performance improvements are difficult (if not impossible) to create inside of the [Sphinx] build system.

The JavaScript packages in the `mystmd` ecosystem also power web-native extensions, such as [JupyterLab-myst], which renders MyST markup directly in JupyterLab.

## How was the MyST Engine Developed?

The initial version was released by [Curvenote] as the [Curvenote CLI](https://curvenote.com/docs/cli) under the MIT license, and later transferred to the [ExecutableBooks] team. The goal of the project is to enable the same rich content and authoring experiences that Sphinx allows for software documentation, with a focus on web-first technologies (JavaScript), interactivity, accessibility, scientific references (e.g. DOIs and other PIDs), and professional PDF outputs.

In June 2024, Jupyter Book was incorporated as a Jupyter sub-project, standardizing on using and stewarding the MyST document engine (`mystmd`). [See #123](https://github.com/jupyter/enhancement-proposals/pull/123).

[^naming]: Originally `mystmd` was called `mystjs`, but was changed as we matured the command-line interfaces.

[2i2c]: https://2i2c.org/
[curvenote]: https://curvenote.com
[executablebooks]: https://executablebooks.org/
[jupyter]: https://jupyter.org
[jupyter book]: https://jupyterbook.org/
[jupyterlab-myst]: https://github.com/jupyter-book/jupyterlab-myst
[sphinx]: https://www.sphinx-doc.org/

---

### Blocks (`docs/blocks.md`)

---
title: Blocks and Comments
short_title: Blocks & Comments
description: Blocks provide structural division in a MyST document using `+++`. These correspond, for example, to separate cells in a Jupyter Notebook. To add a comment, start your line with `%`.
---

## Blocks

`Blocks` provide a structural division of MyST documents using `+++`.
There can be optional metadata associated with the block, such as "tags", "parts" or other identifiers.
This is used to attach attributes to chunks of content, or to break your page into cells for a Jupyter Notebook.

```{myst}
+++ {"cell": "one"}
cell 1
+++ {"meta": "data!"}
cell 2
```

```{tip}
To identify a [part of a document](./document-parts.md), like an abstract, use `+++ { "part": "abstract" }`, this will allow tools like the [](./creating-pdf-documents.md) to be created with the appropriate parts of information.
```

### Document parts

You can use blocks to split your document into parts.
See [](#parts:blocks) for more information.

### Page Breaks

You may use `block` metadata to insert page breaks into your PDF or docx export with `+++ { "page-break": true }`. This will have no impact on your MyST site build nor other static exports that disregard "pages" (e.g. JATS).

```{tip}
You may also use `"new-page"` instead of `"page-break"`. This distinction only matters for $\LaTeX$ where `\newpage` and `\pagebreak` will be used, respectively.
```

### Add classes to blocks

You may attach CSS classes to blocks in order to control their behavior.
The default MyST 

(div-and-span)=
### `div` and `span` elements

You can add `div` and `span` elements to serve a similar purpose.
Any classes and content that you add will be attached to the AST of your document.

For example, here's a div that uses [the HTML theme grid classes](https://jupyter-book.github.io/myst-theme/?path=/docs/components-grid-system--docs) to snap a div to the right:

```markdown
:::{div}
:class: col-gutter-right
I'm off to the right!
:::
```

:::{div}
:class: col-gutter-right
I'm off to the right!
:::

## Comments

You may add comments by putting the `%` character at the beginning of a line. This will prevent the line from being shown in the output document.

```{myst}
This next line won't render, but it is in the HTML and LaTeX!
% Markdown comment line
```

```{warning} Comments only work at the beginning of lines
Note that a `%` is only a comment if it is at the beginning of a line, which is different than, for example, $\LaTeX$ where percent signs have to be escaped.
```

````{note} Comments split paragraphs
:class: dropdown
Putting a comment between items will split any preceding elements. For example, a comment between two lines of text will be broken up into two paragraphs, resulting in a margin between them:

```{myst}
a line
% a comment
another line
```
````

---

### Citations (`docs/citations.md`)

---
title: Citations and Bibliography
short_title: Citations & Bibliography
description: Add academic citations to your documents easily, have hover-references and an automatically created bibliography.
thumbnail: ./thumbnails/citations.png
---

Citations automatically show up in your site, including a references section at the bottom of the page.
These citations are able to be clicked on to see more information, like the abstract.
There are two different ways to add citations to your documents:

1. Add a Markdown link to a [DOI](wiki:Digital_object_identifier); and
2. Add a BibTeX file, which can be exported from any reference manager, and adding a `cite` role to your content.

(doi-links)=

## Simple Referencing with a DOI Link

Link to any DOI in your Markdown files or Jupyter Notebooks by including a link to the DOI.
This will be transformed to a citation with a pop-up panel on hover like this: [Cockett, 2022](https://doi.org/10.5281/zenodo.6476040), and the reference information will be added to the reference section at the bottom of the page. Here's some example syntax:

```md
This is a link in Markdown: [Cockett, 2022](https://doi.org/10.5281/zenodo.6476040).
```

To automatically insert the citation text, provide a standalone DOI link without link text:

- `[](doi:10.5281/zenodo.6476040)`
- `<doi:10.5281/zenodo.6476040>`

For example: <https://doi.org/10.5281/zenodo.6476040>.

If the BibTeX file in your project has this DOI, that citation will be used.

If the BibTex file does not have this DOI, the citation data will be downloaded from `https://doi.org` (and cached to a local file in the `_build` directory).

**Clear the DOI cache** with : `myst clean --cache`.

**To modify the style of the inserted citation text**: Use the styles in {ref}`table-pandoc-citations` (this works with or without a BibTeX file)

:::{warning} Many citations will slow down your build
If you have many citations that aren't present in a local BibTeX file, it may slow down the build process as the citation information is fetched dynamically.
:::

:::{note} Dealing with complex DOIs
:class: dropdown
If your DOI does not follow modern standards (e.g. strange characters or contains multiple `/`s), you must include the `https://doi.org` in the URL and may have to URL encode the DOI string to be recognized as a URL in Markdown.

For the DOI, `10.1175/1520-0493(1972)100<0081:OTAOSH>2.3.CO;2` there are `<`, `;` and `()` characters that do not work well with Markdown URL parsing. There are two options:

1. use the service https://shortdoi.org, which will give you a unique, persistent smaller DOI that will parse correctly, in this case `https://doi.org/cr3qwn` (which becomes https://doi.org/cr3qwn); or
2. URL encode this to: \
   `https://doi.org/10.1175%2F1520-0493%281972%29100%3C0081%3AOTAOSH%3E2.3.CO%3B2`, which also becomes https://doi.org/10.1175%2F1520-0493%281972%29100%3C0081%3AOTAOSH%3E2.3.CO%3B2[^brackets].

[^brackets]: In this case we can also optionally encode the brackets as `%28` and `%29`. There aren't too many of these in the wild, so hopefully it isn't too bad!!

For DOIs with multiple slashes in the identifier you also have to use the full https://doi.org URL, for example, `https://doi.org/10.3847/1538-4365/ac5f56` becomes <https://doi.org/10.3847/1538-4365/ac5f56>.

:::

### Numbered Citations

The default citations are narrative, for numbered citations, these can be set in the `site.options.numbered_references` in your `myst.yml` (See [](#site-options)).

```{code} yaml
:filename: myst.yml
site:
  options:
    numbered_references: true
```



### Writing DOIs to BibTeX

If you encounter problems fetching DOIs from `https://doi.org`, for example the downloaded citation does not include all the data you expect or requests to `https://doi.org` are failing on an automated continuous integration platform, you may write your DOI citations to file using the MyST command:

```bash
myst build --doi-bib
```

This will generate a BibTeX file `myst.doi.bib` which you may then rename, edit, and save to your project.
On subsequent builds, the DOIs will be loaded from this file rather than fetched remotely.

## Including BibTeX

A standard way of including references for $\LaTeX$ is using <wiki:BibTeX>, you can include a `*.bib` file or files in the same directory as your content directory for the project. These will provide the reference keys for that project.

If you want to explicitly reference which BibTeX files to use, as well as what order to resolve them in, you can use the `bibliography` field in your frontmatter, which is a string array of local or remote files.
This will load the files in order specified.

```yaml
bibliography:
  - my_references.bib
  - https://example.com/my/remote/bibtex.bib
```

The remote BibTeX can be helpful for working with reference managers that support remote links to your references.

## Markdown Citations

You can add citations to any BibTeX entry using the citation key preceded by an `@`, for example, `@author2023`.
This syntax follows the [pandoc citation syntax](https://pandoc.org/MANUAL.html#citation-syntax).
Multiple citations can be grouped together with square brackets, separated with semi-colons.
It is also possible to add a prefix or suffix to parenthetical citations, for example, `[e.g. @author2023, chap. 3; @author1995]`.
To add a suffix to a narrative citation, follow the citation with the suffix in square brackets, for example, `@author2023 [chap. 3]`.
As with a link to a DOI, you can also use the DOI directly instead of the BibTeX key.

```{list-table} Examples of Markdown citations
:header-rows: 1
:label: table-pandoc-citations
* - Markdown
  - Rendered
  - Explanation
* - `@cockett2015`
  - @cockett2015
  - Narrative citation
* - `[@cockett2015]`
  - [@cockett2015]
  - Parenthetical citation
* - `[@cockett2015; @heagy2017]`
  - [@cockett2015; @heagy2017]
  - Multiple parenthetical citations
* - `[-@cockett2015]`
  - [-@cockett2015]
  - Show citation year
* - `[e.g. @cockett2015, pg. 22]`
  - [e.g. @cockett2015, pg. 22]
  - Prefix and suffix
* - `@cockett2015 [pg. 22]`
  - @cockett2015 [pg. 22]
  - Suffix for narrative citations
* - `@10.1093/nar/22.22.4673`
  - @10.1093/nar/22.22.4673
  - Citation using a DOI directly
```

Citations that are embedded in links will _not_ be parsed as citations.
For example: [@jupyter-book](https://github.com/jupyter-book) or https://hackmd.io/@turingway/B1OnVLe-3.

:::{note} Mixing URLs and `@citations`
If you have a citation directly after a URL without whitespace, it may be treated as part of the URL rather than as a citation.

For example, `https://mystmd.org,@scipy2025` will treat `@scipy2025` as part of the URL. To cite after a URL, add a space (`See https://mystmd.org, @scipy2025`) or use angle brackets (`See <https://mystmd.org>,@scipy2025`).

**Avoid URLs with @ in square brackets**. A URL with `@` inside square brackets like `[https://hackmd.io/@user]` will be parsed as a citation, to avoid this you can escape the first bracket with a backslash `\[`.
:::

## Citation Roles

MyST also provides a number of roles for compatibility with Sphinx and Jupyter Book V1.
To create a citation role in Markdown, use either a parenthetical or textual citation:

```md
This is a parenthetical citation {cite:p}`cockett2015`.
You can also use a narrative citation with {cite:t}`cockett2015`.
You can also use a narrative citation with {cite:p}`cockett2015; heagy2017`.
You can also add prefix and suffix {cite:p}`{see}cockett2015{fig 1}`.
```

This is the difference between: {cite:p}`cockett2015` and {cite:t}`cockett2015`. You can have many citation keys in a single role, by separating them with a semicolon, `;`, for example: {cite:p}`cockett2015; heagy2017`.
Including a prefix or suffix is displayed as {cite:p}`{see}cockett2015{fig 1}`.

You can also include DOIs in citations (`cite`, `cite:t`, and `cite:p`) which will be linked in the same way as a simple Markdown link, but will match the reference style of the project.

```md
This will be a citation: {cite}`10.1093/nar/22.22.4673`.
```

This will show as: {cite}`10.1093/nar/22.22.4673`.

---

### Cite (`docs/cite.md`)

---
title: Cite MyST Markdown
description: The MyST Markdown CLI (mystmd) and related packages are developed by many contributors across academia and industry.
---

The MyST Markdown CLI (`mystmd`) and related packages developed in [`mystmd`](https://github.com/jupyter-book/mystmd) are developed by many contributors across academia and industry. To cite `mystmd` in publications, please use the following Zenodo reference:

[](https://doi.org/10.5281/zenodo.14805610)

The author list is created automatically by Zenodo based on GitHub contributions.

## Other Publications

There are additional publications that describe the design and vision for the project:

- Continuous Tools for Scientific Publishing: Using MyST Markdown and Curvenote to encourage continuous science practices (Scipy, 2024) [@10.25080/NKVC9349]

---

### Code (`docs/code.md`)

---
title: Code and Code-blocks
short_title: Code & Code-blocks
description: Code and code-blocks can be used to show programming languages.
thumbnail: ./thumbnails/code.png
numbering:
  code: true
---

```{warning}
The code blocks on this page are for **presentation** of code only, they are not executed.

For code execution, see the {myst:directive}`code-cell` directive in the execution section of the documentation.
```

You can include code in your documents using the standard markup syntax of ` ```language `,
where language is the programming language for highlighting.

````{myst}
```python
import matplotlib.pyplot as plt

plt.plot([1, 2, 3], [1, 2, 3], 'go-', label='line 1', linewidth=2)
```
````

```{note}
If the language is `ipython` or `IPython3`, etc., it will be dynamically converted to `python` to ensure that it is highlighted correctly!

A list of language names supported by the  `myst-react` package is here: [HLJS language identifier strings](https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/AVAILABLE_LANGUAGES_HLJS.MD)
```

## Code blocks

The above code is not a directive, it is just standard Markdown syntax, which cannot add a {myst:directive}`code.caption` or {myst:directive}`code.label`. To caption or label blocks of code use the {myst:directive}`code` directive.

````{myst}
```{code} python
:label: my-program
:caption: Creating a TensorMesh using SimPEG
from discretize import TensorMesh

hx = [(1, 40)]
hy = [(1, 40)]

mesh = TensorMesh([hx, hy])
```

In @my-program, we create a mesh for simulation using [SimPEG](https://discretize.simpeg.xyz/).
````

## Numbering and Highlighting

To add numbers and emphasis to lines use the {myst:directive}`code` directive. You can use {myst:directive}`code.linenos` which is a flag, with no value, and {myst:directive}`code.emphasize-lines` with a comma-separated list of line numbers to emphasize.
These options also work with {myst:directive}`code-cell` directives (see [](#code-cell:linenos)).

````{code} md
:linenos:
:emphasize-lines: 2,3
:caption: Emphasize lines inside of a `code` block.
```{code}
:linenos:
:emphasize-lines: 2,3
...
````

You can also set the start number using the {myst:directive}`code.lineno-start` directive, and all emphasized lines will be relative to that number.

```{tip} Docutils and Sphinx Compatibility
:class: dropdown

For full compatibility with Sphinx we suggest using {myst:directive}`code-block` directive, which is an alias of the {myst:directive}`code` directive. The MyST implementation supports both the Sphinx [`{code-block} directive`](https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-code-block) as well as the `docutils` [{code} directive](https://docutils.sourceforge.io/docs/ref/rst/directives.html#code) implementation, which only supports the `number-lines` option.

You can use either `code` or `code-block` directive documented above or even a normal Markdown code block.
All implementations in MyST are resolved to the same `code` type in the abstract syntax tree.
```

## Showing a Filename

Adding a {myst:directive}`code.filename` option will show the name of the file at the top of the code block. For example, `myst.yml` in the following example:

````{myst}
```{code} yaml
:filename: myst.yml
project:
  title: Showing Filenames in code-blocks
```
````

(docs:literalinclude)=

## Including Code Files

If your code is in a separate file you can use the {myst:directive}`literalinclude` directive (or the {myst:directive}`include` directive with the {myst:directive}`include.literal` flag).
This directive is helpful for showing code snippets without duplicating your content.
For parsing the file, see the documentation in [](#docs:include).
For example, a `literalinclude` of a snippet of the `myst.yml` such as:

````markdown
```{literalinclude} myst.yml
:start-at: project
:end-before: references
:lineno-match:
```
````

creates a snippet that has matching line numbers, and starts at a line including `"project"` and ends before the line including `"references"`.

```{literalinclude} myst.yml
:start-at: project
:end-before: references
:lineno-match:
```

:::{important} Paths are Relative
The {myst:directive}`argument <include.arg>` of a {myst:directive}`literalinclude` directive is the file path, which is relative to the file from which it was referenced.
:::

In {myst:directive}`include.literal` mode, the include directive also accepts all of the options from the `code-block` (e.g. {myst:directive}`include.linenos`).
To select a portion of the file to be shown using the {myst:directive}`include.start-at`/{myst:directive}`include.start-after` selectors with the {myst:directive}`include.end-before`/{myst:directive}`include.end-at`, which use a snippet of included text.

Alternatively, you can explicitly select the lines (e.g. `1,3,5-10,20-`) or the {myst:directive}`include.start-line`/{myst:directive}`include.end-line` (which is zero based for compatibility with Sphinx).
The include directive is based on [RST](https://docutils.sourceforge.io/docs/ref/rst/directives.html#including-an-external-document-fragment) and [Sphinx](https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-literalinclude).

---

### Commonmark (`docs/commonmark.md`)

---
title: CommonMark
description: MyST Markdown is a superset of CommonMark Markdown, and fully supports all of the markdown that you are used to. Here we describe all of the CommonMark features that are supported.
---

This page provides an overview of the types of block and inline markup features supported by CommonMark and MyST, with pointers to additional content of interest. For full details on all the nuance of these features, please look at the [CommonMark Spec documentation](https://spec.commonmark.org/).

MyST (Markedly Structured Text) was designed to make it easier to create publishable computational documents written with Markdown notation. It is a superset of [CommonMark Markdown](https://commonmark.org/) and draws heavy inspiration from <wiki:reStructuredText> and <wiki:pandoc>. In addition to CommonMark, MyST also implements and extends [unist](https://github.com/syntax-tree/unist) and [mdast](https://github.com/syntax-tree/mdast), which are standard abstract syntax trees for Markdown. `unist` is part of the [unifiedjs](https://unifiedjs.com) community and has [many utilities](https://unifiedjs.com/explore) for analyzing, exporting and transforming your content.

## Block Markup

### Headings

Markdown syntax denotes headers starting with between 1 to 6 `#` symbols.
For example, a level 3 header looks like:

```{myst}
### Heading Level 3

Try changing the number of `#`s to change the `depth`.
```

(setex-headings)=

### Setext Headings

An alternative syntax (called setext) is also supported for level 1 and 2 headers,
by underlining using multiple `===` or `---`. For example:

```{myst}
Heading 1
=========

Heading 2
---------
```

```{seealso}
Reference headings by preceding headers with a `(label)=`. See [](./cross-references.md)!
```

### Lists

Bullet points:

```{myst}
- headings
- lists
  - bullets
  - numbers
- code blocks
```

Numbered items:

```{myst}
1. quotes
2. breaks
3. links
```

### Code

Code blocks are enclosed in 3 or more `` ` `` or `~` with an optional language name.

````{myst}
```python
print('this is python')
```
````

Indented paragraphs are also treated as literal text. This may be used for code or other preformatted text.

```{myst}
Some JSON:

    {
      'literal': '*text*'
    }
```

```{seealso}
Create code-blocks with additional highlighting using the `code-block` directive. See more here!
```

% TODO: provide a link!
% TODO: myst: implement code-block

### Quotes

Quote blocks are prepended with `>`:

```{myst}
> Super profound quote
```

### Thematic Break

Create a horizontal line in the output

```{myst}
Section 1

---

Section 2
```

```{seealso}
Thematic breaks should not be confused with MyST [block syntax](./blocks.md),
which is used to structurally separate content.
```

### Link Definitions

Links may be defined outside of text with a reference target (no spaces) and an optional title.

```{myst}
[This is a link defined elsewhere!][key]

[key]: https://www.google.com 'a title'
```

```{seealso}
These can be used in [](#inline-links) and are similar to [](./cross-references.md) in MyST.
This syntax is also similar to [](#footnotes).
```

### Paragraph

Any text that does not belong to another block is simply a paragraph:

```{myst}
any _text_
```

### Valid HTML

Any valid HTML may also be included in a MyST document and rendered to HTML. However, you must set the option `allowDangerousHtml: true` in the MyST parser.
This option needs to be set internally in the parser, and is not exposed to the user as a command line flag or `myst.yml` setting.

## Inline Markup

(inline-links)=

### Inline links

Auto-link where link itself is shown in final output:

```{myst}
Search engine: <https://www.google.com>
```

Link with alternative text and optional title:

```{myst}
[search engine](https://www.google.com "Google")
```

```{seealso}
[](./cross-references.md) provides other ways to reference inline content.
```

(md:image)=

### Inline images

Link to an image can be done similar to other inline links, or you may use HTML syntax to include image size, etc.

```{myst}

```

```{seealso}
[](./figures.md) provides other ways to size, label, and caption images.
```

### Text formatting

Standard inline formatting including bold, italic, code, as well as escaped symbols and line breaks:

```{myst}
**strong**, _emphasis_, `literal text`, \*escaped symbols\*, a hard\
break
```

```{seealso}
[](./typography.md) provides other roles for subscript, superscript, abbreviations, and other text formatting.
```

---

### Configuration (`docs/configuration.md`)

---
title: Configuration and content frontmatter
short_title: Configuration and frontmatter
description: Frontmatter can be set at the top of your documents and in myst.yml to change the look and feel of your content.
thumbnail: thumbnails/frontmatter.png
---

Frontmatter allows you to specify metadata and options about how your project should behave or render.
Included in frontmatter are things like the document or project `title`, what `thumbnail` to use for site or content previews, `authors` that contributed to the work, and scientific identifiers like a `doi`.
Adding frontmatter ensures that these properties are available to downstream tools or build processes like building [](./creating-pdf-documents.md).

## Where to set frontmatter

Frontmatter can be set in two places:

1. The YAML header of a markdown (`md`) or notebook (`ipynb`) file (described as a "page" below)
2. In `myst.yml` file. This will be applied to all content in that project (apart from "page only" fields).

See [](#field-behavior) below about how these two sources of settings interact.

See also [](frontmatter.md) for a list of supported frontmatter settings.

See [](#site-options) for theme settings like analytics, logos, and navigation toggles, which are set under `site.options` in your `myst.yml`.

## Page-level frontmatter

### In a MyST markdown file

A frontmatter section can be added at the top of any `md` file using `---` delimiters.

```yaml
---
title: My First Article
date: 2022-05-11
authors:
  - name: Mason Moniker
    affiliations:
      - University of Europe
---
```

### In a Jupyter Notebook

Frontmatter can be added to the first cell of a Jupyter Notebook, that cell should be a Markdown cell and use `---` delimiters as above.

:::{important} Install JupyterLab Myst
To have properly formatted frontmatter, you can install the `jupyterlab-myst` plugin for Jupyter. See the [quickstart tutorial](./quickstart-jupyter-lab-myst.md).

Without the extension installed, remember to format the contents of the section as valid `yaml` even though when rendered, the cell will not look well formatted in your notebook.
:::

::::{note} Using `jupytext` or a Markdown-based notebook?

If your Jupyter Notebook is described as a markdown file (e.g. using [jupytext](https://jupytext.readthedocs.io/en/latest/formats-markdown.html), or [MyST](https://jupyterbook.org/en/stable/file-types/myst-notebooks.html)), then this should be included in the frontmatter section, as shown in the examples below.

:::{tip} a Jupytext (md:markdown) example
:class: dropdown

````{code}
:linenos:
:emphasize-lines: 15-16
---
jupyter:
  jupytext:
    text_representation:
      extension: .md
      format_name: markdown
  kernelspec:
    display_name: Python 3 (ipykernel)
    language: python
    name: python3
  language_info:
    name: python
    nbconvert_exporter: python
    pygments_lexer: ipython3
  short_title: images
  title: images and figures
---

You don't need a level-1 title,
it is defined in the frontmatter above already

```{code-cell} ipython3
import numpy as np
```
````
:::

:::{tip} a Jupytext (md:myst) example
:class: dropdown

````{code}
:linenos:
:emphasize-lines: 14-15
---
jupytext:
  text_representation:
    extension: .md
    format_name: myst
kernelspec:
  display_name: Python 3 (ipykernel)
  language: python
  name: python3
language_info:
  name: python
  nbconvert_exporter: python
  pygments_lexer: ipython3
title: images and figures
short_title: images
---

You don't need a level-1 title,
it is defined in the frontmatter above already

```{code-cell} ipython3
import numpy as np
```
````
:::

::::

## Project-level frontmatter

### In a `myst.yml` file

Frontmatter fields can be added directly to any `project:` section within a `myst.yml` file. These will be applied to all pages in your MyST project. Here's an example:

```yaml
version: 1
site: ...
project:
  license: CC-BY-4.0
  open_access: true
```

(field-behavior)=

## How project and page frontmatter interact

Frontmatter can be attached to a "page", meaning a local `.md` or `.ipynb` or a "project". However, some frontmatter fields are available across an entire project, while others are only available for a given page.

The behavior of each frontmatter field is hard-coded within MyST. These are the kinds of scope that a frontmatter field can have:

`page & project`
: the field is available on both the page & project but they are independent

`page only`
: the field is only available on pages, and not present on projects and it will be ignored if set there.

`page can override project`
: the field is available on both page & project but the value of the field on the page will override any set of the project. If the page field is omitted or undefined, the project value will be used. If the page field has a value of `null` (or `[]` in the case of multi-item fields like `authors`), the page will override the project value and clear the field for that page.

`project only`
: the field is only available on projects, and not present on pages and it will be ignored if set there.

+++

(multiple-projects-deprecated)=

:::{warning} Multiple projects in one `myst.yml` site has been deprecated
A MyST site maps one-to-one to a single project.

Historically, the `site.projects` list could combine several projects under one site, each mounted at its own URL slug. This is deprecated due to development complexity, and we encourage composing multiple MyST sites at a higher level (e.g. DNS, file system or through custom web-applications).
You can combine multiple projects by deploying multiple myst sites next to each other, for example, using GitHub pages or web-based routing. A worked example, which is used in the Jupyter Book documentation deployment can be [found here](https://jupyterbook.org/blog/posts/2026/multi-repo).
:::

(composing-myst-yml)=

## Compose and extend configuration `.yml` files

You may separate your frontmatter into multiple, composable files. This allows you to have a single source of truth for frontmatter to re-use across multiple projects, for example math macros or funding information.

To reference other files from your main `myst.yml` file, use the `extends` key with relative path(s) to the other configuration files:

```yaml
version: 1
site: ...
project: ...
extends:
  - ../macros.yml # A local file
  - https://raw.githubusercontent.com/myorg/myrepo/refs/heads/main/funding.yaml # A remote file
...other-config:
```

- Each entry listed inside `extends` may be a relative path to a file, or a URL.
- URLs must be direct links to files which are downloaded and cached locally.
- The files must contain valid `myst.yml` structure with `version: 1` and `site` or `project` keys.

**List-type fields are combined, not replaced**. This means, for example, you may define a single export in one file:

```{code-block} yaml
:filename: small.yml
version: 1
project:
  exports:
    - format: meca
```

and another format in your main `myst.yml` file:

```{code-block} yaml
:filename: myst.yml
version: 1
extends: ./small.yml
project:
  exports:
    - format: pdf
```

The final project configuration will include **both** a `meca` and a `pdf` export.

:::{note}
The fields `exports` and `downloads` are deduplicated by `id`, so if you wish to override a value from an inherited configuration you may assign it the same `id`. Other fields cannot be overridden; instead, shared configurations should be as granular and shareable as possible.
:::

### Avoid using relative paths in extended configuration

Using relative paths in the configuration you're extending can lead to unpredictable outcomes, especially if the file you're extending is in a different folder or remote location.
Try to keep your "extended" configuration self-contained rather than reliant on local files.
For example, a configuration like the following won't work, because the main `myst.yml` file does not have the same path to the `.css` file listed below:

❌ won't work:

```{code-block} yaml
:filename: config/small.yml
site:
  options:
    style: myfile.css
```

```{code-block} yaml
:filename: myst.yml
extends: config/small.yml
```

**Use remote URLs if you must point to files with "extended" configuration**.
This ensures that MyST can find and include the file regardless of where the `small.yml` file is.

✅ will work:

```{code-block} yaml
:filename: config/small.yml
site:
  options:
    style: https://github.com/jupyter-book/jupyterbook.org/raw/refs/heads/main/docs/_site/footer.md
```

:::{note} Use `raw` links to point to GitHub artifacts
If you wish to refer to a remote resource hosted on GitHub, make sure you use the "raw" GitHub link, not the link that you get when you click on that item in the GitHub UI.
For example:

This is the GitHub URL for a footer hosted on GitHub:

```
https://github.com/jupyter-book/jupyterbook.org/blob/main/docs/_site/footer.md
```

But this is the "raw link" that MyST can use:

```
https://github.com/jupyter-book/jupyterbook.org/raw/refs/heads/main/docs/_site/footer.md
```
:::

+++

---

### Contribute Add Feature (`docs/contribute-add-feature.md`)

---
title: Adding a New MyST Feature
short_title: Add a Feature
description: This tutorial walks through the process of adding a new word-count role {word-count} to MyST as a core feature, rather than a plugin.
---

:::{important} Objective

The goal of this tutorial is to walk through the process of adding a new word-count role to MyST, `{word-count}`, as a core feature. It is also possible to extend MyST by [writing a plugin](plugins.md), however, this tutorial covers the steps required to implement a feature that ships with MyST _out-of-the-box_. We will start from the very beginning of cloning the MyST repository, and finish with a working `word-count` role!

A full, unmerged pull request of this feature is available in [#1027](https://github.com/jupyter-book/mystmd/pull/1027) to see the end-result.

:::



## Cloning the Repository

The rest of this tutorial requires that you have basic knowledge of using Git and running commands in a terminal/shell (using one of the major operating systems). Although you can author a new MyST feature on any (supported) operating system, we will assume that you are using a typical Linux distribution for simplicity.

:::{tip} Unfamiliar with Git?
:class: dropdown

If you have not used Git before, the [Git book](https://git-scm.com/book/) is a _comprehensive_ guide to the tool. Whilst it is recommended to develop a good understanding of Git, if you're short on time, Roger Dudler's [Git Guide](https://rogerdudler.github.io/git-guide/), should cover enough to get you started.
:::

🛠 Clone [the `mystmd` repository](https://github.com/jupyter-book/mystmd)

```shell
$ git clone https://github.com/jupyter-book/mystmd
```

This will populate a new `mystmd` directory in the working directory with the current checkout (snapshot) of the MyST source code. This checkout may include new features that have yet to be released to the public, or new bugs that have yet to be identified!

🛠 Change to the `mystmd` directory

```shell
$ cd mystmd
```

From this point in the tutorial, terminal sessions will show the current working directory before the `$` prefix, excluding the path to the `mystmd` directory itself, for example:

```shell
$ echo MyST is cool!
MyST is cool!
$ cd packages
(packages)$ echo MyST is cool!
MyST is cool!
```

(defining-roles)=

## Defining a Role

The core specification for the MyST markup language is defined in [the MyST spec](https://mystmd.org/spec). Most features in MyST should, over time, be incorporated into this specification so that consumers of MyST documents (such as `myst-parser` from the Jupyter Book V1 software stack) agree on the manner in which the content should be parsed and rendered. The process of adding features to the MyST Spec is more formalized, and is described in the [MyST Enhancement Proposals](https://mep.mystmd.org). This tutorial does not cover updating the MyST Spec.

We should begin by asking the question "What is a role?" The spec [defines roles](https://mystmd.org/spec/overview#roles) as:

> similar to directives, but they are written entirely in one line.

One such role is the {myst:role}`underline` role, which can be used to format text:

```{myst}
The following text {underline}`is underlined`
```

We want to create a _new_ `word-count` role that injects the total word count into a document. It should accept a format-string that allows us to format the resulting text, i.e.

```markdown
This is a lengthy document ...

{word-count}`The number of words in this document is {number} words`
```

should become

```markdown
This is a lengthy document ...

The number of words in this document is 5 words
```

Many of the "core" roles in `mystmd` (including {myst:role}`underline`) are implemented in the [`myst-roles` package](https://github.com/jupyter-book/mystmd/tree/main/packages/myst-roles). Although a word-count role might not be considered a "core" feature, we will pretend it is for this tutorial. Let's start by looking at the existing {myst:role}`abbreviation` role in [`packages/myst-roles/src/abbreviation.ts`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-roles/src/abbreviation.ts)

:::{tip}
You can hover your mouse cursor over the link to [`packages/myst-roles/src/abbreviation.ts`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-roles/src/abbreviation.ts) to see the contents of the file. 🥳
:::

We can see that `abbreviationRole` is annotated with the type `RoleSpec`. This is the basic type of a role declaration defined by the MyST specification. There are a number of important fields, such as the `name`, `alias`, and `body`.

🛠 Add a new source file[^src] `word-count.ts` in the `myst-roles` package, and write the following.

[^src]: Source files are files that are added under the `src/` directory of a package, e.g. `packages/myst-roles/src/abbreviation.ts`

```{code-block} typescript
:filename: packages/myst-roles/src/word-count.ts

import type { RoleSpec, RoleData, GenericNode } from 'myst-common';

export const wordCountRole: RoleSpec = {
  name: 'word-count',
  body: {
    type: String,
    required: true,
  },
  run(data: RoleData): GenericNode[] {
    // TODO!
    return [];
  }
};
```

This defines a simple role called `word-count`, whose _body_ (the raw text between the backticks in `` {word-count}`<BODY>` ``) is a string.
:::{tip} Other kinds of `role` body types
:class: dropdown

It is also possible to write a role whose body is an AST, using `type: 'myst'`, e.g. [the `underline` role](https://github.com/jupyter-book/mystmd/blob/e07d55a0b32673ff9d557991ea1260c5f0bf835e/packages/myst-roles/src/underline.ts#L7). Declaring `body` as a MyST AST allows us to implement more complex markup, such as nesting roles-in-roles:

```{myst}
The following text {underline}`is underlined and also **bold!**`
```

For our role, however, we are keeping things simple!
:::

With an empty `run` function, this role doesn't do anything! In order to determine what should our `run` function _should_ do, we must understand how MyST documents are built. MyST generates a website or article from a MyST Markdown file in roughly three phases, shown in the diagram below.

:::{mermaid}

graph LR;
parse[Parse Markdown into AST]
transform[Transform AST into New ASTs]
export[Export AST to Website/Article]

parse --> transform --> export
:::

At the heart of MyST is the AST, defined by the [MyST Specification](https://spec.mystmd.org/), which serves as a structured representation of a document. Whilst directives, roles, and fragments of Markdown syntax are individually processed to build this AST, transforms are performed on the _entire_ tree, i.e. over the entire document. As computing the word-count requires access to the entire document, it is clear that all of the logic of our new feature will need to be implemented as a transform. Therefore, our role definition will be very simple - generating a simple AST node that our yet-unwritten transform can later replace.

🛠 Modify `word-count.ts`

```{code-block} typescript
:linenos:
:filename: packages/myst-roles/src/word-count.ts
:emphasize-lines: 10,11,12,13,14,15

import type { RoleSpec, RoleData, GenericNode } from 'myst-common';

export const wordCountRole: RoleSpec = {
  name: 'word-count',
  body: {
    type: String,
    required: true,
  },
  run(data: RoleData): GenericNode[] {
    return [
        {
          type: 'wordCount',
          value: data.body as string
        }
    ];
  }
};
```

Our new role is not-yet ready to be used. We next need to tell MyST that it should be included in the main program.

🛠 Import the role in `packages/myst-roles/src/index.ts`

```{code-block} typescript
:filename: packages/myst-roles/src/index.ts

import { wordCountRole } from './word-count.js';
```

Notice the `.js` extension instead of `.ts`; it is important, this is just [how typescript works](https://www.typescriptlang.org/docs/handbook/modules/reference.html#the-moduleresolution-compiler-option).

Next, we must instruct MyST to load our role when parsing a document.

🛠 Add `wordCountRole` to `defaultRoles`:

```{code-block} typescript
:filename: packages/myst-roles/src/index.ts
:linenos:
:emphasize-lines: 2

export const defaultRoles = [
  wordCountRole,
  abbreviationRole,
  chemRole,
  citeRole,
  ...
];
```

Finally, we should _export_ the role from `myst-roles`, so that other packages may use it (should they need to!).

🛠 Add an export statement from the `myst-roles` package

```{code-block} typescript
:filename: packages/myst-roles/src/index.ts

export { wordCountRole } from './word-count.js';
```

In order to try out our new `word-count` role, we need to build the `myst` application.

🛠 Install packages, build and link myst. See [](./contribute-build-locally.md) for more details.

```shell
$ bun install
$ bun run build
$ bun run link
```

After running these steps, the MyST CLI (as described in [](./quickstart-myst-documents.md)) can be used.

## Create a Demo

With our custom role now included in a development build of MyST, we can see it in action. First, we'll create a playground directory in which we can build a MyST project.

🛠 Create a new `demo` directory, outside of the `mystmd` source.

```shell
$ mkdir demo
$ cd demo
```

and add a new file `main.md` in which we will write the following:

```{code-block} markdown
:label: main-md
:filename: demo/main.md

# Demo

This document is not very long.
{word-count}`It is {number} words long`.
```

🛠 Initialize a simple MyST project with:

```shell
(demo)$ myst init
```

Once `myst init` has finished setting up the project, it will ask you whether to run `myst start`, we don't want to start the server now as we are going to create a single build.

🛠 Press {kbd}`n` to exit `myst init`[^or-kill-process]

[^or-kill-process]: If you have already started the server, use {kbd}`Ctrl`-{kbd}`C` to kill the process.

## Investigate the AST

Now we can run `myst build` in the `demo/` directory to run MyST.

🛠 Build the AST for the entire project

```shell
(demo)$ myst build
```

MyST outputs the final AST in the `_build/site/content` directory. Running `ls`, we can see

```shell
(demo)$ ls _build/site/content
main.json
```

The contents of `main.json` are the MyST AST. We can pretty-print the file with the `jq` utility

```shell
(demo)$ jq . _build/site/content/main.json
```

The new `wordCount` node generated by our `wordCount` role can clearly be seen:

```json
{
    ...
    {
      "type": "wordCount",
      "value": "{number} words long"
    },
    ...
}
```

## Writing a Transform

As discussed in [](#defining-roles), the logic of our word count feature needs to be implemented as a transform, so that we can view the entire document. Most transforms in MyST are defined in the [`myst-transforms` package](https://mystmd.org/myst-transforms), such as [the image alt text transform](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-transforms/src/images.ts) which generates an image [alt text](https://en.wikipedia.org/wiki/Alt_attribute) from figure captions. Our transform will need to visit every text-like node and perform a basic word-count.

Let's make a start. First, we need to implement a function that accepts a MyST AST `tree`, and modifies it in-place.

🛠 Create a `wordCountTransform` in a new file `packages/myst-transforms/src/word-count.ts`

```{code-block} typescript
:filename: packages/myst-transforms/src/word-count.ts

import type { GenericParent } from 'myst-common';


export function wordCountTransform(tree: GenericParent) {

}
```

The MyST AST is inspired by (and re-uses parts of) [the MDAST specification](https://github.com/syntax-tree/mdast) for a Markdown abstract syntax tree. MDAST, like MyST, implements [the unist specification](https://github.com/syntax-tree/unist), which has only three node types:

- [`Node`](https://github.com/syntax-tree/unist/blob/main/readme.md#node)
- [`Parent`](https://github.com/syntax-tree/unist/blob/main/readme.md#parent)
- [`Literal`](https://github.com/syntax-tree/unist/blob/main/readme.md#literal)

These nodes form the basic building blocks of any abstract syntax tree, and `unist` defines [some utility functions](https://unifiedjs.com/explore/topic/unist-util/) to manipulate trees composed of them.

Given that we want to count _meaningful_ words, we must look at the MyST specification to determine _which_ nodes we need to look at. As MyST AST is a unist AST, and only `Literal` unist nodes can hold values, we can start by only considering `Literal` MyST nodes. The MyST specification contains [a list of all node types](https://mystmd.org/spec/myst-schema), and it can be seen that there are only a few `Literal` types, such as [`Text`](https://mystmd.org/spec/myst-schema#text) or [`HTML`](https://mystmd.org/spec/myst-schema#html).

To begin with, let's count the words only in `Text` nodes. To do this, we'll need to pull out a list of all of the `Text` nodes from the AST. We can use the `unist-util-select` package to find all nodes with a particular [`type`](https://github.com/syntax-tree/unist/blob/main/readme.md#node).

🛠 Modify the transform to select all the `'text'` nodes

```{code-block} typescript
:filename: packages/myst-transforms/src/word-count.ts
:linenos:
:emphasize-lines: 1,6

import { selectAll } from 'unist-util-select';
import type { GenericParent, GenericNode } from 'myst-common';


export function wordCountTransform(tree: GenericParent) {
    const textNodes = selectAll('text', tree) as GenericNode[];
}
```

It's conventional to also define a "plugin" that makes it easy to include this transform in a suite of transformations.

🛠 Export a plugin to invoke the transform

```{code-block} typescript
:linenos:
:emphasize-lines: 1,10,11,12,13

import type { Plugin } from 'unified';
import { selectAll } from 'unist-util-select';
import type { GenericParent, GenericNode } from 'myst-common';


export function wordCountTransform(tree: GenericParent) {
    const textNodes = selectAll('text', tree) as GenericNode[];
}

export const wordCountPlugin: Plugin<[], GenericParent, GenericParent> =
  () => (tree) => {
    wordCountTransform(tree);
  };
```

Now that we have the text nodes, let's split them by whitespace, and count the total of words.

🛠 Implement the logic to count the words

```{code-block} typescript
:filename: packages/myst-transforms/src/word-count.ts
:linenos:
:emphasize-lines: 8,9,10,11,12,13,14,15,16,17,18,19

import type { Plugin } from 'unified';
import { selectAll } from 'unist-util-select';
import type { GenericParent, GenericNode } from 'myst-common';


export function wordCountTransform(tree: GenericParent) {
  const textNodes = selectAll('text', tree) as GenericNode[];
  const numWords = textNodes
    // Split by space
    .map(node => (node.value as string).split(" "))
    // Filter punctuation-only words
    .map(words => words.filter(word => word.match(/[^.,:!?]/)))
    // Count words in each `Text` node
    .map(words => words.length)
    // Sum together the counts
    .reduce(
      (total, value) => total + value,
      0
    );
}

export const wordCountPlugin: Plugin<[], GenericParent, GenericParent> =
  () => (tree) => {
    wordCountTransform(tree);
  };
```

Having computed the total number of words, let's replace our `word-count` nodes with text formatted with this value. In the same way that we selected all `Text` nodes

🛠 Select all nodes with a 'type' of `wordCount`

```{code-block} typescript
:filename: packages/myst-transforms/src/word-count.ts
:linenos:
:emphasize-lines: 21

import type { Plugin } from 'unified';
import { selectAll } from 'unist-util-select';
import type { GenericParent, GenericNode } from 'myst-common';


export function wordCountTransform(tree: GenericParent) {
  const textNodes = selectAll('text', tree) as GenericNode[];
  const numWords = textNodes
    // Split by space
    .map(node => (node.value as string).split(" "))
    // Filter punctuation-only words
    .map(words => words.filter(word => word.match(/[^.,:!?]/)))
    // Count words in each `Text` node
    .map(words => words.length)
    // Sum together the counts
    .reduce(
      (total, value) => total + value,
      0
    );

  const countNodes = selectAll('wordCount', tree) as GenericParent[];
}

export const wordCountPlugin: Plugin<[], GenericParent, GenericParent> =
  () => (tree) => {
    wordCountTransform(tree);
  };

```

Now we can use the `value` attribute of each `wordCount` node to transform this into a known node type of a `text` node.

🛠 Change the node to `text` and replace `{number}` with the word count

```{code-block} typescript
:filename: packages/myst-transforms/src/word-count.ts
:linenos:
:emphasize-lines: 22,23,24,25,26,27

import type { Plugin } from 'unified';
import { selectAll } from 'unist-util-select';
import type { GenericParent, GenericNode } from 'myst-common';


export function wordCountTransform(tree: GenericParent) {
  const textNodes = selectAll('text', tree) as GenericNode[];
  const numWords = textNodes
    // Split by space
    .map(node => (node.value as string).split(" "))
    // Filter punctuation-only words
    .map(words => words.filter(word => word.match(/[^.,:!?]/)))
    // Count words in each `Text` node
    .map(words => words.length)
    // Sum together the counts
    .reduce(
      (total, value) => total + value,
      0
    );

  const countNodes = selectAll('wordCount', tree) as GenericParent[];
  countNodes.forEach(node => {
    // Change the node type to text
    node.type = 'text';
    // Replace the number with the word count
    node.value = (node.value as string).replace('{number}', `${numWords}`);
  });
}

export const wordCountPlugin: Plugin<[], GenericParent, GenericParent> =
  () => (tree) => {
    wordCountTransform(tree);
  };

```

This pattern, of mutating existing nodes using a transform, is commonly used in the MyST ecosystem. If you want to keep information about the node's source, for example, to style it differently, you could store a flag on `data` or `kind`. If you are introducing a new node into the final rendered document, that will require you to add a new renderer. By staying within the existing node types, all existing renderers will work out of the box.

If we build MyST with `bun run build`, we'd notice that this transform never runs. Like our earlier `word-count` role, we need to include the `wordCountTransform` in the set of MyST transforms that run during building.

🛠 Add a new _export_ line in `packages/myst-transforms/src/index.ts`

```{code-block} typescript
:filename: packages/myst-transforms/src/index.ts
export { wordCountTransform, wordCountPlugin } from './word-count.js';
```

Then we must use this transform in the `myst-cli` package, which contains much of the `myst build` logic.

🛠 Import the `wordCountPlugin` in `packages/myst-cli/src/process/mdast.ts`

```{code-block} typescript
:filename: packages/myst-cli/src/process/mdast.ts
:linenos:
:emphasize-lines: 3

import {
  ...,
  wordCountPlugin,
} from 'myst-transforms';
```

Finally, we'll _use_ this plugin as part of the MyST transformations in the same file

🛠 Add the `wordCountPlugin` to the unified pipe of transformations

```{code-block} typescript
:filename: packages/myst-cli/src/process/mdast.ts
:linenos:
:emphasize-lines: 5

export async function transformMdast(...) {
  ...
  const pipe = unified()
    .use(...)
    .use(wordCountPlugin);
}
```

Having modified all of the source files required to implement our word count feature.

🛠 Run `bun run build` to build the `myst` package

Now let's see what happens over in our demo!

🛠 In your demo directory, run `myst start`

```shell
(demo)$ myst start
```

This will result in the following page with the word count that excludes its own text!

:::{figure} images/word-count-initial-result.png
:class: framed
:align: left

The result of running `myst start` with support for our new `word-count` role in [our document](#main-md).
:::

## Contributing

The next steps to bring this into being a core feature would be [adding documentation](./contribute-docs.md) and running `bun run changeset` to add a description of what you have completed. You can then open a pull request, and the developers of MyST will aim to get this into MyST and released so everyone can use it!

A full, unmerged pull request of this feature is available in [#1027](https://github.com/jupyter-book/mystmd/pull/1027) to see the end-result.

Thanks for your contributions! 🥳

---

### Contribute Build Locally (`docs/contribute-build-locally.md`)

---
title: Installing & Building MyST Locally
short_title: Installing Locally
description: Install and build myst locally using Bun.
---

A description of getting started with development is [given in the README](https://github.com/jupyter-book/mystmd/blob/main/README.md#development); we will also outline the basic process here. MyST uses [Bun](https://bun.sh/) as its package manager and JavaScript runtime; you will need to [install Bun](https://bun.sh/docs/installation) before running the commands in this section.

First, use `bun` in the base directory to install the MyST dependencies:

```shell
$ bun install
```

After installing the dependencies, we can then build the MyST application

```shell
$ bun run build
```

The build process may take a minute, as it has to build every package when run for the first time. Subsequent calls to `bun run build` will be faster as they cache unchanged intermediate dependencies. Finally, we need to make the `myst` binary that was built available to our terminal:

```shell
$ bun run link
```

After running these steps, the MyST CLI (as described in [](./quickstart-myst-documents.md)) can be used.

---

### Contribute Docs (`docs/contribute-docs.md`)

---
title: Contribute to the MyST documentation
short_title: Write Documentation
---

The documentation of MyST is inspired by the [Diataxis Documentation Framework](https://diataxis.fr).

## Suggest an edit to our documentation directly from the browser

The easiest way to suggest an edit to any Jupyter Book / MyST site is by using the **Edit this page** button. If you see something you'd like to change on a page, click this button:

```{figure} ./images/contribute-docs-edit-button.png
:width: 75%
An example of the "edit this page" button in a MyST theme. Clicking this button will take you to the source page for this file in GitHub.
```

This will take you to the source file for that page on GitHub. Then press the "edit this page" button on GitHub, it looks like this:

```{figure} ./images/contribute-docs-edit-button-github.png
:width: 75%
An example of the "edit this page" button on GitHub. This will open an interactive window where you can edit the source text.
```

Alternatively, you can use the [**`github.dev` web-based editor**](https://docs.github.com/en/codespaces/the-githubdev-web-based-editor) to suggest more comprehensive edits to one or more pages. To do so, in the browser URL replace `github.com` with `github.dev`[^period].

[^period]: Alternatively, you can just press {kbd}`.` from any GitHub source file page, and it will open a VSCode editor in-browser to let you suggest edits.

## How to build the MyST guide documentation locally

The documentation in `docs/` uses its own MyST plugins (`docs/*.mjs`) that require an install and build of the packages, so previewing it requires the full local development setup rather than a globally installed `myst`.

To build the MyST guide documentation:

1. Clone this repository and build:

   ```
   git clone https://github.com/jupyter-book/mystmd
   cd mystmd
   bun install
   bun run build
   bun run link  # install this version of mystmd globally
   ```

2. Navigate to the docs folder:

   ```
   cd docs
   ```

3. Start a MyST server to preview the documentation:

   ```
   myst start
   ```

The `bun run docs` command is a shorthand for steps 2 and 3 (see [the developer guide](#local-docs-workflows)).

### Build with executable content

Some pages in the MyST documentation include executable code cells that demonstrate features. To build the documentation with execution enabled:

1. Install the Python requirements:

   ```
   pip install -r requirements.txt
   ```

2. Build with the `--execute` flag:

   ```
   myst start --execute
   ```

   Or for a static build:

   ```
   myst build --html --execute
   ```

This will execute all `{code-cell}` directives in the documentation and include their outputs in the built site.

(docs:update-mystmd.org)=
## How to update the live website at mystmd.org

When you change the content here or in most other MyST repositories, it will _not_ automatically update mystmd.org. We use [a custom MyST theme](#about:mystmd.org) that aggregates content from several MyST repositories into a single website. The content for the live website mystmd.org is hosted by Curvenote. To update the content of `mystmd.org`, [dispatch the action on `main`](https://github.com/jupyter-book/mystmd/actions/workflows/docs.yml).

:::{warning} Only update the live deployment if we know the theme still works!
If we've only changed content in a repository, then it is usually safe to deploy the change to the live site at mystmd.org. However, if MyST or one of its themes has been updated, first confirm that the [mystmd.org theme](#about:mystmd.org) has been updated to reflect these new changes.
:::

## How does the MyST guide content relate to the documentation at mystmd.org

The documentation in this repository serves the content that lives [at `mystmd.org/guide`](https://mystmd.org/guide).

The full content and theme for [`mystmd.org`](https://mystmd.org) is [hosted at `jupyter-book/mystmd.org`](https://github.com/jupyter-book/mystmd.org), which pulls in the content from this folder along with several other documentation sources into one place.

However, the documentation here can be built independently for previewing your changes.

See [](#about:mystmd.org) for more information about the mystmd.org deployment.

(about:mystmd.org)=

## About the `mystmd.org` documentation and theme infrastructure

The [MyST website at mystmd.org](https://mystmd.org) is a custom MyST theme designed by the community in order to aggregate documentation from many locations into one website.

- The **content** for mystmd.org is located across several repositories in the MyST ecosystem, and it is deployed via a Curvenote deployment that uses the latest version of our custom `mystmd.org` theme from Vercel.
- The **theme** for mystmd.org is in [a repository we manage](#mystmd-theme-location) and deployed via Vercel. (see below for details)

(mystmd-theme-location)=

### Where is the mystmd.org theme located?

The [jupyter-book/mystmd.org](https://github.com/jupyter-book/mystmd.org) repository has a custom MyST theme that is used to control the content and structure of the site at mystmd.org. It is a [Remix](https://remix.run/) website and is deployed on [Vercel](https://vercel.com/).

### How does the mystmd.org theme work?

The custom MyST theme at [jupyter-book/mystmd.org](https://github.com/jupyter-book/mystmd.org) is an example of generating a custom application/site using MyST components. It is **not** how most people build websites with MyST Markdown, but is a good "Advanced Use" example.

The MyST documentation uses a custom theme that inherits from a chain of base themes.
Here's a brief overview of where to look for things:

- The MyST documentation theme is a custom MyST theme defined in the [`jupyter-book/mystmd.org`](https://github.com/jupyter-book/mystmd.org) repository.
- It uses a modified version of [the MyST Book theme at `jupyter-book/myst-theme: /themes/book/`](https://github.com/jupyter-book/myst-theme/tree/main/themes/book).
- The `Book` and `Article` themes are both located in [the `jupyter-book/myst-theme` repository in the `/themes` directory](https://github.com/jupyter-book/myst-theme).
- Each is programmatically published to a repository in [the `myst-templates` GitHub organization](https://github.com/myst-templates) for easier and optimized public consumption.
  - [Book theme source](https://github.com/jupyter-book/myst-theme/tree/main/themes/book) -> [Book theme built version](https://github.com/myst-templates/book-theme)
  - [Article theme source](https://github.com/jupyter-book/myst-theme/tree/main/themes/article) -> [Article theme built version](https://github.com/myst-templates/article-theme)

The **content of mystmd.org** is pulled from a number of repositories across the `jupyter-book` organization.

For example, `mystmd.org/guide` is pulled from [`jupyter-book/mystmd: /docs/`](https://github.com/jupyter-book/mystmd/tree/main/docs), and [`mystmd.org/jtex`](https://mystmd.org/jtex) is pulled from [`jupyter-book/mystmd: /jtex/docs/`](https://github.com/jupyter-book/mystmd/tree/main/packages/jtex/docs). It also includes some custom applications like the Sandbox and MyST demo on the landing page.

### How do I deploy changes to the mystmd.org theme?

After updating the theme at `mystmd.org`, we must [deploy it to Vercel](#team-vercel-deployment) in order to make it available for use.
We use [a GitHub Action to deploy to our Vercel project](https://github.com/jupyter-book/mystmd.org/blob/main/.github/workflows/deploy.yml). This will update the theme infrastructure used to power `mystmd.org`.

To trigger that action, you can either:

1. **Trigger a workflow dispatch**. Go to [the Vercel action page](https://github.com/jupyter-book/mystmd.org/actions/workflows/deploy.yml). Click on _Run Workflow_ and it will run.
2. **Push a commit to `main`** (of [jupyter-book/mystmd.org](https://github.com/jupyter-book/mystmd.org)). Any new commit to the `main` branch will trigger this action.

(mystmd-org-update-packages)=

### How do I update the myst package versions used by the mystmd.org theme?

The `mystmd.org` theme explicitly imports myst packages and pins their versions in [`theme/package.json`](https://github.com/jupyter-book/mystmd.org/blob/main/theme/package.json). When we release new versions of these packages, the theme must be updated manually to pull them in.

To update the package versions:

1. Clone [jupyter-book/mystmd.org](https://github.com/jupyter-book/mystmd.org) locally.
2. Update the myst package versions in `theme/package.json`. Use the [VSCode Version Lens extension](https://marketplace.visualstudio.com/items?itemName=pflannery.vscode-versionlens) to show the latest available version inline for each dependency.
3. Run `npm install` to install the updated packages.
4. Run `npm run dev` to verify the site works with the new versions.
5. Commit and push to `main`. This triggers [the Vercel deploy action](https://github.com/jupyter-book/mystmd.org/actions/workflows/deploy.yml) automatically.

(team-vercel-deployment)=

### Where is the Vercel deployment that serves the mystmd.org theme?

Currently the theme is run on **Rowan's** personal Vercel project, the deployment is completed in the GitHub Actions and access to this is only needed if the GitHub Action does not deploy.

## How do I preview content changes in pull requests?

We use [the Netlify service](https://netlify.app) to generate deploy previews of the `mystmd` documentation for all pull requests.
These build only the `mystmd` guide (hosted at https://mystmd.org/guide), not the entire mystmd.org website.
They're just used for convenience and review purposes.

Configuration for our Netlify build exists in the [`netlify.toml` configuration file](https://docs.netlify.com/configure-builds/file-based-configuration/) in the root of the repository.

Any team members can have `Developer` access to our shared Netlify account, and Steering Council members can have `Owner` access.
If you'd like access, please ask a maintainer.

(jb-vs-md)=

## How to choose what to document in jupyterbook.org vs. mystmd.org?

:::{warning} We're still figuring this out!
This is a best-effort description of our approach to documentation, based on some conversations we had in https://github.com/jupyter-book/jupyter-book/issues/2239. We'll re-assess this as the documentation of each project evolves.
:::

Jupyter Book and the MyST Document Engine have heavily overlapping functionality, so it may be unclear whether something should be documented at mystmd.org or jupyterbook.org. That's OK and expected - here are some guidelines for where to document things:

- The MyST document engine will be a **power user tool**. It will be more flexible and modular, with an extensive plugin ecosystem. It will be agnostic to build output, and single- or multi-page documents.
  - MyST should have the complete reference documentation for the MyST engine, as well as longer explanatory content about the MyST ecosystem.
  - As functionality is moved into plugins, we similarly prioritize reference documentation and explanation in those spaces.
  - MyST should be a standalone tool and have enough information for a power user to use on its own.
- Jupyter Book will be a **tool for typical users** focused around multi-page documents and websites. It will be opinionated, focused around the "book themes", and be more accessible to a new user or someone unfamiliar with JavaScript workflows.
  - Jupyter Book should focus on **How-Tos** and **Tutorials** that are driven by use-cases in multi-page workflows (e.g., documentation, books, community websites, etc).
  - Focus on keeping documentation outcome-oriented, and link heavily to the MyST engine docs for more complete reference information and explanation.

## How to create and edit Excalidraw diagrams

We use [Excalidraw diagrams](https://excalidraw.com) throughout our documentation.
This is a lightweight way to create flow charts and diagrams.

(export-excalidraw)=

**To create a new Excalidraw diagram**, first create what you wish in Excalidraw. Then, take the following steps:

1. Click the **hamburger menu**, then **export image**.
2. Ensure that **embed scene** is checked. This will include Excalidraw metadata with the output for future editing.
3. Click the `SVG` button (or `PNG` if necessary). This will download a local file with the diagram.
4. Put that in the `images/` folder and link it from your content.

**To make edits to an Excalidraw diagram**, follow these steps:

1. Open [excalidraw.com](https://excalidraw.com).
2. Find the file that you want to edit.
3. Confirm that it is an SVG or PNG that was **created with Excalidraw**, and that had **embed scene** checked upon creation.
4. Drag-and-drop that file into the Excalidraw window. (or, click **hamburger menu** -> **open** and add your file that way).
5. Make your edits in Excalidraw.
6. Export the new diagram using the [steps described above](#export-excalidraw).
7. Replace the old file with the new one and commit it to `git`. If using an SVG, you can also just copy/paste the new SVG text and replace the old SVG text with it.

## How to enable Pull Request previews on Netlify

Netlify [Deploy Previews](https://docs.netlify.com/site-deploys/deploy-previews/) allow others to preview the documentation for a repository as part of the Pull Request workflow. This will add a Documentation Preview to the Status Checks of a pull request.
To enable it, do the following:

1. Enable Netlify builds for your repository.
2. Go to the `configuration -> notifications` section and look for **emails and webhooks**.
3. Go to **Deploy Notifications**, which lists the notifications that will post to each PR.
4. To add a new notification, click **Add Notification** -> **GitHub Commit Status**.
5. Ensure the following notifications are listed for **deploy state commit checks**:
   - Add deploy state commit checks when Deploy Preview starts
   - Add deploy state commit checks when Deploy Preview succeeds
   - Add deploy state commit checks when Deploy Preview fails

## How to modify and release a MyST theme

Below is a brief description for how modifications in a theme are released for public consumption.

1. **[dev facing]** we make a bunch of changes to the theme, probably changing things in `themes/book/*`, `themes/article/*` and `packages/*`
2. **[dev facing]** if there were changes in `packages/*` we release the `@myst-theme/*` packages (changesets based ci step)
3. **[dev facing]** we then run `make deploy-book` and `make deploy-article` which builds and bundles each theme, making commits to the https://github.com/myst-templates/book-theme and https://github.com/myst-templates/article-theme repos.
4. **[user facing]** at that point those latest bundle commits will be what is pulled by `mystmd` clients - people who already have those downloaded need to `myst clean --all` (as we don't yet auto bump based on version changes, see [#854](https://github.com/jupyter-book/mystmd/issues/854) for updates).

---

### Contribute Templates (`docs/contribute-templates.md`)

---
title: Contribute a LaTeX, Word or Typst Template
short_title: Create a Template
description: Create a MyST Template so others in the MyST community can make use of your work and potentially improve it. There is an API to list all templates, and when you contribute it, your template will show up in command line queries, like listing all `myst templates`.
---

The [MyST templates organization](https://github.com/myst-templates) curates a community collection of MyST Markdown compatible templates. These templates allow MyST to export markdown files as typeset, formatted documents using PDF, LaTeX, Word or Typst templates. These templates expose data-driven options for customization ensuring the final documents comply with author submission guidelines provided by a particular journal, conference organizer or university.

## Creating a Template

To create a template, you can [follow the guide](https://mystmd.org/jtex/create-a-latex-template), as well as see the video below. Note that these guides are currently written for LaTeX, but can be generalized for Word and Typst. Documentation updates welcome!

````{note} See the video tutorial 📺
:class: dropdown
```{iframe} https://www.youtube.com/embed/-oD6jlM23wY
:width: 100%
```
````

## Contributing a Template

MyST welcomes contributions of new templates, or improvements to any of our curated templates. To get started with LaTeX:

- 📝 [open an issue](https://github.com/myst-templates/templates/issues) - tell us about the template you'd like added. Provide a link to the template if it's online, or attach the files if you have them.
- 🏋🏽‍♀️ [create your own template](https://mystmd.org/jtex/create-a-latex-template) - Learn how to create your own template in a few easy steps!
- 🤝 [contribute a template](https://mystmd.org/jtex/contribute-a-template) - Even if it's partial or barely started we'll help test and get it over the line.

For more details on contributing, learning about the structure of templates specifically and how to build one. See the [Contributors Guide](https://mystmd.org/jtex/contribute-a-template), currently the documentation is written for creating a LaTeX templates but you can follows the same approach for any MyST Template or see [MyST templates organization](https://github.com/myst-templates) for a range of examples.

---

### Contributing (`docs/contributing.md`)

---
title: Contribution Guide
short_title: Contribution Guide
---

This page contains pointers and links to help you contribute to this project.

## Developer guide

Technical detail about project architecture and contributing code is given in the [developer guide](./developer.md)

## Our team compass

The [Jupyter Book Team Compass][compass] is a source of truth for our team structure and policy.
It also has a lot of information about how to contribute.

## Code of conduct

We expect all contributors to this project to [Code of Conduct][coc].

## AI policy

It is important for us that contributions are correct, that the author
understands their submission, and to prioritize human interactions in
GitHub communications.  With this in mind, please:

- Follow our [contribution workflow](#contributing:workflow) especially if you're using an LLM to generate code.
- Carefully review (with your own eyes) and test any LLM-generated code before submitting.
- Write PR descriptions by hand (fine to use some AI text below yours, if clearly delineated, or to use an LLM for a grammar check).
- Respond to questions in person (do not paste LLM feedback).
- Disclose the tool used. This is not punitive (some team members use LLMs too): it better informs the review process.

As a rule of thumb: the more effort and thoughtfulness you put into your contribution, the more likely maintainers are to review, discuss, and iterate.

## Where we work

We do most of our work in GitHub repositories in [the `jupyter-book/` GitHub organization](https://github.com/jupyter-book).

## What should I work on?

Our [roadmap](https://github.com/orgs/jupyter-book/projects/1/views/1) provides a big picture overview of project initiatives.
[Current priorities](https://github.com/orgs/jupyter-book/projects/1/views/7) track work items that we would like to complete soon.
You will see these divided into two lists: "Priority" items (important and urgent) and "Side Quest" items (important, not urgent).
If you are unsure what to work on, we recommend you pick an item from one of these two lists.
These items are most likely to get an enthusiastic response, and will likely be reviewed quickly.

## Where we communicate

- For chat and real-time conversations: [The MyST community Discord server](https://discord.mystmd.org).
- For discussions around work and development: Issues in the `mystmd` repositories.
- For general discussions and questions: [the `mystmd` community forum](https://github.com/jupyter-book/mystmd/discussions).

## Relevant GitHub repositories

The `mystmd` project covers a _subset_ of the [`jupyter-book/` GitHub organization](https://github.com/jupyter-book).
It focuses on the JavaScript-based MyST Markdown engine and ecosystem, as well as the markdown syntax that MyST uses.

Below is a list of relevant repositories and a brief description of each.

- [mystmd](https://github.com/jupyter-book/mystmd): The MyST document engine and functionality not related to specific renderers.
- [myst-theme](https://github.com/jupyter-book/myst-theme): The web components and themes that are used for either the book or article themes for MyST.
- [myst-spec](https://github.com/jupyter-book/myst-spec): Questions about the markdown syntax for MyST and standardization efforts for MyST functionality.
- [jupyterlab-myst](https://github.com/jupyter-book/jupyterlab-myst): Questions about the JupyterLab extension for MyST.
- [MyST Templates](https://github.com/myst-templates): Repositories that contain templates for rendering MyST documents into various outputs like LaTeX, JATS, Typst, and Docx.

> [!NOTE]
> There are many repositories with similar functionality in the `executablebooks/` organization. Many of these are based around the [Sphinx documentation ecosystem](https://www.sphinx-doc.org). For example, the [MyST-NB repository](https://github.com/executablebooks/myst-nb) is a Sphinx extension for Jupyter notebooks, and the [MyST Parser repository](https://github.com/executablebooks/myst-parser) is a MyST markdown parser for Sphinx.

(contributing:workflow)=
## Contribution workflow

Generally speaking, our contribution workflow looks something like this:

- **Conduct free-form conversation and brainstorming in our forum**. We have [a community forum](https://github.com/jupyter-book/mystmd/discussions) for general discussion that does not necessarily require a change to our code or documentation. If you have a specific enhancement or bug you would like to propose for resolution, see the next steps.
- **Search open issues to see if your idea is already discussed**. Use [a GitHub search in the `jupyter-book/` organization](https://github.com/search?q=org:jupyter-book%20&type=code) to see if you should add to an existing issue or create a new one. If you don't think an issue exists that covers your idea or bug, go ahead and open one.
- **Discuss and propose changes in issues**. Issues are a way for us to agree on a problem to solve, and align on a way to solve it. They should invite broad feedback and be as explicit as possible when making formal proposals.
- **Make a pull request to implement an idea**. We use Pull Requests to formally propose changes to our code or documentation. These generally point to an issue and ideally will close it.
- **Iterate on the pull request and merge**. Pull Requests should have discussion and feedback from at least one core team member, and ideally from many. Once the PR is ready to merge, a core team member may decide to do so. See [our decision-making guide for formal details][governance].

This describes the high-level process that is usually followed.
In practice, we recommend attempting a contribution to get a feel for how it works in practice.

## How our team is structured

Our [Team page][team] lists all of the teams in the `jupyter-book/` organization and their members.
In addition, [our Governance page][governance] describes the responsibilities and authority that team members have.

## How we make decisions

Our [governance page][governance] describes our formal decision-making processes.

[compass]: https://compass.jupyterbook.org
[coc]: https://compass.jupyterbook.org/code-of-conduct
[team]: https://compass.jupyterbook.org/team
[governance]: https://compass.jupyterbook.org/team
[decisions]: https://compass.jupyterbook.org/team

---

### Creating Citation Cff (`docs/creating-citation-cff.md`)

---
title: Exporting CITATION.cff
description: MyST can be used to generate a `CITATION.cff` file for your project, reducing duplication of citation information.
---

The [Citation File Format](https://github.com/citation-file-format/citation-file-format) is a human-readable format for declaring citation information, particularly for software and datasets. By adding a `CITATION.cff` file to your project, other researchers know exactly how your project should be cited. This makes authors' lives easier, improves citations to your project, and enables reproducibility by pointing readers directly to the software/data repository. The Citation File Format is supported by GitHub, Zenodo, and Zotero. 

In MyST, much of the citation information is already present in the `myst.yml` file. Rather than duplicating information between `myst.yml` and `CITATION.cff`, you may instead export `CITATION.cff` from MyST. This behaves like a standard [export](./documents-exports.md):

```yaml
version: 1
project:
  ...
  exports:
    - cff
```

There are fields in the Citation File Format that are not present in `myst.yml`. To include these, you may add them to your export. Available fields are [described in the `citation-file-format` repository](https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md). For example:

```yaml
version: 1
project:
  ...
  exports:
    - format: cff
      date-released: '2021-07-18'
      commit: b49bf7feb3913b15a29cdc8c246e75df4ed4def9
```

---

### Creating Jats Xml (`docs/creating-jats-xml.md`)

---
title: Working with JATS
description: MyST can be used to create JATS (Journal Article Tag Suite), a NISO standard that is widely used in scientific publishing.
---

In the context of open access scientific publishing, it is common[^openaccessjats] that the Version of Record (VoR) includes the full text of the article as well as figures and tables. Scientific metadata about an article is no longer just the abstract, authors, and references. This full text, structured data that is permissively licensed will open up many workflows for scientific research. The full text is most often stored in an XML format which can be used to create all other views of this content (PDF, HTML). The structure of this XML varies between publisher, with the most used open standard being JATS ([Journal Article Tag Suite](https://jats.nlm.nih.gov/)), a [NISO standard](https://www.niso.org/standards-committees/jats).

[^openaccessjats]: PubMedCentral has about 8.5 million full-text articles in JATS. There are currently 5.8 million works with full-text XML available through CrossRef, for example. See [CrossRef’s API](https://api.crossref.org/works?filter=full-text.type:application/xml,full-text.application:text-mining&facet=publisher-name:*&rows=0).

[JATS](https://jats.nlm.nih.gov) defines a set of XML elements and attributes designed to represent journal articles in a single standard XML format. A JATS document is a single XML file that includes an `article`, which has `front` matter (authors, affiliations, title, abstract, funding), the `body` of the article (all sections, text, references to figures/images, tables), and the `back` matter (appendix sections, data-availability statements, conflict statements, acknowledgments, and the reference list). There can also be a number of `sub-article`s (with their own stubbed, frontmatter) that can be used to store other documents in a project (reviews, responses, appendices, or even computational notebooks!).

MyST can be used to both download, read, create the full JATS XML, using our tool called `jats-xml` (see [install instructions](https://www.npmjs.com/package/jats-xml)). To download a JATS file, for example, you can use the command-line interface:

```bash
jats download https://elifesciences.org/articles/81952 article.jats
```

You can also summarize a JATS article, either locally or remotely using a DOI or some URLs.

```bash
jats summary https://elifesciences.org/articles/81952
```

```{figure} images/jats-output.png
Summarize the contents of the JATS, given a URL, DOI, or local file. This will list the various components, and can be read by MyST.
```

## JATS for Journal Archiving and Interchange

There are three different tag-sets for JATS, as a lot of the content that we are aiming to work with requires computational notebooks and multiple articles we have chosen to focus MyST on the Journal Archiving and Interchange (v1.3). There is a lot of overlap between the tag-sets, with the Journal Archiving and Interchange tag-set being the most permissive and allowing, for example, `sub-articles`. Try clicking the "JATS" button in the following demo.

```{myst}
---
numbering: | # This has to be a string for now, sillyness in the docutils clone
  heading_3: true
  enumerator: 5.3.%s
---

(jats-sec)=
### Looking at JATS

JATS body content is XML: **strong**, _emphasis_, with cross-references ([Sec. %s](#jats-sec)) as an `xref`.
```

The largest structural difference in body content is that the sections (`sec`) are nested, which are accomplished as specific transforms for this export target.

---

### Creating Pdf Documents (`docs/creating-pdf-documents.md`)

---
title: Create a PDF
description: Export to over 400 journal templates from a MyST Markdown file, which uses LaTeX and can create print-ready, multi-column, professional PDF documents.
---

MyST can create a PDF for print-ready scientific papers or books.
It does so by first _rendering_ your MyST document into [$\LaTeX$](#render-latex) or [Typst](#render-typst) and then using those engines to create a PDF.

Myst uses **templates** to allow you to control the look and feel of the final PDF output. The [MyST Templates organization](https://github.com/myst-templates) contains templates for rendering MyST documents into the structure of over 400 journals.

:::{seealso}
In addition to PDF, you can also render your documents as Beamer presentations or as [Microsoft Word](./creating-word-documents.md) to share with other collaborators.
:::

```{figure} ./images/pdf-exports.png
:label: fig-export-to-pdf
:width: 100%

Export to over 400 journal templates from a MyST Markdown file, which uses $\LaTeX$ and can create print-ready, multi-column, professional PDF documents.
```

(myst-documents-tutorial-card)=
:::{card} MyST Documents Quickstart Tutorial 📑
:link: ./quickstart-myst-documents.md
See the quickstart tutorial for getting started with exporting to Word documents, $\LaTeX$ and PDFs with various templates.
:::

## How to export to PDF

To create a new `pdf` export type for your MyST document, add an `exports` list to either your [document frontmatter](./frontmatter.md) or your `myst.yml` configuration file.

(export-frontmatter-pdf)=

```{code-block} yaml
:filename: article.md
---
title: My PDF
exports:
  - format: pdf
    template: arxiv_two_column
    output: exports/my-document.pdf
---
```

To build the exports, use the `myst build` command, which will work with your project structure if it exists and create a document in the output path that you specify.

```bash
myst build my-document.md --pdf
```

Based on the `output` field in the export list in the [frontmatter](#export-frontmatter-pdf), the PDF and a log file will be written to `exports/my-document.pdf` and any associated log files. If the output file is a folder, the document name will be used with a `.pdf` or `.tex` extension, as appropriate. Any necessary auxiliary files (e.g. for example `*.png` or `*.bib`) will be added to the base folder (`exports/` above).

(render-latex)=
## Rendering PDFs with $\LaTeX$

```{danger}
:class: dropdown
# PDF exports require $\LaTeX$ or Typst to be installed

The default PDF renderer uses $\LaTeX$ to create PDFs, which means that to work locally you will need to [](#install-latex). A warning will occur if MyST cannot find a $\LaTeX$ environment, as well as forcing the build process and reporting any errors.

As an alternative, for faster PDF builds, you may use [Typst](#rendering-pdfs-with-typst) instead.
```

The rendering process for scientific PDFs uses $\LaTeX$ and makes use of the [`jtex`](xref:jtex) templating library, to convert to $\LaTeX$ the `myst-to-tex` packages is used. The libraries work together for sharing information about [frontmatter](./frontmatter.md) (e.g. title, keywords, authors, and affiliations).

```{mermaid}
flowchart LR
  A[Jupyter Notebook] --> C
  B[MyST Markdown] --> C
  C(mystmd) --> D{AST}
  D --> E[jtex] --> G[LaTeX]
  D --> F[myst-to-tex] --> G
  G --> H[PDF]
```

To include the $\LaTeX$ source code as well as the included images, change the `format` to:

`tex`
: create a folder containing the $\LaTeX$ source code, referenced images, citation files, and any class files required by the template.

`tex+pdf`
: create a folder containing all the same outputs as `tex` as well as run the build process for the `pdf`.

`pdf`
: Run the above processes in a temporary folder, and only copy in the PDF export and any log files if there are problems.

(install-latex)=

### Install $\LaTeX$

See the official documentation for installation instructions for $\LaTeX$ at:

- <https://www.latex-project.org/get/>

Ensure that you download a full distribution with appropriate libraries installed.

% Probably a note in the future about running this remotely?

(rendering-pdfs-with-typst)=

### LaTeX export gotchas

By default, MyST-rendered PDFs will use the `\section` command as the top-level heading in LaTeX. This is standard for scientific papers and short reports. However, if you are writing a book or long document (e.g. with Jupyter Book), this may cause errors as LaTeX expects the `\chapter` or `\part` command to be top-level. MyST can accomodate for this difference by manually setting the `level` key to each file you wish to export, as per the table below:

| Level | Corresponding LaTeX command |
| ----- | --------------------------- |
| -1    | `\part`                     |
| 0     | `\chapter`                  |
| 1     | `\section`                  |
| 2     | `\subsection`               |
| 3     | `\subsubsection`            |

For instance, assuming you had the following directory structure:

```
.
├── chapter-one
│  ├── index.md
│  ├── section-one.md
│  └── section-two.md
├── chapter-two
│  ├── index.md
│  ├── section-one.md
│  └── section-two.md
├── index.md
└── myst.yml
```

And the following table of contents in your `myst.yml`:

```yml
toc:
  - file: index.md
  - file: chapter-one/index.md
    children:
      - file: chapter-one/section-one.md
      - file: chapter-one/section-two.md
  - file: chapter-two/index.md
    children:
      - file: chapter-two/section-one.md
      - file: chapter-two/section-two.md
# ... rest of your config
```

By default, MyST will assign `chapter-one/index.md` with the `\section` command in LaTeX, instead of the `\chapter` command. To be able to change this behavior, you will need to set the `level` key for every page, as follows:

```yml
exports:
  - format: pdf
    template: plain_latex_book
    output: my_book.pdf
    articles:
      - file: index.md
        level: 0
      - file: chapter-one/index.md
        level: 0
      - file: chapter-one/section-one.md
        level: 1
      - file: chapter-one/section-two.md
        level: 1
      - file: chapter-two/index.md
        level: 0
      - file: chapter-two/section-one.md
        level: 1
      - file: chapter-two/section-two.md
        level: 1
```

This will render the chapters using the `\chapter` command, ensuring it is consistent with LaTeX's book rendering.

## Rendering PDFs with Typst

[Typst](https://typst.app) is a markup-based typesetting language. It is **significantly faster and simpler than using $\LaTeX$** with results of equal or better quality.

(typst:install)=
### How to install Typst

Follow [the Typst installation instructions](https://github.com/typst/typst?tab=readme-ov-file#installation) for several options to install Typst.
We **strongly recommend using the latest releases of Typst**. If you get a confusing Typst error, a good first step is to upgrade your version of Typst.

:::{warning} Do not use `npm` to install Typst
The version of Typst on `npm` (or similar community-managed installation services) is often out-of-date, and we recommend [following the Typst instructions directly](https://github.com/typst/typst?tab=readme-ov-file#installation).
:::

### How to render PDFs with Typst

To render Typst PDFs locally, you must first [install Typst](#typst:install).

Then add Typst to your export targets. Add `format: typst` and select a Typst template. Below is an example that also defines the output PDF to generate:

```{code-block} yaml
:filename: article.md
---
title: My PDF
exports:
  - format: typst
    template: lapreprint-typst
    output: exports/my-document.pdf
---
```
Finally, build the PDF output with Typst using the following command:

```bash
myst build article.md --typst
```

You can use [document frontmatter](./frontmatter.md) to control various aspects of your Typst outputs.
The Typst templates use the [MyST templating library](xref:jtex) and support the same configuration as [$\LaTeX$](#render-latex).

## Choosing a Template

There are currently 422 journals supported[^journals] and it is straight forward to add new personal templates, or contribute them back to the community.

[^journals]: As of September 15, 2022.

    This is the total number of _journals_ that can be created from MyST, which is a higher number than the number of _templates_, as some templates support many different journal exports. As we add more templates we will probably switch this number to templates, which is closer to 15, but that doesn't sound as impressive out of the gate. 🚀

Templates exist for both $\LaTeX$ and Typst builds. To list all of the public templates, use the `myst templates` command:

```bash
myst templates list --pdf --tag two-column

> arXiv (Two Column)       arxiv_two_column
> Description: A two column arXiv compatible template
> Tags: paper, two-column, preprint, arxiv, bioarxiv, eartharxiv
>
> ...
```

Once you have found a template, you can list detailed information about the parts and options that the template exposes using:

```bash
myst templates list arxiv_two_column --tex

> ID: public/arxiv_two_column
> Version: 1.0.0
> Author: Brenhin Keller
> Description: A two column arXiv compatible template
> Tags: paper, two-column, preprint, arxiv, bioarxiv, eartharxiv
>
> Parts
> abstract (required) - Keep it short — abstracts longer than 1920 characters will not be accepted ...
>
> Options
> line_numbers (boolean) - Turn line numbers on in the PDF
```

There are two ways to provide information to a template, through `parts` and `options`.


## Template `parts`

The `parts` of a template are things like `abstract`, `acknowledgments` or `data_availability`, see [](./document-parts.md) for more information. These parts are usually written pieces of a document, but are placed specifically in a template. For example, an abstract usually has a place in templates, with a box or other typographic choices applied. These parts can be marked as `required`, and will raise error in the PDF export process, however, myst will always try to complete the build.

A `part` of a template can be defined using the [page frontmatter](#parts:frontmatter) or [metadata on a block](#parts:blocks). An example of using the frontmatter is:

```{code-block} yaml
:filename: article.md
---
abstract: |
  MyST (Markedly Structured Text) is designed to create publication-quality documents
  written entirely in Markdown. The markup and publishing build system is fantastic,
  MyST seamlessly exports to any PDF template, while collecting metadata to make your
  writing process as easy as possible.
---
```

### Template `options`

Template authors should choose to use [standard frontmatter](./frontmatter.md) properties where possible, however, all templates can also expose custom options through their [](xref:jtex#template-yml). Include options for the build in the exports list. For example, to turn on `line_numbers` in the template, add the option to the dictionary.

```{code-block} yaml
:linenos:
:emphasize-lines: 7
:filename: article.md
---
title: My PDF
exports:
  - format: pdf
    template: arxiv_two_column
    output: exports/my-document.pdf
    line_numbers: true
---
```

Any unrecognized, or malformed entries will be logged as errors as well as required options that are not provided.


### Use `extend` to set options
Using [`extend` configuration](#composing-myst-yml) you can create an `export.yml` file which is referred to in the `myst.yml` file. For example, this configuration tells `myst.yml` to look for an `export.yml` file for configuration:

```{code-block} yaml
:filename: myst.yml
---
extends:
  - export.yml
---
```

And the `export.yml` file defines the export configuration to use in the project:

```{code-block} yaml
:filename: export.yml
---
version: 1
project:

  downloads:
    - id: output-pdf1

  exports:
    - id: output-pdf1
      format: typst
      template: https://github.com/myst-templates/plain_typst_book
      output: book.pdf
      # additional options

      #### Cover picture
      cover: Cover.PNG
      #Coverposition:
      # coverwidth:

      #### Logo at top of position
      logo: logo.svg
      logo_width: 10
---      
```

## Creating a Template

The export list can also point to local templates, for $\LaTeX$ these are built using [`jtex`](/jtex), and you can learn more about how to create a template for: [any $\LaTeX$ document](/jtex/create-a-latex-template) and [Beamer presentations](/jtex/create-a-beamer-template).

To make use of the template locally, validate it using `jtex check` and then point to the template folder in your export:

```{code-block} yaml
:filename: article.md
:linenos:
:emphasize-lines: 5
:caption: The template can be a path to a `jtex` template, which contains a `template.yml` and `template.tex` as well as any other `cls` or `def` files.
---
title: My PDF
exports:
  - format: pdf
    template: ../templates/my-template
    output: exports/my-document.pdf
---
```

Please consider [contributing your template](/jtex/contribute-a-template) to the growing list of templates so that other people can benefit and improve your work!

## Excluding Content from Specific Exports

If you have a [block](./blocks.md) or notebook cell that you do not want to render to your $\LaTeX$ output, add the `no-tex` tag to the cell. Similarly, to exclude a cell from Typst, use `no-typst`. To exclude a cell from both formats, use `no-pdf`.

````markdown
+++{"no-pdf": true}
This will not be in the pdf
+++
````

## Including Content with Specific Exports

If you need to inject some $\LaTeX$- or Typst-specific content into their respective exports, you may use the `{raw:latex}` or `{raw:typst}` role and directive. For example, to insert a new page in Typst with two columns:

````markdown
```{raw:typst}
#set page(columns: 2, margin: (x: 1.5cm, y: 2cm),);
```
````

The content in these directives and roles will be included exactly as written in their respective exports, and will be ignored in all other contexts.

(multi-article-exports)=

## Multi-Article Exports

Sometimes you may want to combine multiple MyST documents into a single export, for example a thesis or a book. MyST makes this possible with multi-article exports for PDFs built with either $\LaTeX$ or Typst.

For perform a multi-article export, add multiple `articles` to the export frontmatter:

```{code-block} yaml
:filename: article.md
---
title: My PDF
exports:
  - format: pdf
    template: plain_latex_book
    output: exports/my-thesis.pdf
    articles:
      - introduction.md
      - project-one.md
      - project-two.md
      - conclusions.md
---
```

As an alternative to listing articles in MyST frontmatter, you may specify a table of contents using the [Jupyter Book V1 format](#toc-format):

```{code-block} yaml
:filename: article.md
---
title: My PDF
exports:
  - format: pdf
    template: plain_latex_book
    output: exports/my-thesis.pdf
    toc: thesis_toc.yml
---
```

By default if no `articles` are given, exports defined in page frontmatter will produce a single-article export from of that page, and exports defined in the `myst.yml` project configuration will produce a multi-article export based on the project structure.

## Custom Frontmatter for Exports

Export frontmatter may differ from page or project frontmatter. For example, you may with to give your export its own title, which does not match the project title. To do so, add the alternative frontmatter to your export:

```{code-block} yaml
:filename: article.md
---
title: My Interactive Research!
exports:
  - format: pdf
    title: My Static Research as a PDF
    output: exports/my-document.pdf
---
```

You may redefine [any frontmatter fields](./frontmatter.md). These redefined fields will replace the values found in page frontmatter and `myst.yml` project configuration.

Further, for [](#multi-article-exports), you may redefine frontmatter for every specific page. To do so, you must use a list of article objects (as opposed to a `_toc.yml` file or a list of article names):

```{code-block} yaml
:filename: article.md
---
title: My PDF
exports:
  - format: pdf
    title: My Thesis
    date: 10 May 2023
    template: plain_latex_book
    output: exports/my-thesis.pdf
    articles:
      - file: introduction.md
        title: Introduction to This Thesis
      - file: project-one.md
      - file: project-two.md
      - file: conclusions.md
        title: Summary of this Thesis
---
```

---

### Creating Word Documents (`docs/creating-word-documents.md`)

---
title: Microsoft Word
description: Export to Microsoft Word directly from MyST Markdown.
---

You can render your MyST documents as Microsoft Word documents.

```{figure} ./images/word-export.png
:label: fig-export-to-word
:width: 50%

Export to a Microsoft Word document to easily share with your colleagues.
```



## Exporting to Word

To create a new `docx` export type for your MyST document, in your document frontmatter, add an `exports` list:

(export-frontmatter-word)=

```yaml
---
title: My Document
exports:
  - format: docx
    output: exports/my-document.docx
---
```

To build the exports, use the `myst build` command, which will work with your project structure if it exists and create a document in the output path that you specify.

```bash
myst build my-document.md --docx
```

Based on the `output` field in the export list in the [frontmatter](#export-frontmatter-word), the PDF and a log file will be written to `exports/my-document.docx`.

````{warning}
:class: dropdown
# When opening, click **Yes** to "Accept Links"

The default export creates links for cross references and citations, and the first time this is opened Microsoft Word asks you if you would like to link these. **Click Yes**.

```{figure} ./images/export-word-link.png
:label: export-word-link
:width: 40%

Allow word to fix links for cross-references and citations.
```
````

## Math and Equations

Currently MyST export does not fully create math in Word's format, instead, $\LaTeX$ is used, which can easily be converted inside of Word.

1. Select any equation and open the equation toolbar
2. Click `LaTeX`
3. In the convert dropdown, select "All - Professional"
4. Click convert

```{figure} ./images/convert-word-equations.png
:label: convert-word-equations
:width: 100%

To fix equations in Word, use the equation toolbar to select `LaTeX` and from the dropdown select, all professional, then click convert.
```

## Rendering Word with `myst-to-docx`

The rendering process for word documents uses the `myst-to-docx` package. The library works together with `mystmd` for sharing information about [frontmatter](./frontmatter.md) (e.g. title, keywords, authors, and affiliations).

```{mermaid}
flowchart LR
  A[Jupyter Notebook] --> C
  B[MyST Markdown] --> C
  C(mystmd) --> D{AST}
  D --> E[myst-to-docx]
  E --> G[docx]
```

## Word Templates

We are looking for contributions in this area to improve Microsoft Word export, please reach out if you want to help!

---

### Cross References (`docs/cross-references.md`)

---
title: Cross-references
subtitle: Link to equations, figures, tables, and so much more!
description: Create numbered cross-references to labeled content (e.g. a figure, document, or table) and automatically generates links with hover previews.
thumbnail: ./thumbnails/cross-references.png
numbering:
  headings: true
---

% Based loosely on https://jupyterbook.org/content/references.html

References refer to labeled content (e.g. a figure, document or table) and automatically generates links and extra information, like numbering. This page covers the basics of setting up references to content and shows examples for sections, figures, tables and equations.

```{seealso}
See [](./external-references.md) to connect your <wiki:documents> to external [linked](wiki:Hyperlink) content like <wiki:Wikipedia>, or other MyST projects. These cross-references allow for [hover](wiki:Hovercraft)-references to external content.

See [](./citations.md) to cite scholarly work and create bibliographies.
```

## Reference syntax

There are several ways that you can define cross-references with MyST.
Below are the major ones.

(link-references)=

### Reference using Links

Cross-referencing content is accomplished with markdown link syntax (`[text](#target)`) where `#target` is the target label[^1], like the figure, equation or section header that you are referencing. If you leave the text empty, MyST will fill in the link with the title, caption, document name, or equation number as appropriate (e.g. "Figure 1" or "Section 1.3.7"). If you do supply text, you can control what is displayed in the reference, as well as have access to placing the name and enumerator of the target, using `{name}` and `{number}`, respectively[^2].

[^1]: Note that targets without the `#` will resolve, however, they throw a deprecation warning. By including the `#` there is a better chance of your content working in other markdown renderers like GitHub or VSCode.
[^2]: Note that not everything has a number or name (e.g. a paragraph usually isn't numbered, and an equation doesn't have text to resolve into `{name}`). An unnumbered node will resolve to `??`, and raise a warning if they are not defined. If no `{name}` is defined the node `label` will be used instead.

```
/* Detailed source-code truncated for AI context efficiency. */
```

[^no-toc]: To link to a page, that file must be included in the project's [table of contents](./table-of-contents.md). If it isn't, then the document will be presented as a static file.

% TODO: absolute links

### Reference using a shorthand `@` syntax

You can reference targets with a short-hand using the `@` symbol, like so:

```markdown
@target
```

This cuts down on the amount of markdown that is needed to create the reference.
For example, the following text:

```md
Other ways to reference are @link-references and the @ref-role role.
```

Results in:

> Other ways to reference are @link-references and the @ref-role role.

:::{note} This is a short-hand for several types of references
The `@` short-hand syntax for referencing maps on to many different types of [referencing roles](#reference:roles), depending on the target that you are referencing.

For example, if `@target` is a bibliography entry, it will map onto the {myst:role}`cite` role.
If it is an image or a section header, it will map on to the {myst:role}`ref` role.
:::

(reference:roles)=

### Reference using MyST roles

Roles are a more explicit way of defining references that provide more configuration at the cost of requiring more complexity to write.
There several roles that define various kinds of references in MyST.
In many cases, the short-hand syntax described above are aliases for these roles.
Below we describe the most commonly-used ones.

(ref-role)=

ref
: The {myst:role}`ref` role can be used to bring the title or caption directly in line, the role can take a single argument which is the label, for example, `` {ref}`reference-target` ``
: You can also choose the reference text directly (not taking from the title or caption) by using, `` {ref}`your text here <reference-target>` ``.

(numref-role)=

numref
: The {myst:role}`numref` role is exactly the same as the above {myst:role}`ref` role, but also allows you to use a `%s` in place of the number, which will get filled in when the content is rendered. For example, ``{numref}`Custom Table %s text <my-table-ref>`.`` will become `Custom Table 3 text`.

(eq-role)=

eq
: The `` {eq}`my-equation` `` syntax creates a numbered link to the equation, which is equivalent to `[](#my-equation)` as there is no text content to fill in a title or caption.

(doc-role)=

doc
: The `` {doc}`./my-file.md` `` syntax creates a link to the document, which is equivalent to `[](./my-file.md)`.

(download-role)=

download
: The `` {download}`./my-file.zip` `` syntax creates a download to a document, which is equivalent to `[](./my-file.zip)`.

:::{tip} When to use roles vs. short-hand

Short-hand syntax is provided for a quick and clean way to reference content with MyST if you are happy with default behavior.
However, some roles provide additional configurability that allow you to change their behavior.

Thus, a good rule of thumb is the following:

1. If you're happy with the default behavior of references, use `@target` syntax.
2. If you only wish to modify the displayed text, use `[My text](#target)` syntax.
3. If you wish to use more complex configurability, use the role syntax (`{ref}`, `{cite}`, etc).

:::

## Targets and labels for referencing

The content you wish to reference is called a **target**, and to be targeted that content must have a **label**.
For example, in this reference syntax:

```md
[](#my-targets-label)
```

The text `my-targets-label` is the label for the target.
There are many ways that you can label a target, and the sections below describe the most common approaches.

:::{note}
To be referenced, targets must have a `label`/`identifier` pair [in the AST](xref:spec#association).
:::

### Directive Targets

Labels can be given to most directives by setting the `label` option. For example, to label and reference a figure, use the following syntax:

````{myst}
```{figure} https://github.com/rowanc1/pics/blob/main/mountains.png?raw=true
:label: my-fig
:align: center

My **bold** mountain 🏔🚠.
```

Check out [](#my-fig)!!
````

```{tip} Using Markdown Links 🔗
You can use this syntax to also reference [Section/Header targets](#targeting-headers) as well as [label equations](#referencing-equations) when using [dollar math](#dollar-math) or [AMS math](#ams-environments).
```

Or, to label an equation:

(example-equation-targets)=

````{myst}
```{math}
:label: my-math-label
e=mc^2
```

See [](#my-math-label) for an equation!
````

(targeting-headers)=

### Header Targets

To add labels to a header use `(my-section)=` before the header, these can then be used in markdown links and {myst:role}`ref` roles. This is helpful if you want to quickly insert links to other parts of your book. Referencing a heading will show the heading and the subsequent two pieces of content[^heading-content], unless a header is encountered.

[^heading-content]: The content could be a single paragraph, a figure, table or list. It can also be fully interactive content, with cross-references to other content, allowing you to nest and follow references easily!

```{myst}
(my-section)=
#### Header _Targets_

Use `(label)=` before the element that you want to target, then reference content with:

* [](#my-section)
```

:::{tip} How to turn on heading `numbering`
:class: dropdown

By default headings are not numbered, see [](#header-numbering) for more information. To turn on numbered headers you need to turn numbering on in the document or project using `numbering` in the frontmatter. You can control this for each heading level:

```yaml
numbering:
  heading_1: true
  heading_2: true
```

These will show up, for example, as `Section 1` and `Section 2.1`. To turn on all heading numbering, use `headings: true`.
:::

% TODO: We should support pandoc style unnumbered {-} and {.class, #id} syntax

(header-numbering)=

#### Header Numbering

By default section numbering for headers is turned off with numbering for figure and table numbering enabled.
To turn on `numbering` for headers, you can can change the frontmatter in the document or project. See [](#numbering) for more details on the numbering object.

```{myst}

---
numbering:
  heading_2: true
  heading_3: true
---

(my-chapter)=
## My Chapter

(my-section)=
### My Section

(my-section2)=
### My Second Section

* [](#my-chapter)
* [](#my-section)
* [](#my-section2)
```

(targeting-cells)=

### Notebook Cell Targets

You can label notebook cells using a comment at the top of the cell, using a `#| label:` syntax, or have this added directly in the notebook metadata for the cell.

```python
#| label: my-cell
print('hello world')
```

The cell output or the entire cell can be embedded or referred to using the image or link syntax.

```markdown
[](#my-cell) - This is a cross-reference to a notebook cell
 - This will embed the output of a notebook cell
```

or as a `figure` directive, where you can then add a caption. If you are referring to that figure in a further cross reference that figure (i.e. not the original cell), give it a new `name`.

```markdown
:::{figure} #my-cell
:label: fig-my-cell
:::
```

:::{card} ♻️ See Also: Reusing Jupyter Outputs
:link: ./reuse-jupyter-outputs.md
See more about reusing Jupyter outputs in figures, adding placeholders, and other options.
:::

:::{note} Interactive Example

The following example embeds a figure from [](./interactive-notebooks.ipynb), and can be used in cross references [](#fig-altair-horsepower).

```{figure} #img:altair-horsepower
:label: fig-altair-horsepower
This figure has been included from [](./interactive-notebooks.ipynb) and can be referred to in cross-references through a different label.
```

:::

(label-anything)=

### Label Anything

It is possible to label any document node by adding `(my-label)=` before any other block of content. These can be referenced using the {myst:role}`ref` role, but by default will not be enumerated, so you cannot use `%s` or `{number}` in the content.

```{myst}
(my-paragraph)=
This is just a paragraph!

(my-points)=
* Bullet
* points

Please see [this paragraph](#my-paragraph) and [these points](#my-points).
```

(numbering)=

## Numbering

Frontmatter may specify `numbering` to customize how various components of the page are numbered. By default, numbering is enabled for figures, equations, tables, math, and code blocks; it is disabled for headings and other content types contained on the page. Additionally, by default, numbering resets on every page.

### Enabling and Disabling Numbering

To enable numbering of all content, you may simply use:

```yaml
numbering: true
```

Similarly, to disable all numbering:

```yaml
numbering: false
```

The `numbering` object allows you to be much more granular with enabling and disabling specific components:

```yaml
numbering:
  code: false
  equations: false
  headings: true
```

Numbering may be used for `figure` as above, as well as `subfigure`, `equation`, `subequation`, `table`, `code`, `headings` (for all heading depths), and `heading_1` through `heading_6` (for modifying each depth separately).

### Numbering Custom Content

You may also add numbering for custom content kinds:

```markdown
---
numbering:
  box:
    enabled: true
---

:::{figure} image.png
:label: my-box
:kind: box

This figure will be numbered as "Box 1"
:::
```

### Customizing Numbering Appearance

By default, all components are numbered sequentially as 1, 2, 3... However, under the `numbering` object, you may specify `enumerator`. For now, this applies to all numberings on the page. Instead of enumerating as simply 1, 2, 3... they will follow the template set in `enumerator`. For example, in Appendix 1, you may want to use the following `numbering` so content is enumerated as A1.1, A1.2, A1.3...

```yaml
numbering:
  enumerator: A1.%s
```

If you want to control the numbering for a specific figure, you can use the {myst:directive}`figure.enumerator` option. This will give the figure a specific enumerator, and will not increment the counting for other figures. This is helpful if you want to explicitly count figure `2a` and then carry on counting figures as normal; alternatively you can take control of numbering entirely by setting {myst:directive}`figure.enumerator` on every figure.

You may also redefine how the component will render when referenced in the text by specifying `template`. For this example, the figures on the page will start with `Figure 1` and when referenced in the text they will appear as "fig (1)"

```yaml
numbering:
  figure:
    template: fig (%s)
```

### Continuous Numbering

By default, numbering will reset on every page. However, you may enable continuous numbering across all pages by specifying `continue: true` in your `numbering` object. If this is specified on a single page, it will continue counting from the previous page; if specified in your `myst.yml`, counting will be continuous across the entire project.

```yaml
numbering:
  figure:
    continue: true
```

You may also override the `start` value to begin counting on the page at a specific number. This is useful, for example, if you want continuous figure numbering across your project until you reach your appendix, then you want to reset to A1:

```yaml
numbering:
  enumerator: A%s
  figure:
    start: 1
```

### Title Numbering

By default, page titles are not numbered, even if you turn on all numbering with `numbering: true`. However, you may add `title` to your numbering object:

```yaml
numbering:
  title: true
```

Doing so will enumerate all the titles in your MyST project. These numberings will follow the structure of your table of contents. So, given the structure:

```yaml
toc:
  - file: index.md
  - file: section_a.md
    children:
      - file: chapter_1.md
      - file: chapter_2.md
  - file: section_b.md
```

The numbering will be: `1 - index.md`, `2 - section_a.md`, `2.1 - chapter_1.md`, `2.2 - chapter_2.md`, and `3 - section_b.md`.

If both `title` and `heading` numbering are enabled, these will be incremented together. So, for the example above, if there is a single heading of level 1 in `section_a.md`, it will increment the same count as the title of `chapter_1.md` and `chapter_2.md` (i.e. the heading will be `2.1` and the chapters will be `2.2` and `2.3`):

```yaml
numbering:
  title: true
  headings: true
```

You can further customize this behavior by setting an explicit `offset` value on a page. By default the offset matches the nesting level in the table of contents, but, for example, if you want page numbering to be flat, despite nesting in the table of contents, you can set `offset: 0`:

```yaml
numbering:
  title:
    enabled: true
    offset: 0
```

For the example above, the numbering will change to: `1 - index.md`, `2 - section_a.md`, `3 - chapter_1.md`, `4 - chapter_2.md`, and `5 - section_b.md`.

---

### Deployment Curvenote (`docs/deployment-curvenote.md`)

---
title: Deploying to Curvenote
short_title: Curvenote
description: Deploy your MyST site to Curvenote
---

Curvenote provides a free service to host your MyST sites with an up-to-date theme ([deployment documentation](https://github.com/curvenote/action-myst-publish) for MyST sites). The websites are hosted on a `curve.space` subdomain with your username or a [custom domain](https://curvenote.com/docs/web/custom-domains). To configure the domain(s) add them to your site configuration:

```yaml
site:
  domains:
    - username.curve.space
```

You can then deploy the site using:

```bash
curvenote deploy
```

You can also deploy from a GitHub action, which will build your site and then deploy it to Curvenote.

🛠 In the root of your git repository run `myst init --gh-curvenote`

The command will ask you questions about which branch to deploy from (e.g. `main`) and the name of the GitHub Action (e.g. `deploy.yml`). It will then create a GitHub Action[^actions] that will run next time you push your code to the main branch you specified. Ensure that you including setting up your `CURVENOTE_TOKEN` which can be created from your Curvenote profile.

:::{tip} Full GitHub Actions
:class: dropdown

You can use GitHub actions to build and deploy your site automatically when you merge new documents, for example.

See the documentation for the action, including setting up your `CURVENOTE_TOKEN`:\
https://github.com/curvenote/action-myst-publish

```yaml
name: deploy-myst-site
on:
  push:
    branches:
      - main
permissions:
  contents: read
  pull-requests: write
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy 🚀
        uses: curvenote/action-myst-publish@v1
        env:
          CURVENOTE_TOKEN: ${{ secrets.CURVENOTE_TOKEN }}
```

:::

[^actions]: To learn more about GitHub Actions, see the [GitHub documentation](https://docs.github.com/en/actions/quickstart). These are YAML files created in the `.github/workflows` folder in the root of your repository.

---

### Deployment Github Pages (`docs/deployment-github-pages.md`)

---
title: Deploy to GitHub Pages
short_title: Github Pages
description: Deploy your MyST site to GitHub pages.
---

[GitHub Pages](https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages) allows you to host static HTML files online from GitHub repositories using GitHub Actions.
This page has important information for how to do so.

## Instructions

To get setup with GitHub Pages, ensure that your repository is hosted in GitHub and you are in the root of the Git repository.
There's a special `init` function which adds the proper configuration for deploying to GitHub Pages with a GitHub Action.

🛠 In the root of your git repository run `myst init --gh-pages`

The command will ask you questions about which branch to deploy from (e.g. `main`) and the name of the GitHub Action (e.g. `deploy.yml`). It will then create a GitHub Action[^actions] that will run next time you push your code to the main branch you specified.

:::{figure} ./images/myst-init-gh-pages.png
:class: framed
The command `myst init --gh-pages` will guide you through deploying to GitHub Pages.
:::

[^actions]: To learn more about GitHub Actions, see the [GitHub documentation](https://docs.github.com/en/actions/quickstart). These are YAML files created in the `.github/workflows` folder in the root of your repository.

🛠 In your repository, navigate to {kbd}`Settings` -> {kbd}`Pages` and enable GitHub Pages by choosing {kbd}`GitHub Actions` as the source.

This has activated GitHub Pages to accept new HTML from GitHub actions.

To trigger the action, push new commits of code to the branch that you've configured with the action above. You should start seeing your website show up at `<githuborg>.github.io/<githubrepo>`.

## `BASE_URL` Configuration for GitHub Pages
The MyST CLI needs to know the destination (base URL) of your site during build time. If you setup deployment to GitHub Pages using the `myst init --gh-pages` command, then _this is handled automatically for you_. Otherwise, if you deploy your website from a repository that's not the default GitHub Pages repository (i.e., not called `<username>.github.io`), you likely need to define a `BASE_URL` that includes the repository name.[^except-custom-domains] 
[^except-custom-domains]: If you're using a custom domain, you may not need to set `BASE_URL` if the site is served from the base domain (e.g.: `mydomain.org`) without a sub-folder (e.g., `mydomain.org/mydocs/`).

## Example: A Full GitHub Action

The GitHub Action below builds and deploys your site automatically.
Click the dropdown to show it, and copy/paste/modify as you like.

:::{note} GitHub Action Example
:class: dropdown

```{code} yaml
:filename: deploy.yml
# This file was created automatically with `myst init --gh-pages` 🪄 💚

name: MyST GitHub Pages Deploy
on:
  push:
    # Runs on pushes targeting the default branch
    branches: [main]
env:
  # `BASE_URL` determines the website is served from, including CSS & JS assets
  # You may need to change this to `BASE_URL: ''`
  BASE_URL: /${{ github.event.repository.name }}

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
  group: 'pages'
  cancel-in-progress: false
jobs:
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Pages
        uses: actions/configure-pages@v3
      - uses: actions/setup-node@v4
        with:
          node-version: 24.x
      - name: Install MyST Markdown
        run: npm install mystmd
      - name: Build HTML Assets
        run: myst build --html
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: './_build/html'
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4
```

:::

---

### Deployment Gitlab (`docs/deployment-gitlab.md`)

---
title: Deploy to GitLab Pages
short_title: GitLab Pages
description: Deploy your MyST site to GitLab pages.
---

GitLab Pages allows you to host static HTML files online from GitLab repositories using [GitLab CI/CD](https://docs.gitlab.com/ci/).
This page has important information for how to do so.

## Instructions

:::{warning}
Because of your institution’s GitLab configuration, the descriptions below may differ from the actual deployment on GitLab Pages.

If you are new to GitLab or you are not familiar with `git`, please proceed to [](#instructions-for-beginners)
:::

To get setup with GitLab Pages, ensure that your repository is hosted in GitLab and you are in the root of the Git repository.

### Deployment with uv
Create `.gitlab-ci.yml` file in the root of your project with the content provided below:

```{code} yaml
:filename: .gitlab-ci.yml
:linenos:
:emphasize-lines: 47

image: ghcr.io/astral-sh/uv:debian-slim

stages:
  - build
  - deploy

variables:
  HOST: "127.0.0.1"

cache:
  paths:
    - .venv

before_script:
  - uv --version

build:
  stage: build
  script:
    # initialize uv project and install jupyter-book
    - uv init
    - uv add "jupyter-book>=2.1.2,<3"

    # install node
    - apt-get update
    - apt-get install -y curl
    - apt-get install -y procps
    - curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
    - apt-get install -y nodejs

    # run jupyter-book via uv
    - uv run jupyter-book clean --all -y
    - export BASE_URL=""
    - uv run jupyter-book build --html
  artifacts:
    paths:
      - _build/html

pages:
  stage: deploy
  script:
    - mv _build/html/ public
  artifacts:
    paths:
      - public
  only:
    - main # replace it with YOUR branch name
```

then push this file to your GitLab repo.

> If your Git branch is different from `main`, you should replace main in the `.gitlab-ci.yml` file on the highlighted line with your branch name.

Once everything done, you should see `GitLab Pages` link in the right menu as shown below:
```{figure}  ./images/gitlab-pages.png
:height:300px
```

### Deployment with poetry
Create a file called `.gitlab-ci.yml` with the following content:


```
/* Detailed source-code truncated for AI context efficiency. */
```

### Deployment with pixi
*Note*: You may not use pixi in your project but you may use it for GitLab deployment.

1. Make sure that you have [`pixi`](https://pixi.prefix.dev/latest/#installation) installed on your machine.

2. Create a file called `.gitlab-ci.yml` with the following content:

```{code} yaml
:filename: .gitlab-ci.yml
:linenos:
:emphasize-lines: 39 

image: ghcr.io/prefix-dev/pixi:latest

stages:
  - build
  - deploy

variables:
  PIXI_CACHE_DIR: "$CI_PROJECT_DIR/.pixi"
  HOST: "127.0.0.1"

cache:
  paths:
    - .pixi

before_script:
  - pixi --version

build:
  stage: build
  script:
    # install environment from pixi.toml + pixi.lock
    - pixi install --locked

    # run jupyter-book via pixi environment
    - pixi run jupyter-book build --html
  artifacts:
    paths:
      - _build/html

pages:
  stage: deploy
  script:
    - mkdir public
    - cp -r _build/html/* public/
  artifacts:
    paths:
      - public
  only:
    - main # replace it with your branch name!
```

> If your Git branch is different from `main`, you should replace main in the `.gitlab-ci.yml` file on the highlighted line with your branch name.

3. Make sure your pixi project is initialized (you may use `pixi init` CLI command to do so)

4. Make sure that your `pixi.toml` file contains `linux-64` as a platform and `python` with `jupyter-book` as dependencies.
    A minimal version of the `pixi.toml` file is shown below.

```{code-block} toml
:filename: pixi.toml

[workspace]
authors = ["Me <me@mygroup.org>"]
channels = ["conda-forge"]
name = "jbtest"
platforms = ["win-64", "linux-64"]
version = "0.1.0"

[tasks]

[dependencies]
python = ">=3.14.3,<3.15"
jupyter-book = ">=2.1.2,<3"
```

5. Synchronize `pixi.lock` file using `pixi lock` CLI command.

> Note that a [pixi.toml](https://pixi.prefix.dev/latest/python/pyproject_toml/) and pixi.lock file should be tracked by Git and pushed to the repository with other files.

6. Add your project files to git using `git add ` (e.g `git add myst.yml main.md pixi.toml pixi.lock`)
7. Commit the changes
8. Push your branch to GitLab (e.g `git push -u origin main`)



## External server through GitLab CI/CD
Another option is to deploy your MyST site to an external server through GitLab CI/CD. A main difference is setting 'variables' (settings $\rightarrow$ CI/CD $\rightarrow$ variables) for connecting to the server.

An example `.gitlab-ci.yml` file for this deployment method is shown below.

```{code} yaml
:filename: .gitlab-ci.yml
:lineos:

stages:
  - deploy

image: python:3.11-slim

variables:
  SSH_COMMAND: 'ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes'
  LOCAL_BUILD_DIR: "_build/html"
  HOST: "127.0.0.1"
  BASE_URL: ""

before_script:
  - apt-get update
  - apt-get install -y --no-install-recommends curl rsync openssh-client git procps

  # Node.js
  - curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
  - apt-get install -y --no-install-recommends nodejs
  - node --version
  - npm --version

  # Python deps
  - python -m pip install --upgrade pip
  - pip install mystmd

  # Load SSH key
  - eval "$(ssh-agent -s)"
  - chmod 400 "$WEBSITE_UPLOAD_KEY"
  - ssh-add "$WEBSITE_UPLOAD_KEY"

deploy:
  stage: deploy
  script:
    # Build (important: define the project path)
    - myst build --html

    - rsync -ravz "${LOCAL_BUILD_DIR}/" -e "${SSH_COMMAND} -i ${WEBSITE_UPLOAD_KEY}" "${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/"

```

Note that this way of deploying requires a gitlab runner.

## Instructions for beginners
If this is your first time using GitLab, complete these one-time setup steps:
1. [Install Git](https://docs.gitlab.com/topics/git/how_to_install_git/) 
2. Configure your git by using the following commands in the terminal
    ```shell
    git config --global user.name "Your Name"
    git config --global user.email "your-mail@your-domain.com"
    ```
3. Create a GitLab account [on official
   GitLab](https://gitlab.com/users/sign_in/) or on the GitLab of your
   institution.
4. [Set up SSH authentication](https://docs.gitlab.com/user/ssh/)  

Once set up, you have two options to connect your project to GitLab:
1. *Start from GitLab*: [Create a repository on GitLab, clone it to your computer, add your files, and push them](https://docs.gitlab.com/tutorials/make_first_git_commit/#steps)
2. *Start from your computer*: Initialize your local folder as a Git repository and push it to GitLab using the following commands:
    ```bash
    cd your-project-folder   # go to your local folder with your myst project
    git init                 # initialize git
    git add .                # stage all files
    git commit -m "first commit"
    git remote add origin git@gitlab.com:username/project.git # you may change this link with the link of your repository
    git push -u origin main
    ```

Once your git project is initialized, create `.gitlab-ci.yml` file in the root
of your myst project and paste the contents described in [](#deployment-with-uv) to the file.


Once you saved the file with provided contents, execute the next commands:
```shell
git add .gitlab-ci.yml
git commit -m "added .gitlab-ci.yml to set up GitLab Pages"
git push
```

You are all done. You may proceed to the page of your GitLab repository and
open GitLab Pages.

---

### Deployment Netlify (`docs/deployment-netlify.md`)

---
title: Deploying to Netlify
short_title: Netlify
description: Deploy your MyST site to Netlify
---

% Adapted from: https://jupyterbook.org/en/stable/publish/netlify.html#step-2-add-the-command-to-install-and-build-your-book

[Netlify](https://www.netlify.com/) is a continuous deployment service that can
**automatically build an updated copy of your project** as you push new content.
It can be used across git clients including GitHub, GitLab, and Bitbucket.
Although Netlify has both free and paid tiers, the build process is the same across both.
Importantly, the free tier only allows for 100GB of bandwidth usage per month across all of your Netlify built projects[^pricing].

:::{note} You may wish to set more permissive CORS settings
To allow other MyST sites to reference and use your content, ensure that Netlify has the proper CORS configuration. For an example, see [this GitHub PR updating CORS settings for Netlify](https://github.com/the-turing-way/the-turing-way/pull/4156). See [](#cors-settings) for more information.
:::

[^pricing]: If your project will be used by a large audience, or if you're creating many projects, you might want to consider registering for [a paid account](https://www.netlify.com/pricing/).

These instructions assume you're keeping your source files under version control,
rather than the built project HTML.

In order to use Netlify, you'll need to [create an account](https://app.netlify.com/signup).
Here, we'll walk through connecting your project to Netlify's continuous deployment services using their UI.
You can also check out their [documentation on continuous deployment](https://www.netlify.com/docs/continuous-deployment/).

## Step 1: Connect your GitHub repo to Netlify

After you've created a Netlify account, you'll need to log in.
The home page will be a dashboard of all sites you're currently building with Netlify.
We can then import a new site by clicking the "New Site from Git" button in the upper right.

This should launch [the site builder](https://app.netlify.com/start):



Here, you can select the git client where your project is hosted.
For the purposes of this tutorial, we'll assume that your book is hosted on GitHub.

When you select the "GitHub" option, you'll be asked to grant permission for Netlify to access your GitHub account.
Authorizing access will take you to the next step of the build process, where you can select your project repository.



## Step 2: Add the command to install and build your project

:::{note}
If your book content is not in the root of your repository, make sure you point to
where you will run the `myst build --html` command locally.
:::

Once you've selected the correct repository, you'll need to supply build instructions.
This is a command that Netlify runs before hosting your site. We'll use it to do the
following:

- Install `mystmd`
- Build your project's HTML

Put the following command in the _Build command_ section:

```bash
npm install mystmd && myst build --html
```

Finally, the _Publish directory_ should be `_build/html`.

You'll also need to select the appropriate branch to build your repository from.
In this example, we'll use the `main` branch.



You can then select _Deploy site_ and wait for the site to build.
You'll be redirected to the site dashboard during the build process.

## Step 3: Updating your domain name

If your site has successfully built, it will be assigned a random domain name.
In order to have a more memorable address, you can update your site's name.

From the site dashboard, select _Domain settings_.
This will take you to a sub-menu, where you can choose to update your site name.



You can enter a memorable, unique name here to describe your project!
Note that it will be prepended to `.netlify.com` so, `MY-BOOK` will become `MY-BOOK.netlify.com`.

You can also use a custom domain (i.e., one that you have purchased through a DNS registrar).
See the [Netlify documentation on custom domains](https://www.netlify.com/docs/custom-domains/) for more details on this process.

---

### Deployment Readthedocs (`docs/deployment-readthedocs.md`)

---
title: Deploy to Read the Docs
short_title: ReadTheDocs
description: Deploy your MyST site to Read the Docs.
---

[Read the Docs](https://readthedocs.org) is a popular platform for hosting documentation that provides free hosting for open source projects and supports automatic builds from your Git repository.
This page has important information for how to deploy MyST sites to Read the Docs.

## Instructions

To get setup with Read the Docs, ensure that your repository is hosted on GitHub, GitLab, or Bitbucket, and you are in the root of the Git repository.
There's a special `init` function which adds the proper configuration for deploying to Read the Docs.

🛠 In the root of your git repository run `myst init --readthedocs`

The command will ask you which `Python` and `Node.js` versions to use. It will then create a `.readthedocs.yaml` configuration file in the root of your repository.[^python-note]

[^python-note]: While MyST builds only require Node.js, the configuration also includes Python. This is useful if you need to execute code in Jupyter notebooks or if you're using [Jupyter Book](https://jupyterbook.org) features alongside MyST.

After creating the configuration file, you'll need to:

🛠 Create an account on [readthedocs.org](https://readthedocs.org) if you don't have one

🛠 Import your project from your Git hosting provider (GitHub, GitLab, or Bitbucket)

🛠 Commit and push the `.readthedocs.yaml` file to your repository

Read the Docs will automatically build your documentation on each push. Your documentation will be available at `https://YOUR-PROJECT.readthedocs.io`.

## ReadTheDocs JavaScript might interfere with your site

By default, ReadTheDocs enables [documentation addons](https://docs.readthedocs.com/platform/latest/addons.html) that execute JavaScript on the page.
This may interfere with the React-based rendering that the `myst-theme` uses.
You might see an occasional "flicker" of the content as a result.
Experiment with disabling these add-ons and it may improve your outcomes, your mileage may vary!

## Example: A Full Read the Docs Configuration

The configuration file below builds and deploys your site automatically.
Click the dropdown to show it, and copy/paste/modify as you like.

:::{note} Read the Docs Configuration Example
:class: dropdown

```{code} yaml
:filename: .readthedocs.yaml
# Read the Docs configuration file for myst
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# This file was created automatically with `myst init --readthedocs`

# Required
version: 2

# Set the OS, Python version, and Node.js version
# Note: Python is included for executing code in notebooks or using Jupyter Book
build:
  os: ubuntu-22.04
  tools:
    python: "3.12"
    nodejs: "22"
  commands:
    # Install mystmd
    - npm install mystmd
    # Build the site
    - myst build --html
    # Copy the output to Read the Docs expected location
    - mkdir -p $READTHEDOCS_OUTPUT/html/
    - cp -r _build/html/. "$READTHEDOCS_OUTPUT/html"
    # Clean up build artifacts
    - rm -rf _build
```

:::

---

### Deployment Webserver (`docs/deployment-webserver.md`)

---
title: Deploy on an Apache web server (httpd)
short_title: Apache httpd
description: Deploy your MyST site on Apache httpd
---

Once you have built a static version of your MyST project via `myst build --html`, it can be served on an any common web server: [Apache web server (httpd)](https://httpd.apache.org), [nginx](https://nginx.org/), or others.

For example, let's assume your web server's base URL is `http://www.example.com` and it uses `/var/www/html` as the file server root (`DocumentRoot` in httpd). If you copy the `_build/html/` directory to `/var/www/html/my-project` using

```shell
cp -r _build/html /var/www/html/my-project
```

then the resulting URL would be `http://www.example.com/my-project`, and you are all set if you have [configured the base URL](deployment.md#deploy-base-url).

---

### Deployment (`docs/deployment.md`)

---
title: Host your MyST Site
short_title: Web hosting
description: Deploy your MyST site to static HTML or a MyST-aware server.
---

There are two different ways to host MyST websites online.

- **As a static website**. An HTML file is generated for each page at once. The collection of HTML files and website assets can be served from static site hosts (like [GitHub Pages](https://docs.github.com/en/pages), [Netlify](https://netlify.com), and [ReadTheDocs](https://readthedocs.org)).
- **As an application**. A MyST _server_ is run that dynamically generates pages when a user visits them. Your site can be served by a hosting provider that supports applications (like [Curvenote](https://curvenote.com) or [Vercel](https://vercel.com))

The high-level differences between these approaches are outlined in [](#deployment-comparison).
:::{table} High-Level Comparison of MyST Site Deployment Types
:label: deployment-comparison

| Deployment Type | High Performance | Seamless Updates | Static Hosting |
| :-------------: | :--------------: | :--------------: | :------------: |
| Static website  |        ❌        |        ❌        |       ✅       |
|   MyST server   |        ✅        |        ✅        |       ❌       |

:::

:::{note} MyST was designed to be deployed as an application
Deploying MyST as an application has many benefits. For example, [performance enhancements](./accessibility-and-performance.md) (like pre-fetching for instant page-transitions, loading indicators, and smaller network payloads) and easier upgrades as new MyST versions are released.

The [default themes](#default-web-themes) for MyST are designed to be MyST applications rather than static sites, but the core functionality is equally shared between the two options.
:::

% - Static deployments are MPA (each page own HTML document), SSG (rendered ahead of time)
% - Servers are SPA (request JSON), SSR+hydration
%- Term definitions?
% - SPA vs MPA
% - SSR vs CSR vs SSG

The choice between static hosts and application-based hosts often comes down to the type of website hosting that is available, and the amount of complexity that you're willing to deal with in deploying your site.
The sections below share a few considerations to help you make a decision.

## Static Websites

### Creating Static HTML

To create a static HTML export of your MyST site, build it as HTML:

```bash
myst build --html
```

After the build process, you can see the folder in `_build/html`, which has all assets for your static website. You can verify that the site is working correctly by starting a static web-server, for example,

```shell
npx serve _build/html
```

which will serve a static version of the site.

:::{danger} Static sites should have an `index.html`
:class: dropdown

A static site needs an `index.html` at its root.
MyST generates one automatically when your site has a single project built at the root URL, which is the default.

If a root `index.html` is _not_ generated, your project is being built under a nested URL instead of at the root.
You're probably using the [deprecated `projects:` configuration](#multiple-projects-deprecated), and should remove it.

:::

:::{tip} Ignore the `_build` folder in Git
:class: dropdown

If you are using Git, add the `_build` folder to your `.gitignore` so that it is not tracked. This folder contains auto-generated assets that can easily be re-built -- for example in a Continuous Integration system like GitHub Actions.
:::

:::{tip} Static HTML generates folder-based HTML files
:class: dropdown

When you generate static HTML using MyST, routes to documents (e.g. `/folder/mydoc`) must be rendered into static HTML files. MyST will turn routes into HTML paths like so:

```
/myfolder/mydoc/index.html
```

When the browser sends a request to the route `/folder/mydoc`, the server interprets that as request for the HTML file `/myfolder/mydoc/index.html`, and returns that.

Some SSGs instead return HTML files like `/myfolder/mydoc.html`, and this can trigger different behavior depending on the hosting platform you're using. However, `/myfolder/mydoc/index.html` is generally a safer bet, which is why it is the default.

See [the trailing slash and hosting provider guide](https://github.com/slorber/trailing-slash-guide) for more information about the impact of this behavior across hosting providers.

_Inspired from the [excellent Docusaurus documentation](https://docusaurus.io/docs/advanced/routing#routes-become-html-files)_
:::

(deploy:base-url)=
### Custom domains and the base URL

When deploying static HTML to the web, you may have to specify a Base URL so that links resolve properly.
This happens when you serve your MyST site from a *subfolder* of a parent URL.
For example:

- `mysite.org/`: **Does not** require a `BASE_URL` to be set, because the root site is where your MyST site lives.
- `mysite.org/docs/`: **Does** require a `BASE_URL` to be set, because your MyST HTML files will be in `docs/`, not the root.

If MyST detects an environment variable called `BASE_URL` it will prepend it to all links.

In the following examples we first define a `BASE_URL` parameter and then build the MyST HTML assets.

::::{tab-set}
:::{tab-item} Bash
```bash
export BASE_URL="/repository_name"
myst build --html
```
:::
:::{tab-item} Powershell
```powershell
$env:BASE_URL = "/folder1/folder2" 
myst build --html
```
:::
:::{tab-item} Fish
```fish
set -x BASE_URL "/folder1/folder2"
myst build --html
```
:::
:::{tab-item} CMD
```cmd
set BASE_URL=/folder1/folder2
myst build --html
```
:::
::::

:::{tip} Set `BASE_URL` in your CI/CD
You can set environment variables in many CI/CD services like GitHub Actions and Netlify.
This can be a useful way to ensure the `BASE_URL` is set before your site is deployed.
:::

### Services for Static Web Hosting

The contents of the `_build/html` can be served from any static web server. The following articles outline the process of deploying your static site to well-known website providers:

(static-web-services-dropdown)=

:::{toc}
:context: children
:::

## Application Websites

### Creating Structured Site Data

MyST servers consume _structured data_ that represents a MyST website. These data can be built using the `myst build` command,

```shell
myst build --site
```

which populates the `_build/site` directory with information about your website including the metadata, cross-references, static images, and [MyST AST](https://mystmd.org/spec).

### Serving on a Network Interface

`myst start` only listens on `localhost`, so the site is not reachable from other machines.
To serve it to your network (for example, from a container or a remote server), set the `HOST` environment variable and pass `--keep-host`:

```shell
HOST=0.0.0.0 myst start --keep-host
```

Without `--keep-host`, MyST resets `HOST` to `localhost` and prints a warning.

### Deploying to a MyST-Aware Server

:::{note}
At present, only [Curvenote](https://curvenote.com/) provides out-of-the-box support for deployment of MyST websites:
:::

% TODO: vercel/netlify server

:::{card} Curvenote
:link: ./deployment-curvenote.md
Deploy to Curvenote as a dynamic site with a managed MyST theme.
:::

---

### Developer Api (`docs/developer-api.md`)

---
title: MyST engine internals
short_title: Engine internals
description: How a build moves through the MyST engine, and which objects carry state between the stages.
---

This page explains how a build moves through the engine and which objects carry state between the stages.
It is for people changing the engine or calling `myst-cli` from their own code.
If you are writing a plugin, start with [](#plugins:api) instead.
Each section links to the source on `main`, which may be newer than the version you have installed.

(api:pipeline)=

## Build pipeline

```{mermaid}
flowchart TD
    src["Source files<br>(.md / .ipynb / myst.yml)"]
    out["Render<br>(site JSON · PDF · JATS · DOCX)"]
    p1["🔌 DirectiveSpec · RoleSpec"]
    p2["🔌 TransformSpec stage: 'document'"]
    p3["🔌 LinkTransformer<br>TransformSpec stage: 'project'"]

    subgraph per_file ["Per file"]
        parse["Parse → MDAST<br>(PreRendererData)"]
        exec["Execute notebooks<br>(myst-execute)"]
        dtrans["Document transforms<br>→ RendererData"]
        parse --> exec --> dtrans
    end

    subgraph project ["Project"]
        ptrans["postProcessMdast<br>(resolve links and cross-references,<br>then project transforms)"]
    end

    src --> per_file
    p1 -.-> parse
    p2 -.-> dtrans
    per_file --> project
    p3 -.-> ptrans
    project --> out
```

Directives and roles run inside the parser, so they see no other file and no execution output.
Document transforms then run once per file in [`transformMdast`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-cli/src/process/mdast.ts), which ends by building that file's `RendererData`.
Once every file is loaded, MyST collects cross-reference targets from all of them.
Finally `postProcessMdast`, in the same module, runs once per file.
It resolves links and cross-references in place and then runs the project transforms.
See [](#develop:transforms) for what the AST looks like before and after.

Every engine function in these stages takes an `ISession`.
Plugins never receive a session, as explained in [](#api:session-cache).

(api:session)=

## Session

Every stage shares one session object.
It carries the logger, the HTTP client, the Redux store, the build paths, and the loaded plugins.
Two types share the name.

- The minimal [`ISession` in `myst-cli-utils`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-cli-utils/src/types.ts) has only `log` and `fetch()`. Use it for utilities and [link transformers](#api:link-transformer).
- The full [`ISession` in `myst-cli`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-cli/src/session/types.ts) adds the Redux `store` (see [](#api:config)), path helpers such as `sourcePath()` and `buildPath()`, the loaded `plugins`, and helpers for notebook execution. The source lists the rest.

(api:session-cache)=

### Session cache: `ISessionWithCache`

At runtime the session also caches per-file data such as parsed trees, citation renderers, and execution outputs.
[`ISessionWithCache`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-cli/src/session/types.ts) is the wider type that exposes these caches.
Call `castSession(session)` to get the wider type.
The two types are separate so that code which only needs `ISession` does not have to import every `myst-*` package that the cache fields depend on.
Both types and `castSession` are exported from `myst-cli`, but neither is a stable public API.

- `$mdast` maps each file to its `pre` and `post` data (see [](#api:document-data)). Read and write entries through `$getMdast(file)` and `$setMdast(file, data)`.
- The other caches are `$citationRenderers` (keyed by file), `$doiRenderers` (keyed by DOI), `$externalReferences`, `$outputs`, and `$siteTemplate`.

Plugin transforms never see the session.
If you drive the build yourself, you can pass `extraTransforms` to `transformMdast` or `processProject` instead.
MyST calls each transform as `transform(session, opts)` once per file, right after that file's `RendererData` is stored.
The `opts` argument is the same options object that `transformMdast` received.

(api:document-data)=

## Document data

- A [`VFile`](https://github.com/vfile/vfile) wraps one document while transforms run. Its `path` is the absolute source path. Messages attached to the file become build warnings, as described in [](#plugins:warnings).
- [`PreRendererData`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-cli/src/transforms/types.ts) is created when a file is loaded. It holds the `file` path, its `location` in the project, the parsed `mdast`, the `kind` (`Article`, `Notebook`, or `Part`), and optional `frontmatter`, `identifiers`, and `widgets`.
- `RendererData` extends `PreRendererData` with `sha256`, `slug`, the resolved `frontmatter`, `references`, and `dependencies`. `transformMdast` builds the `RendererData`, `postProcessMdast` updates the object in place, and the site content JSON is the serialised form.

(api:ast)=

## AST node types

- [`GenericNode` and `GenericParent`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-common/src/types.ts) are the loosely typed shapes most engine code uses. They have `type`, optional `children`, `value`, `label`, `identifier`, and `position`, and allow any other field.
- The canonical node types are in [myst-spec](https://github.com/jupyter-book/myst-spec). MyST-only additions are in [`myst-spec-ext`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-spec-ext/src/types.ts).
- Traverse with [unist-util-visit](https://github.com/syntax-tree/unist-util-visit) and query with [unist-util-select](https://github.com/syntax-tree/unist-util-select):

```{code} typescript
import { visit } from 'unist-util-visit';
import { selectAll } from 'unist-util-select';

visit(tree, 'code', (node) => {
  if (!node.lang) node.lang = 'text';
});
const figures = selectAll('container[kind=figure]', tree);
```

(api:link-transformer)=

## Link transformers

DOIs, arXiv IDs, and internal cross-references each need their own handling.
Link resolution is therefore a chain of [`LinkTransformer`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-transforms/src/links/types.ts) objects, tried in order during post-processing.

- `test(uri)` returns whether this transformer handles the URI.
- `transform(link, vfile)` mutates the `Link` node in place and returns `true` on success.
- `protocol` names the scheme. Set `formatsText` to `true` if your transformer sets the link text itself, so that MyST leaves it alone.

The built-in transformers live in [`myst-transforms/src/links/`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-transforms/src/links).
To add your own, pass them as `extraLinkTransformers` to `postProcessMdast` or `processProject`.
They run before the built-ins.
There is no way to add them from `myst.yml`.

(api:config)=

## Where the other types live

- [`ProjectConfig`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-config/src/project/types.ts) and [`SiteConfig`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-config/src/site/types.ts) are the validated forms of `myst.yml`. Read them from the Redux store with the [`selectors`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-cli/src/store/selectors.ts) exported from `myst-cli`.
- [`ICache` and `LocalDiskCache`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-execute/src/cache.ts) in `myst-execute` cache cell outputs on disk, one JSON file per key, so that rebuilds skip unchanged cells.
- [`Logger`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-cli-utils/src/types.ts) is `Pick<typeof console, 'debug' | 'info' | 'warn' | 'error'>`. Use `session.log` for build-level messages and `fileWarn` from `myst-common` for anything tied to a document, as described in [](#plugins:warnings).

---

### Developer (`docs/developer.md`)

---
title: Developer Guide
short_title: Developer Guide
---

These sections help you get started with a development environment for `mystmd` and learn how to contribute to the codebase. Note that `mystmd` is written in [TypeScript](https://www.typescriptlang.org/).

We start by discussing the project architecture, and give a birds eye view of how the various parts fit together.
Then, we delve into the specific tools you need, and the developer workflow for each part.
Finally, we go over requirements for contributing code back, via GitHub Pull Requests.

(architecture)=

## Architecture underlying a MyST build

From an author's perspective, `mystmd` can be thought of as a tool which compiles files in [MyST Markdown format](./quickstart-myst-markdown),
a variant of Markdown with several extensions, into books, articles, and websites.
Like other such tools, it can produce static output, such as PDF, docx, or HTML.
See [](#overview-build-process) for a conceptual overview.

However, for a developer it is important to understand that `mystmd` consists of two parts:

1. An engine that converts input documents into an AST (abstract syntax tree).
2. A renderer, that converts that AST into a given output format.

:::{seealso} Learn more about the AST
If the AST is unfamiliar, start with the [AST primer](xref:spec/ast-primer) for a short introduction to its structure.
:::

This model is equally applicable to exporting/converting static documents and rich web applications. Here's a workflow for static documents:

```{mermaid}
flowchart LR
  subgraph "<tt>myst build</tt>"
  myfile.md --> AST --> PDF
  end
```

Here's a workflow for producing a rich web application:

(diagram-app)=

```{mermaid}
flowchart TB
  subgraph "myst start --headless"
    subgraph "<b>Document conversion</b>"
    direction LR
    doc[folder_of/myfile.md] --> ast[AST]
    end
    subgraph "<b>Content server</b>"
    ast --> content_server[serve AST on http://localhost:3100]
    end
  end
  subgraph "bun run theme:book"
    subgraph "<b>Theme server</b>"
    direction LR
    theme_server[render themed content at http://localhost:3000] --> content_server
    user[User browser] --> theme_server
    end
  end
```

Walking through this last example, we see that invoking `myst start --headless` converts a set of input files into an AST, and serves the resulting AST via a content server.
The **theme server** is a React app that knows how to style data, which it pulls in from the content server.
The user interacts with the React app, which may trigger new fetches from the content server.
For what happens inside the engine at each stage of the build, see [](#api:pipeline).

## Project-specific concepts

`mystmd` is built on top of well known tools in the JavaScript ecosystem, such as [unist](https://github.com/syntax-tree/unist) from [unified](https://unifiedjs.com/), [mdast](https://github.com/syntax-tree/mdast), and [citation.js](https://citation.js.org/) for the `myst` CLI. The default MyST web themes use [React](https://reactjs.org/), [Remix](https://remix.run/) (potentially [`vite`](https://remix.run/docs/en/main/guides/vite) soon), and [Tailwind CSS](https://tailwindcss.com/) for the theme server.

If you are familiar with these tools, you should not find many surprises in the codebase.

That said, there are a couple of concepts used _only_ in this project, that won't be familiar. These are detailed below:

(develop-renderers-themes)=

### Concepts: Renderers, themes, and templates

In the diagram above, we saw that `mystmd` produces websites by:

- Parsing a set of documents to an AST.
- Transforming the AST into a resolved AST.
- Rendering the AST into components that can be used by a template or theme.
- Exporting into a final output by a template / theme.

This section describes a bit more how **Rendering** and **Exporting** work using **Themes** and **Templates**.

For an introduction to themes and templates, see [](#overview-themes). For a hands-on guide to building a web theme, read [](./theme-developer.md). In addition, below we'll define what a **Renderer** is:

```{glossary}
Renderer
: Converts MyST AST into components that {term}`themes` and {term}`templates` can use to export final outputs. For example, the [`myst-to-react` renderer](https://github.com/jupyter-book/myst-theme/tree/main/packages/myst-to-react) converts MyST AST into a number of React components that the [`book` and `article` React themes](https://github.com/jupyter-book/myst-theme/tree/main/themes) use to generate websites.
```

For example, in the case of the `book` theme, a MyST Document engine serves MyST AST via a Content Server, the [MyST React renderer](https://github.com/jupyter-book/myst-theme/tree/main/packages/myst-to-react) ingests that content and output React components, and the [book theme](https://github.com/jupyter-book/myst-theme/tree/main/themes/book) converts those components into HTML outputs.

#### Where to find renderers, themes, and templates

MyST has multiple renderers, themes, and templates that allow it to transform MyST AST into final output formats. The MyST team maintains a few that are worth noting:

- [`github.com/jupyter-book/mystmd`](https://github.com/jupyter-book/mystmd): Has several out-of-the-box renderers in addition to the core document engine.
  - A collection of Renderers, look for the [`myst-to-*` folders in `mystmd/packages`](https://github.com/jupyter-book/mystmd/tree/main/packages). These render MyST AST into components that themes can consume.
- [`github.com/jupyter-book/myst-theme`](https://github.com/jupyter-book/myst-theme): The core React-based renderer and theme.
  - A collection of [MyST Rendering Packages](https://github.com/jupyter-book/myst-theme/tree/main/packages) that define various React UI components for default MyST themes to use.
  - The [MyST React Renderer](https://github.com/jupyter-book/myst-theme/tree/main/packages/myst-to-react) generates React components out of MyST AST for use by the default MyST Themes. It provides a `<MyST />` component which can render MyST AST into a React tree.
  - The source code of the [default MyST Themes](https://github.com/jupyter-book/myst-theme/tree/main/themes), each of which use the React renderer. These themes are built and then published at the [`myst-templates` GitHub organization](https://github.com/myst-templates/book-theme) for consumption by users.
  - A React [context](https://react.dev/reference/react/useContext), named `ThemeContext` (defined [here in the `myst-theme` repository](https://github.com/jupyter-book/myst-theme/blob/main/packages/providers/src/theme.tsx)), is used to push state deeply into the tree, without having to pass it via props.
- [`myst-templates`](https://github.com/myst-templates): An index of templates that convert rendered components into final outputs. These are similar to _MyST Themes_, but follow a more standard "template" structure to produce static outputs.

:::{error} to do — explain rendering

- describe the render loop, and how render blocks are registered
- explain the ThemeProvider
- explain styling

:::

#### Example: Adding an "edit this page" button

Here's a brief example to illustrate a common development pattern.
Let's say we want to add a new button to each page of the MyST Theme that includes an "edit link" for the page.

To accomplish this, we need to make three contributions.

First, update [`jupyter-book/mystmd`](https://github.com/jupyter-book/mystmd), so that we can expose the "edit link" for each page as a new piece of metadata. [The main logic for adding the edit URL is here](https://github.com/jupyter-book/mystmd/pull/1804/files#diff-582c1df86d16945dd170ec211cedead020d37f750744946564f7483d08a1059bR27-R30).

Second, update the React theme infrastructure at [`jupyter-book/myst-theme`](https://github.com/jupyter-book/myst-theme/tree/main/themes). [Here's a pull request that implements this](https://github.com/jupyter-book/myst-theme/pull/577/files). Note how it:

1. [Defines a new React component called `<EditLink />`](https://github.com/jupyter-book/myst-theme/pull/577/files#diff-9f15761b56400d627876d6a1402c47f2e463590d010256066b64dc0475fd4e99R156-R174).
2. [Pulls the new edit URL metadata from the MyST AST](https://github.com/jupyter-book/myst-theme/pull/577/files#diff-9f15761b56400d627876d6a1402c47f2e463590d010256066b64dc0475fd4e99R248).
3. [Adds the new `<EditLink />` component to the `<FrontMatterBlock />` component](https://github.com/jupyter-book/myst-theme/pull/577/files#diff-9f15761b56400d627876d6a1402c47f2e463590d010256066b64dc0475fd4e99R299).
4. Because the book theme and the article theme _already use_ the `<FrontMatterBlock />`, they inherit this functionality automatically.

(develop:transforms)=

### Concepts: MyST Transformers

See [](#overview-transformers) for a higher-level overview of transforms.
This section provides a few concrete examples of how transforms modify the AST throughout the transforms process.

#### Example: Parsing an admonition

Let's say you've got MyST Markdown that defines an admonition, like this:

```{code} markdown
:filename: page1.md
:::{note} Here's an admonition
:::
```

The result of Parsing phase will be raw MyST AST (normally, this is `.json` but we'll show it in YAML so it is a bit more readable):

```{code} yaml
:filename: page1.json
- type: mystDirective
  name: note
  args: Here's an admonition
  children:
    - type: admonition
      kind: note
      children:
        - type: paragraph
          children:
            - type: text
              value: Here's an admonition
```

The AST simply encodes that there's a Directive present, with the name `note`.

After initial parsing, all **Directive** nodes are run, triggering the [Admonition Directive logic](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-directives/src/admonition.ts). This converts the `Directive Node` into an `Admonition Node`.

During the **transform** phase, the [Admonition Transforms](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-transforms/src/admonitions.ts) is applied to each Admonition node. These do things like double-check that the admonition has all the necessary information to be rendered.

The final output has more admonition-specific metadata defined, like `admonitionTitle`.

```{code} yaml
:filename: page1.json
- type: admonition
  kind: note
  children:
    - type: admonitionTitle
      children:
        - type: text
          value: Note
    - type: paragraph
      children:
        - type: text
          value: Here's an admonition
```

#### Example: Parsing a cross-reference

Let's say you have a page that labels some content, and cross-references it elsewhere on the page:

```{code} markdown
:filename: page1.md
(label)=
**A labeled paragraph**.

A reference to [my label](#label)
```

The initial parse of this page creates nodes where labels are present, and treats our markdown link syntax as a regular URL.

```{code} yaml
:filename: page1.json
- type: mystTarget
  label: label
- type: paragraph
  children:
    - type: strong
      children:
        - type: text
          value: A labeled paragraph
- type: paragraph
  children:
    - type: text
      value: 'A reference to '
    - type: link
      url: '#label'
      children:
        - type: text
          value: my label
```

During the **Transformations** phase, a number of [enumeration transforms](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-transforms/src/enumerate.ts) are run, including one that detects and resolves cross-reference links. At the end of these transforms, the AST now correctly encodes that we have a cross reference rather than a "normal" URL link. This can now be rendered into various output formats.

```{code} yaml
:filename: page1.json
- type: paragraph
  children:
    - type: strong
      children:
        - type: text
          value: A labeled paragraph
  label: label
  identifier: label
  html_id: label
- type: paragraph
  children:
    - type: text
      value: 'A reference to '
    - type: crossReference
      children:
        - type: text
          value: my label
      urlSource: '#label'
      identifier: label
      label: label
      kind: paragraph
      template: Paragraph
      resolved: true
      html_id: label
```

### Concepts: Frontmatter inheritance

Some frontmatter fields inherit from project-level config to individual pages.
This is controlled by the [`USE_PROJECT_FALLBACK` list](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-frontmatter/src/page/validators.ts).
To make a new field inherit from project to page, add its key to this list.

## Tools used in development

`mystmd` is built and developed using:

- [Bun](https://bun.sh), which provides a JavaScript runtime and package management;
- [TypeScript](https://www.typescriptlang.org/) for static type checking;
- [ESLint](https://eslint.org/) for code linting;
- [Prettier](https://prettier.io) for code formatting; and
- [Changesets](https://github.com/changesets/changesets) for versioning and changelogs.

```{note}
Below you will see several `bun run x` commands.
These are simply aliases for other commands, defined in the [`package.json` file](https://github.com/jupyter-book/mystmd/blob/main/package.json) under "scripts".
```

(developer:mystmd)=

## Local development: `mystmd`

The `mystmd` libraries and command line tools are written in [TypeScript](https://www.typescriptlang.org/), and require [Bun](https://bun.sh) for local development.

:::{warning} Don't use `mystmd-py` and the NPM installation at the same time
:class: dropdown

The [`mystmd-py` package](https://github.com/jupyter-book/mystmd/tree/main/packages/mystmd-py/src/mystmd_py) is a thin Python wrapper around the `mystmd` bundle that can be installed using `pip` or `conda`. If you have installed `mystmd` this way, uninstall it before using the local development instructions below.
:::

To do local development, [clone the repository](https://github.com/jupyter-book/mystmd):

```shell
git clone git@github.com:jupyter-book/mystmd.git
cd mystmd
```

Then, install dependencies via bun.
You need to do this each time you pull from upstream, since dependency versions may change:

```shell
bun install
```

Now, build `mystmd`:

```shell
bun run build
```

Optionally, you can link the built executable as your globally installed `mystmd`:

```shell
bun run link
```

These commands allow you to use the `myst` CLI from any directory; source code changes are picked up after each `bun run build` (executed in the top-level source directory).

```{warning} Windows users should use unix-like shells
The build process uses unix commands that might not work properly on Windows.
When building on Windows, use either WSL or a unix-like shell (such as Git Bash or MSYS2).
```

(local-docs-workflows)=

### Local docs workflows (preview/build)

To run a MyST server with your local changes and a preview of the documentation, run:

```shell
$ bun run docs
```

This builds the `mystmd` packages, and starts a live-reloading preview server.

The `docs/` plugins import several `myst-*` packages as `workspace:*` dependencies, so that they build against the source versions in this repository (not against npm). If you only change the plugins in `docs/*.mjs`, you will need to rebuild the packages and restart the server.

## Local development: myst-theme

The [`myst-theme` README](https://github.com/jupyter-book/myst-theme/) provides a more detailed overview of the components of that package.

There are two ways to deploy a theme (AKA React web app): as a server, or as a static build.
Development procedures are slightly different, depending on which approach you take.

### Approach 1: Theme server

Recall from the [architecture overview](#diagram-app) that `myst-theme` is a React web application. It provides theming, and requires a separate content server for data. When developing, the steps are therefore to:

1. Launch a content server
2. Launch the `myst-theme` web application server (this is what you browse to)
3. Run a process to monitor changes and rebuild `myst-theme`

#### Content server

We need some example data to test our theme against, such as [the example landing page](https://github.com/jupyter-book/example-landing-pages). Clone this example content repository and start the content server:

```shell
git clone https://github.com/jupyter-book/example-landing-pages
cd example-landing-pages
myst start --headless
```

The `--headless` flag tells `myst` not to start a theme server; we want to do that ourselves in the next step.

When you start a content server _without_ a theme server, you can still "visit" the pages in your site (often on port `3100`). If you do so, you will see raw JSON and images. These represent the AST that the _content server_ produces, and that a _theme server_ uses to render a website (in the next step).

#### myst-theme server

We now fire up the `myst-theme` React app. This app server fetches the AST `JSON` from the content-server, then converts it to HTML, and serves it to the client where it is [hydrated](<https://en.wikipedia.org/wiki/Hydration_(web_development)>).

First, clone [the `myst-theme` repository](https://github.com/jupyter-book/myst-theme/) and install dependencies:

```shell
git clone https://github.com/jupyter-book/myst-theme/
cd myst-theme
bun install
```

Then, see if you can build the package:

```shell
bun run build
```

After the build succeeds, launch the theme server:

```shell
bun run theme:book
```

After a while, it should tell you that the server has been started at http://localhost:3000. Browse there, and confirm that you can see the landing-page content.

Each time you change the myst-theme source, you must recompile by re-running `bun run build`. This allows you to preview the changes locally.

To automatically watch for changes and reload, use the following command:

```shell
bun run dev
```

Note that you can run `bun run dev` from within any folder if you'd like to watch individual packages instead of the entire directory structure.

### Approach 2: Static build

No content or theme server is required for a static site build. Steps are:

1. Build the theme for production
2. Point your site config to the built theme
3. Build the site statically

We'll use the mystmd docs site as an example.

Under the hood, `mystmd build --html` starts myst-theme as a local Remix server, fetches each route as HTML, writes the results to disk, and runs a small post-processing pass (see [`packages/myst-cli/src/build/html/index.ts`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-cli/src/build/html/index.ts)).

#### Build theme

To build a static site against a local theme, the theme must be built as it would be for production. For that we will use the "make" target
instead of `bun run`:

```{code} bash
cd myst-theme
make build-book # because mystmd docs site uses the book theme
```

That should produce a production ready version of the book theme under `.deploy/book`.

:::{tip}
While debugging, it helps to work with a theme built against the "development" version of React, which results in unminimized build artifacts (ie preserving whitespace and variable/function names) and more detailed React errors and warnings. For this, tell remix to run in node "development" mode:

```{code} json
:filename: myst-theme/themes/book/package.json
// Add NODE_ENV near the end of the "prod:build" script
                      v
"prod:build": "... && NODE_ENV=development remix build",
                      ^
```

:::

#### Configure site

Building a static site against a local theme requires configuring your site's `myst.yml` to point to the built theme's `template.yml`. Using the mystmd docs site as
an example:

```{code} yaml
:filename: mystmd/docs/myst.yml
site:
    # assuming your mystmd and myst-theme working directories are siblings
    template: ../../myst-theme/.deploy/book/template.yml
```

(NOTE: This is the _built_ template file, under `.deploy`, not the source template)

#### Build site

```{code} bash
cd mystmd/docs
mystmd build --html
```

Then host the static site locally. An easy way is with Python's built-in http server:

```{code} bash
cd _build/html
python3 -m http.server  # serves on port 8000 by default
```

Finally, browse the site at [http://localhost:8000](http://localhost:8000).

## Step Debugging

Sometimes the trusty `console.log` (aka print statement) is not sufficient for your debugging needs. In more involved situations, a proper step debugger can be your friend.
You may have used Firefox or Chrome developer tools to debug in-browser code by adding the `debugger` keyword into your javascript source.
But what about code that runs in node engine on the server?
Chrome and Firefox dev tools can _also_ debug server-side javascript. To do this, node must be invoked with the `--inspect`
or `--inspect-brk` comand-line option. That will cause the node process to open a socket listening for a debugger to connect. If "inspect-brk" is used
(vs "inspect"), then the process will immediately pause, awaiting a debugger connection. The `debugger` keyword in source will only pause the program if a
debugger is connected when that keyword is reached.

To connect to an awaiting node debug socket, enter into the browser address bar:

- Firefox: `about:debugging`, or
- Chrome: `chrome://inspect`

That opens a debugger control panel in the browser which should list your awaiting node process as available to connect to (if it has been correctly invoked).
(NOTE: other browsers and IDEs can also connect as debug inspectors - see Inspector Clients reference below)

In most cases we don't call `node` directly, so there is no easy way to add those options to a shell invocation.
Instead, a script can be defined with environment variable `NODE_OPTIONS=--inspect` (or "--inspect-brk") set in an appropriate spot (example follows).

### Debug myst-theme service

For example, to debug myst-theme's book theme running as a dynamic application server, alter the scripts like so:

```{code} json
:filename:  myst-theme/themes/book/package.json
// add NODE_OPTIONS
//                                                                                    v
"dev": "bun run dev:copy && bun run build:thebe && concurrently \"bun run dev:css\" \"NODE_OPTIONS=--inspect-brk remix dev\"",
```

Now remove the turbo "--parallel" option, because when turbo runs the theme server in "parallel" (ie multiprocess) mode, each process will attempt to open its own debug socket on the same port, with all but the first failing.
Then your debugger will only connect to the one that succeeded, with no guarantee any subsequent web request will hit the one process connected to the debugger.

```{code} json
:filename:  myst-theme/package.json
// remove the --parallel option
//                           v
"theme:book": "turbo run dev --filter='./themes/book'",
```

### Debug static myst-theme

To debug myst-theme running server-side in service of a static build:

**TBD**

### Debug a mystmd subpackage test suite

This requires a handful of options to be passed to vitest to ensure it runs in a single process. For example, to connect a step debugger to a running `myst-transforms` test:

```{code} json
:filename: mystmd/packages/myst-transforms/package.json
"test": "vitest --inspect-brk --pool threads --poolOptions.threads.singleThread --no-file-parallelism run",
```

### Debugging references

- [Node Inspector Clients](https://nodejs.org/en/learn/getting-started/debugging#inspector-clients)

## Infrastructure we run

(myst-api-server)=

### The MyST API server

We run a lightweight server at [`api.mystmd.org`](https://api.mystmd.org/) to help users resolve and download templates. The code for this exists at [the `myst-templates/templates` repository](https://github.com/myst-templates/templates).

For example, to get a list of template types (i.e. the available output types) you can `GET` this URL:

https://api.mystmd.org/templates

And to see a list of available templates that can be resolved for Typst, you can `GET` this URL:

https://api.mystmd.org/templates/typst

(howto:release)=
## How to make a release

Here are the basic steps to follow for any project:

1. [Coordinate the release with the team](#release:coordination).
2. Publish the release in the package repository for the tool. For example:
   - [How to publish a release of `mystmd`](#release:mystmd).
   - [How to publish a release of `myst-theme`](#release:myst-theme).
3. [Confirm that GitHub made a release](#release:github).
4. (optionally) [Create and share a blog post](#release:share).

(release:coordination)=
### Coordinating the release with the team

We use the [`#release_coordination`](https://discord.com/channels/1083088970059096114/1384242935645737141) Discord channel to coordinate and collaborate on releases.
This is a way to generate excitement and get any last-second work in before shipping.
It also gives others a heads-up that some new functionality is about to go live.

### Publish a release for the repository

When you publish a release, you upload a new version of the tool for package managers to use. The specifics depend on the toolchain for your package (in particular, it is different for Python vs. JavaScript tools). Here are a few specifics for the `mystmd` repository.

(release:mystmd)=
#### Publish a `mystmd` release to NPM, PyPI and Conda

`mystmd` is published to NPM via a GitHub Action. Here's how to publish a release.

- **Find the changesets PR**. This contains a list of the version updates that will be included with this release. [Here's an example of a release PR](https://github.com/jupyter-book/mystmd/pull/1896).
- Review the changeset PR.
  - Ensure that either `mystmd` or `myst-cli` is in the changesets.
    Or, ensure you are intentionally **not** releasing `mystmd` (this generally shouldn't happen), in which case the python and release notes are expected to fail.
    See [](#changesets:myst-cli) for more explanation.
  - Ensure that private or non-existent packages like docs, etc. are not in the changesets (these will cause an early failure)
  - Ensure that there are no **new** myst packages that need to be published (see [](#release:new-package))
- **Merge the changesets PR**. After merging that PR, [this GitHub action will make a release](https://github.com/jupyter-book/mystmd/blob/main/.github/workflows/release.yml).
  - It calls `bun run version` to generate the changelog (to review the changelog, you can run that command locally too).
  - It then publishes the updated packages to the [`mystmd` npm registry](https://www.npmjs.com/package/mystmd) (it calls `bun run publish:ci`, which calls `changeset publish`).
  - It creates multiple git version tags (which you'll use in making the GitHub release).
  - It releases to PyPI
  - The release notes are created automatically based on the `mystmd@v...` tag
- Confirm that NPM, PyPI versions are released and a GitHub release has been made. Once this happens and there are no errors, you're done!
- A short time later, a Conda PR is opened automatically and needs to be merged.

#### Fixing errors during a release

Ask for help in the [`#release_coordination` Discord channel](https://discord.com/channels/1083088970059096114/1384242935645737141). The exact fix will depend where in the automated release things broke. Some tips:

- In general, do not revert a release PR, instead fix the errors (permissions, etc. with NPM/tokens) and merge any necessary fixes to `main`.
- A `mystmd` tag at the right version is necessary for the release notes to run
- A PyPI release is only triggered if there is a release triggered by NPM
- Partial NPM releases (e.g. due to permission failures or token access) can be rerun **without** a new changeset. In this case you can:
  - update the token/connection and rerun the action
  - fix a `package.json` (e.g. add a git trusted publisher), merge to main, and add a tag for `mystmd` (`git tag mystmd@M.m.p`, for the release notes) if that package isn't being re-released
- A new NPM package has been created but not created or linked:
  - Create the package, add `ebp-bot` to it, setup trusted publishing in NPM.

(release:new-package)=
#### Publishing a new NPM package for the first time

If a PR introduces a new package, you must publish it to NPM manually before merging the changesets PR.
For example, [PR #2602](https://github.com/jupyter-book/mystmd/pull/2602) and its [myst-theme counterpart](https://github.com/jupyter-book/myst-theme/pull/795) added the new `anywidget` package.

Before proceeding, ask about this in [`#release_coordination` Discord channel](https://discord.com/channels/1083088970059096114/1384242935645737141) and ensure that we are (a) about to make a release; and (b) there are no last-minute changes to the package name. Creating a new NPM package cannot be undone and packages cannot be renamed.

Steps to publish a new package:

1. **Build and test the package** to confirm it works as expected.
2. **Set the version to `0.0.0`** in the package's `package.json`. Changesets will overwrite this on the first automated release.
3. **Publish the package** manually with public access:
   ```shell
   npm publish --access=public
   ```
4. **Set up [trusted publishing](https://docs.npmjs.com/trusted-publishers)** in the NPM admin so that GitHub Actions can publish future releases automatically.
5. **Add `ebp-bot` as a maintainer** on the NPM package page. This is not needed if the package belongs to a team (e.g., `@myst-theme`).
6. **Announce the new package** in the [`#release_coordination` Discord channel](https://discord.com/channels/1083088970059096114/1384242935645737141) so the team is aware and comment on the relevant GitHub Release PR that this package has been created.

(release:myst-theme)=
#### Publish a release of `myst-theme`

The process for releasing `myst-theme` infrastructure is similar to the release process for `mystmd`. Here's a brief overview:

- **Find the changesets PR** in `myst-theme`, similar to [the `mystmd` release process](#release:mystmd).
  [Here's an example PR in `myst-theme`](https://github.com/jupyter-book/myst-theme/pull/574).
- **Merge the changesets PR**. This will trigger the release process by running our release action.
- **Check the GitHub Workflow to see if it completes**. Go to the [`myst-theme` workflows page](https://github.com/jupyter-book/myst-theme/actions) to track its progress.
  - The action will build the latest version of the theme infrastructure.
  - It updates the template files in the [`myst-templates` GitHub organization](https://github.com/myst-templates).
  - [Here are the lines that update this template](https://github.com/jupyter-book/myst-theme/blob/8283e4505fdb418355ca25ae114ba7bea3cec956/.github/workflows/release.yml#L39-L50).
  - [Here's an example run of this workflow](https://github.com/jupyter-book/myst-theme/actions/runs/15005221275).
- Confirm that a GitHub release has been made. Once this happens and there are no errors, you're done!

(release:github)=
### Automated releases on GitHub

After a successful NPM release, our [`release.yml` workflow](https://github.com/jupyter-book/mystmd/blob/main/.github/workflows/publish-github-release.yml) will automatically create a new GitHub Release.
The release notes are generated using [`github-activity`](https://github.com/cheukting/github-activity) and include a summary of all merged PRs and commits since the previous release.

**Maintainers are encouraged to review the new GitHub Release and edit the description as needed.**
For example, you may want to add an executive summary, highlight important changes, or clarify upgrade instructions for users.

You can find the latest releases at: https://github.com/jupyter-book/mystmd/releases

(release:docs)=
### Update documentation

**For tools hosted at mystmd.org**: when we make a release of `mystmd`, the MyST documentation is automatically updated via [this GitHub Workflow](https://github.com/jupyter-book/mystmd/blob/main/.github/workflows/docs.yml). You can also trigger a manual release by following [](#docs:update-mystmd.org).

**For most other tools**, the documentation should auto-update with new releases (e.g., via a GitHub action).

(release:share)=
### Create and share a blog post

Feel free to use the blog to post release notes as well.
This should be as simple and quick as possible, don't over-think it. Here are some simple steps:

1. Copy and paste the [release notes you generated](#release:notes) into a new file [on our blog repository](https://github.com/jupyter-book/blog).
2. Use the following YAML header metadata for the post:

   ```yaml
   ---
   date: <release-date>
   author: The Jupyter Book Team
   title: <title from GitHub release>
   tags: release
   ---

   <content from GitHub release>
   ```
3. Self-merge the blog post.

Feel free to celebrate new releases and share the news publicly so that others know about new enhancements in our projects.

**Spaces to publicize releases**. Here are a few places that are worth sharing (you can just copy/paste the same text into each):

- [The MyST Discord](https://discord.mystmd.org/)
- [The Jupyter Zulip Forum](https://https://jupyter.zulipchat.com)
- [The Jupyter Discourse](https://discourse.jupyter.org)
- Social media spaces of your choosing.

## Practices we follow

### Build system

We use [Turbo](https://turborepo.com/) to manage our testing and build system.

(developer:testing)=

### Testing

We use [vitest](https://vitest.dev/guide/) for all tests in `mystmd`.

#### How to run the test suite

First [install `mystmd` locally](#developer:mystmd).

Then, run the test suite using:

```shell
bun run test
```

If you are working in a particular package, change your working directory to that specific package, and run the tests there.

```shell
cd packages/myst-cli
bun run test
```

To run in "watch mode" (runs each time a change is saved), use:

```shell
bun run test:watch
```

To run a single test by matching its title, first change the working directory to the package where the test exists. For example:

```shell
cd packages/mystmd
```

Then run the test command like so:

```shell
bun run test -- -t "Basic tex build"
```

For integration test titles, see `packages/mystmd/tests/exports.yml`.

#### Types of tests

There are two types of tests in the `mystmd` repository:

**Unit Tests** - are attached to each sub-package in the `packages/` directory. These use [`vitest`](https://vitest.dev/) for basic functionality within each package. They have files like [`config.spec.ts`](https://github.com/jupyter-book/mystmd/blob/main/packages/myst-cli/src/config.spec.ts).

**Integration Tests** - Test the entire `mystmd` build workflow. Here's how it works:

- `packages/mystmd/tests/endToEnd.spec.ts` runs a build from end to end, similar to the `vitest` tests above.
- `packages/mystmd/tests/exports.yml` contains several integration tests - each one points to a build configuration (a folder in `packages/mystmd/tests/`) and compares expected to generated outputs.

### Linting

When contributing code, continuous integration will run linting and formatting on your pull request.
You can also run `bun run lint` and `bun run lint:format` locally to catch errors early. To automate that process for each commit, install the git pre-commit hook: `bun run install-pre-commit`.[^uninstall-pre-commit]
If you are using the VSCode editor, it can be setup to show changes in real time and fix formatting issues on save (extensions: [eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) and [prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)).

[^uninstall-pre-commit]: Uninstall the pre-commit hook with `git config --unset core.hooksPath`.

Running in live-changes mode: depending on the package you are working in we have also setup live changes which can be faster than the `bun run build`; this can be run using `bun run dev`. If your changes aren't showing up, use `bun run build` as normal.

### Versioning and changesets

We use [changesets](https://github.com/changesets/changesets) for tracking changes to packages and updating versions.
To learn about changesets, see [this introductory guide to changesets](https://github.com/changesets/changesets/blob/main/docs/intro-to-using-changesets.md).
We use this [`changesets` GitHub Action](https://github.com/changesets/action) when we publish a release.

Before submitting your Pull Request, please add a changeset using `bun run changeset`, which will ask you questions about the package and ask for a brief description of the change.
Commit the changeset file to the repository as a part of your pull request.
You can use `bun run version` to preview the generated changelog.

Our current versioning procedure is a little loose compared to strict semantic versioning; as `mystmd` continues to mature, this policy may need to be updated.
For now, we try to abide by the following rules for version bumps:

- **major**: Backward incompatible change to the underlying supported MyST data. These would be cases where a non-developer MyST user's project or site built with major version _N_ would not work with major version _N+1_. Currently, we never intentionally make these changes.
- **minor**: Backward incompatible change to the JavaScript API, for example, changing the call signature or deleting an exported function. These can be a headache for developers consuming MyST libraries, but they do not break MyST content.
- **patch**: For now, everything else is a patch: bug fixes, new features, refactors. This means some patch releases have a huge, positive impact on users and other patch releases are basically invisible.

(changesets:myst-cli)=
#### What if changesets doesn't bump `mystmd` or `myst-cli`?

The auto-generated changesets release PR must list at least one changeset that bumps `mystmd` or `myst-cli`, or its CI will fail.
This is because we *almost always* want to release a new `mystmd` on merge, which only happens if one of these is bumped.

If you merge the changesets PR when neither is bumped, the release job of `mystmd-py` to PyPI will fail, and a GitHub release won't be made for the repository.
The packages that we _did update_ will still be uploaded to NPM.
Here's an example of this happening: [mystmd#2857](https://github.com/jupyter-book/mystmd/issues/2857).

**You can still merge the Changesets PR if you want!**
If you intentionally don't want a `mystmd` bump on this release, override the failing check and merge the release PR anyway.
NPM still publishes everything else, and the PyPI and GitHub release jobs are an expected failure with nothing to fix afterwards.

## Packages in the mystmd repository

All packages used to build `mystmd` live in the [https://github.com/jupyter-book/mystmd](https://github.com/jupyter-book/mystmd) repository.

```{note}
`myst-theme` is *not* part of the `mystmd` package, and lives at https://github.com/jupyter-book/myst-theme.
```

These packages are [ESM modules](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c)[^ESM], written in [TypeScript](https://www.typescriptlang.org/), and live at https://github.com/jupyter-book/mystmd/tree/main/packages.

[^ESM]: ESM modules are imported using the JavaScript `import` syntax, and cannot be used with CommonJS `require()`.

**Command Line Tools:**

- `mystmd`: provides CLI functionality for `myst start`.
- `mystmd-py`: a Python wrapper around `mystmd`, which makes it easy to install the tool in a Python environment. It should not be used for development.

**Core Packages:**

- `myst-cli`: provides CLI functionality for `mystmd`. It does not export the CLI directly.
- `jtex`: a templating library ([see docs](https://mystmd.org/jtex)).
- `myst-frontmatter`: definitions and validation for scientific authorship/affiliation frontmatter ([see docs](https://mystmd.org/guide/frontmatter)).
- `myst-config`: validation and reading of configuration files.
- `myst-templates`: types and validation for templates (LaTeX, web, and word).

**Markdown Parsing**

MyST parsing builds on the [markdown-it](https://github.com/markdown-it/markdown-it) parser.
`markdown-it` handles "standard" syntax (paragraphs, bold, links, etc), and `markdown-it-myst` adds rules for MyST-specific syntax (e.g., roles and directives).
The MyST engine first uses `markdown-it` to parse raw text into tokens, and then `myst-parser` converts them into the MyST AST (using [mdast](https://github.com/syntax-tree/mdast)).

- `markdown-it-myst`: markdown-it plugin to handle tokenizing roles and directives.
- `myst-directives`: core directives for MyST.
- `myst-roles`: core roles for MyST.
- `myst-parser`: converts the markdown-it token stream to MyST AST.

**Readers**

- `tex-to-myst`: convert LaTeX to MyST AST.
- `jats-to-myst`: convert JATS XML, a standard for representing papers, to MyST AST.

**Transformers**

- `myst-transforms`: transformations for use with MyST AST to transform, e.g., links, citations, cross-references, and admonitions (see here for more [information](#develop:transforms)).

**Export Tools**

- `myst-to-docx`: convert MyST documents to MS Word format.
- `myst-to-jats`: convert MyST to JATS, for use in scientific archives.
- `myst-to-tex`: convert MyST to LaTeX, to be used in combination with our [jtex](https://mystmd.org/jtex) template compiler, to create stand alone LaTeX documents.
- `myst-to-html`: convert MyST to HTML.

**Extensions:**

- `myst-ext-card`: Card directives.
- `myst-ext-grid`: Grid directives.
- `myst-ext-tabs`: Tab directives.
- `myst-ext-reactive`: Reactive directives.

**Miscellaneous:**

- `myst-common`: common utilities for working with ASTs.
- `myst-spec`: JSON Schema that defines the MyST AST.
- `myst-spec-ext`: temporary development extensions to `myst-spec`.
- `citation-js-utils`: utility functions to deal with citations.
- `myst-cli-utils`: shared utils between jtex, and myst-cli.
- `simple-validators`: validation utilities, that print all sorts of nice warnings.

## Tips and tricks

### Grepping the codebase

While developing, there are a lot of build artifacts lying around,
making grepping the code harder than it needs to be. Assuming you
have
[ripgrep](https://github.com/BurntSushi/ripgrep?tab=readme-ov-file#installation)
or a compatible alternative installed, you can define a customized
"myst grep" in your shell config (`~/.zshrc`, `~/.bashrc`, etc.):

```sh
alias mg="rg --exclude-dir=build --exclude-dir=_build -g '!*.js' -g '!tailwind.css'"
```

Most notably, this excludes `.js` files, which are generated from TypeScript.

---

### Diagrams (`docs/diagrams.md`)

---
title: Diagrams
description: Include simple programmatic mermaid diagrams in your documents.
thumbnail: ./thumbnails/diagrams.png
---

It is possible to add [mermaid diagrams](https://mermaid-js.github.io/mermaid) using the {myst:directive}`mermaid` directive, for example:

````{myst}
```{mermaid}
flowchart LR
  A[Jupyter Notebook] --> C
  B[MyST Markdown] --> C
  C(mystmd) --> D{AST}
  D <--> E[LaTeX]
  E --> F[PDF]
  D --> G[Word]
  D --> H[React]
  D --> I[HTML]
  D <--> J[JATS]
```
````

:::{note}
Both GitHub and JupyterLab ([#101](https://github.com/jupyter/enhancement-proposals/pull/101)) support the translation of a code-block ` ```mermaid ` to a mermaid diagram directly, this can also be used by default in MyST.
:::

---

### Directives (`docs/directives.md`)

---
title: Directives
description: A full list of the directives included in MyST Markdown by default.
label: directives_list
---

To learn more about the syntax and usage of the directives, please refer to the [](#syntax:directives) section of the documentation.

:::{myst:directive} admonition
:::

:::{myst:directive} aside
:::

:::{myst:directive} bibliography
:::

:::{myst:directive} blockquote
:::

:::{myst:directive} code
:::

:::{myst:directive} code-cell
:::

:::{myst:directive} csv-table
:::

:::{myst:directive} dropdown
:::

:::{myst:directive} embed
:::

:::{myst:directive} figure
:::

:::{myst:directive} glossary
:::

:::{myst:directive} iframe
:::

:::{myst:directive} image
:::

:::{myst:directive} include
:::

:::{myst:directive} list-table
:::

:::{myst:directive} math
:::

:::{myst:directive} mdast
:::

:::{myst:directive} mermaid
:::

:::{myst:directive} myst
:::

:::{myst:directive} table
:::

:::{myst:directive} toc
:::

---

### Document Parts (`docs/document-parts.md`)

---
title: Document Parts
description: Parts allow you to specify special parts of your document, like abstract, key points, and acknowledgements.
---

Document *parts* allow you to add content and metadata for specific components of your page or project, including `example`, `abstract`, `dedication`, and `acknowledgment`. [Templates](./documents-exports.md) may use the parts and their metadata, and render such content in various locations.

## Add document parts

Document parts can be used in any export media (`html`, `pdf`, etc).
There are several ways you can define document parts, each described below:

1. [In project-level configuration](#parts:project)
2. [In page frontmatter](#parts:frontmatter)
3. [With a content block](#parts:blocks)
4. [With specific section headings](#parts:implicit)
5. [With Jupyter Notebook cell tags](#parts:cell-tags)

(parts:project)=

### Parts in `myst.yml` Project configuration

You may also specify `parts` in the project configuration of your `myst.yml` file. These are defined exactly the same as [`parts` defined in page frontmatter](#parts:frontmatter).

```yaml
version: 1
project:
  abstract:  |
    This is a multi-line
    abstract, with _markdown_!
  parts:
    special_part: |
      This is another _special_ part!
```

Project-level `parts` are useful, for example, if you have an abstract, acknowledgments, or other part that applies to your entire project and doesn't make sense attached to an individual page.

```{caution}
Project-level `parts` are a new feature and may not yet be respected by your chosen MyST template or export format. If the project `part` is not behaving as you expect, try moving it to page frontmatter for now.
```

(parts:frontmatter)=

### Parts in Frontmatter

On any page, you can add a part to your document directly in the frontmatter, for example, the `abstract`:

```yaml
---
title: My document
abstract: |
  This is a multi-line
  abstract, with _markdown_!
---
```

You may also write your part in a separate file, and point to that file from the frontmatter, for example:

```yaml
---
title: My document
abstract: ../abstract.md
---
```

(parts:blocks)=

### Parts with content blocks

You can use [content blocks](./blocks.md) in a page to define a part. This will be parsed differently from the other content on the page for re-use in templates and websites.

The following example shows how to define an _abstract_ part in a content block on a page.

```{code} markdown
:filename: mypage.md

# Page title

+++ { "part": "abstract" }

This is my abstract block.

+++

Page content

```

(parts:implicit)=

### Parts with specific header titles

If you are rendering your project in other places, it can be helpful to leave these sections directly in the document.
Complete this using a header as usual:

```
# Abstract

This is my abstract!
```

Note that frontmatter parts and explicitly tagged cells/blocks will take precedence over this method. Themes may choose to only pick up a subset of implicit parts, for example, only an `Abstract` and not `Summary` as summary section can be used in other contexts.

(parts:cell-tags)=

### Parts with Jupyter cell tags

When using a Jupyter Notebook, you can add a `tag` to the cell with the part name. If multiple cells share that tag, they will be extracted and merged. 

### Known Document Parts

The known parts that are recognized as _top-level_ document parts keys are:

abstract
: A concise overview of the entire document, highlighting the main objectives, methods, results, and conclusions. It's meant to give readers a quick snapshot of what to expect without having to read the entire document.

summary
: Similar to an abstract, but can either be slightly longer and more detailed or used as a plain-language summary, depending on the context. It summarizes the document's content, including the background, purpose, methodology, results, and conclusions.
: Alias: `plain_language_summary`, `lay_summary`

keypoints
: A brief list that highlights the main findings, conclusions, or contributions of the document. Key points are often used to quickly convey the core message or most important aspects to the reader.

dedication
: A short section where the author dedicates the document to someone, often as a gesture of honor or respect.

epigraph
: A quote or poem that the author includes at the beginning of the document to set a tone or theme, or to hint at the document’s underlying message. It is often relevant to the content but not directly related to it.
: Alias: `quote`

data_availability
: A statement or section that details how readers can access the data sets and resources used in the document. This can include links to repositories, conditions for access, and any restrictions on the data. It's crucial for transparency and reproducibility in research documents.
: Alias: `availability`

acknowledgments
: A section where the author thanks individuals, organizations, or agencies that contributed to the completion of the document. This can include support in the form of funding, expertise, feedback, or moral support.
: Alias: `ack`, `acknowledgements`

### Custom Frontmatter Parts

If you have a custom part name for a template, you can nest it under `parts:`, which takes arbitrary keys.

```yaml
---
title: My document
parts:
  special_part: |
    This is another _special_ part!
---
```

The advantage of this method is that the content is not rendered in your document.

(parts:site)=

## Add website parts

[Website themes](./website-templates.md) have additional parts because they render user interface elements that are not part of a standard "document" structure. These are theme-dependent: for example, the [default myst themes](#default-web-themes) support a [`footer` part](#navigation:footer) and [`banner` part](#navigation:banner).

Specify the content of a site `part` in the `site.parts` key of the `myst.yml` configuration file:

```{code} yaml
:filename: myst.yml
version: 1
site:
  template: ...
  parts:
    footer: |
      (c) MyST Markdown
    banner: My banner [content](https://mystmd.org)!
  ...
```

Alternatively, you may specify a path to a file that contains the part content:

```{code} yaml
:filename: myst.yml
version: 1
site:
  template: ...
  parts:
    footer: parts/myfooter.md
    banner: _site/banner.md
  ...
```

You can also specify a URL to a remote markdown file:

```{code} yaml
:filename: myst.yml
version: 1
site:
  template: ...
  parts:
    footer: https://example.com/shared-footer.md
  ...
```

Content in parts will generally be parsed similarly to other MyST content (though some functionality like code execution will not work).

### Share the same part across multiple sites

If you wish to share the same part across multiple sites, use the [`extends:` key to compose multiple configuration files](#composing-myst-yml). This lets you define the part in one location, and re-use it in several others. It is useful if you want to standardize website components like a footer across many websites.

For example, in one file:

```{code} yaml
:filename: parts.yml
site:
  parts:
    footer: |
      My nifty footer!
  ...
```

And in another:

```{code} yaml
:filename: myst.yml
version: 1
extends: parts.yml
site:
  template: ...
```

**If you're extending configuration from a remote source**, make sure that you use absolute URLs if you must refer to an image or other asset in your part content. Relative paths that are defined inside the part content will generally break.

:::{seealso} Referring to parts directly with a URL is coming
See the [issue tracking this enhancement](https://github.com/jupyter-book/mystmd/issues/2127).
:::


(parts-ast)=
## How parts appear in the AST

Each way of defining a part lands in a different place in the JSON that `myst build` emits.
This section describes how these are represented in the AST.
See [](xref:spec) for more details about the MyST AST.

### Page-level parts in the page AST

There are three ways to mark a region as a named part in a document.
Each one ends up in a different place in the served JSON, even though they are often treated the same in the rendered output (see [](#ast-parse-helper) for guidance in parsing them).
We show each method below, and where it lands in the AST:

````{list-table}
- - Method
  - Example
  - Location in AST
- - **Page frontmatter** (in the `parts:` key)
  - ```markdown
    ---
    parts:
     acknowledgments: "..."
     abstract: "My abstract"
    ---
    My content...
    ```
  - Stored in the page frontmatter key:
  
    `frontmatter.parts.<partname>.mdast`.
- - **Block metadata** (within content of a page)
  - ```markdown
    +++ {"part": "abstract"}

    My abstract content.

    +++

    My content

    +++ {"part": "acknowledgements"}
    Thanks to ...
    ```
  - Stored in a `block` node inside `mdast` with `data.part` set.

    `.mdast.children.<block>.data.part = "acknowledgements"`
- - **Heading auto-match** (heading text equals a known part name)
  - ```markdown
    ## Abstract

    My abstract ...

    ## Header one

    A normal (non-part) header

    ## Acknowledgments

    Thanks to ...
    ```
  - Remains a regular `heading` + paragraphs sequence.
    Only becomes a part block when [`extractPart()`](#ast-parse-helper) is called.
````

### Site-level parts in the project AST

Site-level `parts:` (under `site:` in `myst.yml`) is a different `mystmd`-specific system for content shared across pages (like a project footer or header).
These are project-level and not part of any page's AST.
The [theme developer guide](./theme-developer.md) covers the rest of what mystmd serves alongside per-page JSON.

(ast-parse-helper)=
### Programmatically extract a part from an AST

Instead of manually parsing the page AST for these parts, use the [`extractPart()`](https://github.com/jupyter-book/mystmd/blob/0d626b198093fa740125d02267a111d84547fd36/packages/myst-common/src/extractParts.ts) helper to retrieve a named part regardless of how it was defined.

For example, exporters like [`myst-to-jats`](https://github.com/jupyter-book/mystmd/blob/0d626b198093fa740125d02267a111d84547fd36/packages/myst-to-jats/src/index.ts#L720-L729) call `extractPart()` to pull these regions into their output.

---

### Documents Exports (`docs/documents-exports.md`)

---
title: Exporting overview
description: Create an export for PDF, LaTeX, Typst, Docx, JATS, or CITATION.cff in your page or project frontmatter, and use `myst build` to build the export.
---

You can export MyST content into one or more static documents, and optionally bundle them with a MyST website. This section gives an overview of the Exporting process and major configuration options.

(types-of-exports)=
## List of formats you can export

Below are supported export types and links to documentation for further reading:

```{list-table} Frontmatter Export Formats
:header-rows: 1
:label: table-export-docs
- * Export type
  * Learn more
- * `pdf`
  * [](./creating-pdf-documents.md)
- * `tex`
  * [](./creating-pdf-documents.md)
- * `typst`
  * [](./creating-pdf-documents.md)
- * `JATS`
  * [](./creating-jats-xml.md)
- * `Microsoft Word`
  * [](./creating-word-documents.md)
- * `CITATION.cff`
  * [](./creating-citation-cff.md)
- * `MyST Markdown`
  * [](#export:myst)
```

## Where to configure options for exports

You can configure export options in two different places:

(exports-page-frontmatter)=
**In page frontmatter**:

```{code-block} yaml
:filename: my-markdown-file.md
---
title: My PDF
exports:
  - format: pdf
    template: arxiv_two_column
    output: exports/my-document.pdf
---
```

**In your `myst.yml` configuration**. In this case you will need to specify the `article` (or `articles`) that you are targeting. For example, here's how you'd configure an export from a single-page document.

```{code-block} yaml
:filename: myst.yml
version: 1
project:
  exports:
    - format: pdf
      template: arxiv_two_column
      article: my-markdown-file.md
      output: exports/my-document.pdf
```

(articles-or-article)=
:::{note} You can use either `article:` or `articles:`
MyST will let you use either one of these options, to make the `myst.yml` configuration more readable.
:::


## Configuration options for exports

There are a few options you can use to configure exports:

```{list-table}
- - Option
  - Description
- - `format`
  - The type of export you'll create. For examples, see [](#types-of-exports).
- - `template`
  - The template to use for the export. For more information, see [](#export-templates).
- - `output`
  - The output file to be created.
- - `id`
  - A unique identified for the output, in case you want to [re-use exports later](#reuse-export-outputs).
- - `articles`
  - One or more source files to use in the export (you can [use `article` as well](#articles-or-article)). If using [page frontmatter](#exports-page-frontmatter), it will default to the current document.
- - `toc`
  - If exporting from a multi-page book, the [Table of Contents](./table-of-contents.md) that defines the book structure.
```

(export-templates)=
## Choose a template

The exporting process uses a **MyST Template** [MyST Template](https://github.com/myst-templates) to transform the {term}`MyST AST` into an output format. MyST Templates are written for a specific export `format`. A MyST Renderer converts MyST AST into components that a template can use to export a final output.

You can choose the template for a given export format with the `template` argument.
There are several template names you can use out of the box[^api-server].
For a list of community templates you can use, see [the MyST Templates table](https://github.com/myst-templates#templates) in the [`myst-templates`] GitHub organization.

[^api-server]: These are resolved by the [MyST API server](#myst-api-server).

You can also use a **URL** or a **local path** that points directly to a template. For example:

```yaml
- format: typst
  id: typstpdf
  template: https://github.com/rowanc1/typst-book.git
  articles:
    - page1.md
    - page2.md
  output: ./_build/pdf/typst-report.pdf
```

### The `myst-templates` GitHub organization

The [`myst-templates` GitHub organization](https://github.com/myst-templates) has a collection of MyST templates that are contributed and maintained by the community. These templates are made easily-consumable by MyST users [via the MyST API service](https://api.mystmd.org), see [](#myst-api-server) for technical details.

## Build one or more exports

After defining `exports` in your frontmatter, you may build them with the `myst build` command, by default this only builds the site.
You can configure the CLI command in a number of ways:

`myst build --all`
: Build all exports in the project

`myst build --pdf --docx`
: Build `pdf` (LaTeX or Typst) exports and `docx` in the project

`myst build my-paper.md`
: Build all exports in a specific page

`myst build my-paper.md --pdf`
: Build all `pdf` exports in a specific page

(reuse-export-outputs)=
## Re-use export outputs for download buttons

You can re-use exported artifacts by setting an `id:` in your export configuration.
Then, reference that ID in [your `downloads:` configuration](#download-link).

## Export Configuration

The following table shows the available properties for each export. You must define at least one of `format`, `output`, or `template` for MyST to be able to perform your output. You may also specify a string instead of a full export object; this string will be inferred to be either the export format or the output filename. The table below is from [](#frontmatter:exports).



```{seealso} Exposing Exports as Downloads
You can also include exported documents as downloads in your site, see [](./website-downloads.md).
```

## Split your document across multiple content files

When writing longer documents like manuscripts, it's common to write your document in multiple parts and then stitch them together into a single narrative.
You can accomplish this in MyST with the {myst:directive}`include` directive.

See [](#docs:include) for more information.

(export:myst)=

## Export MyST Markdown from another document format

MyST can parse some non-MyST document formats as well.
This makes it possible to convert something _into MyST Markdown_.

For example, to convert LaTeX into MyST Markdown, use the following command:

```
myst build doc.tex --md
```

---

### Dropdowns Cards And Tabs (`docs/dropdowns-cards-and-tabs.md`)

---
title: Dropdowns, Grids, Tabs and Cards
short_title: Grids, Tabs & Cards
description: Add advanced user-interface elements to your MyST documents with grids, cards, tabs, and dropdowns.
thumbnail: ./thumbnails/dropdowns-cards-and-tabs.png
---

(dropdowns)=

## Dropdowns

Dropdowns can be used to toggle content and show it only when a user clicks on the header panel. These use the standard HTML `<details>` element, meaning they also will work without JavaScript. The dropdown can have a title, as the directive argument, and the open option can be used to initialise the dropdown in the open state.

```{myst}
:::{dropdown} Dropdown Title
:open:
Dropdown content
:::
```

```{seealso}
:class: dropdown

# Use "Admonition Dropdowns" for style!
You can also hide the body of your admonition blocks so that users must click a button to reveal their content. This is helpful if you’d like to include some text that isn’t immediately visible to the user.

To turn an admonition into a dropdown, add the option `:class: dropdown` to them. See [](#admonition-dropdown) for more information.
```

## Cards

Cards provide an easy way for you to content into a standard “header”, “body”, “footer” structure that has a similar alignment and visual style. It is useful for creating galleries or high-visibility collections of links and information.
For example, a card with a header, title, body, and footer:

````{myst}
```{card} Card title
:header: The _Header_
:footer: Footer

Card content
```
````

You can also add a `link` option to the card, which will allow you to make the entire card clickable:

```{myst}

:::{card} Clickable Card
:link: https://mystmd.org

The entire card can be clicked to navigate to `mystmd.org`.
:::
```

````{note} Compatibility with Sphinx design
:class: dropdown

In the [Sphinx design project](https://sphinx-design.readthedocs.io/en/latest/cards.html) card headers and footers take a special syntax:

- A card `title`: The argument given to the directive.
- A card `header`: Any content that precedes a line with ^^^.
- A card `footer`: Any content that comes after a line with +++.
- A card `body`: Any content that comes in between ^^^ and +++.

This syntax is supported in `mystmd`, for example:

```markdown
:::{card} Card Title
Header
^^^
Card content
+++
Footer
:::
```

Note that, card headers and footers are optional. If you don’t include ^^^ or +++ in your card, they will not show up.
````

:::{myst:directive} card
:::

(ui:buttons)=
## Buttons

A button is an element with text content that triggers an action to navigate to an internal or external reference upon a user click. Use the {myst:role}`button` role followed by the text content and target path to create a button.

```{myst}
{button}`MyST Role Spec <roles.md>`
```

```{myst}
{button}`MyST-MD GitHub <https://github.com/jupyter-book/mystmd>`
```

```{myst}
{button}`A button without a link!`
```

(grids)=
## Grids

Grids allow you to structure arbitrary chunks of content in a grid-like system.

To generate a grid, use the `:::{grid} ...` wrapper directive along with `:::{grid-item}` or `:::{card}` directives inside.

The numbers supplied in the argument are column counts to be used on different screen sizes e.g. `1 1 2 3` corresponding to smallest (<768px), medium (768px – 1024px), large (1024px – 1280px), and extra-large screens (>1280px). These pixel widths are determined by the theme (e.g. the book theme), which uses the default Tailwind CSS breakpoints.

Example with grid-items:

```{myst}
::::{grid} 1 1 12 12

:::{grid-item}
:columns: 3
This is one sentence. It occupies the narrower column.
:::

:::{grid-item}
:columns: 9
This is another longer sentence which requires more space. It occupies the wider column.
:::

::::
```

Example with cards:

```{myst}
::::{grid} 1 1 2 3

:::{card}
:header: Text content ✏️
Structure books with text files and Jupyter Notebooks with minimal configuration.
:::

:::{card}
:header: MyST Markdown ✨
Write MyST Markdown to create enriched documents with publication-quality features.
:::

:::{card}
:header: Executable content 🔁
Execute notebook cells, store results, and insert outputs across pages.
:::
::::
```

:::{myst:directive} grid
:::

## Tabs

You can also produce tabbed content. This allows you to display a variety of tabbed content blocks that users can click on.

```{myst}
::::{tab-set}
:::{tab-item} Tab 1
:sync: tab1
Tab one
:::
:::{tab-item} Tab 2
:sync: tab2
Tab two
:::
::::
```

If you have multiple tabs with the same name, they will be synced!

````{tab-set}
```{tab-item} Tab 1
:sync: tab1
Synced content for tab 1
```
```{tab-item} Tab 2
:sync: tab2
Synced content for tab 2
```
````

:::{myst:directive} tab-set
:::

:::{myst:directive} tab-item
:::

---

### Embed (`docs/embed.md`)

---
title: Embed & Include Content
description: You can embed labeled content (paragraphs, figures, notebook outputs, etc) across pages, allowing you to avoid re-writing the same information twice.
---

You can [embed](#docs:embed) **labeled content** (paragraphs, figures, notebook outputs, etc) across pages, allowing you to avoid re-writing the same information twice. You can also [include files](#docs:include) that are not in your project.

::::{seealso} Creating a Label
Embedding content requires a label to be present.
To attach labels to blocks of content, see [](./cross-references.md).
To attach labels to Jupyter Notebook content, see [](./reuse-jupyter-outputs.md)

For the examples below, we are defining a figure with a label:

```markdown
:::{figure} https://github.com/rowanc1/pics/blob/main/mountains.png
:label: myLabel
Here's a cool figure.
:::
```

:::{figure} https://github.com/rowanc1/pics/blob/main/mountains.png
:label: myLabel
Here's a cool figure.
:::
::::

(docs:embed)=

## The {myst:directive}`embed` directive

The {myst:directive}`embed` directive allows you to insert snippets of content at the time a page is rendered.

See {myst:directive}`the {embed} directive documentation <embed>` for details about all the arguments you can give to `{embed}`.

The {myst:directive}`embed` directive can be used like so:

````myst
```{embed} #myLabel
```
````

```{embed} #myLabel

```

Note that this works for any labeled item in your MyST document, including from other pages.
For example, the following references the admonitions list in [](admonitions.md).

````
```{embed} #admonitions-list
```
````

```{embed} #admonitions-list

```

(embed-image-short-hand)=

### The `` short-hand

The embedding shorthand lets you embed content using the Markdown image syntax (see more about [images](./figures.md)).
This **removes the input cell** if you are [embedding from a Jupyter notebook](./reuse-jupyter-outputs.md).

It can be used like so:

```markdown

```



### Embed images into figures

If you have a labeled image in your documentation, you can embed it as a Figure so that it contains figure metadata (like a caption, or adding alt-text).
To do so, use a **label attached to an image** instead of a filepath.

For example, we'll define an image with a label below:

```
(nice-sunset)=

```

(nice-sunset)=


And embed it into a figure next with a new `label`:

````
```{figure} #nice-sunset
:label: sunset-figure
Here's a nice sunset with a caption!
```
````

```{figure} #nice-sunset
:label: sunset-figure
Here's a nice sunset with a caption!
```

The new label can be referred to in this context, i.e. `[@sunset-figure]`: [@sunset-figure], which refers to the new figure rather than the original image. This allows you to scroll to embedded content on the page, rather than jumping to the original document. Note that this is especially useful with [embedding Jupyter Notebook outputs](./reuse-jupyter-outputs.md). For example:

```{figure} #img:altair-horsepower
This figure has been included from a Jupyter Notebook and can be referred to in cross-references through a different label. See [](./reuse-jupyter-outputs.md) for more information.
```

### Embed notebook content and outputs

You can embed notebook content (for example, images generated by running a cell).
For instructions on how to embed notebook content, see [](./reuse-jupyter-outputs.md).

### Embed from External MyST Projects

You can embed content from an **external site**, allowing you to re-use snippets of text, figures and tables, etc from other MyST projects. This is similar to [external cross-references](#myst-xref), which allow you to hover over a link and see the content on a different MyST site.

First, add `references` to your `myst.yml`:

:::{embed} #myst-xref-config
:::

You can then refer to content in these sites in two ways:

1. The [embed short hand](#embed-image-short-hand):

   ```md
   
   ```

2. The {myst:directive}`Embed directive <embed>`:

   ```md
   :::{embed} xref:spec#admonition
   :::
   ```

When you build your MyST project, the content that your `#label` points to will be embedded in-place of the directive.

:::{proof:example} Embedding from the MyST Spec

The following content is embedded from ``:



:::

(docs:include)=

## The {myst:directive}`include` directive

You can include multiple files into your MyST document as if they were all written in the same file.
This allows you to store content in separate files, and then weave them together at build time.
To do so, use the {myst:directive}`include` directive.

This is also helpful for including content snippets, such as a table or an equation, that you want to keep in a different file on disk, but present as if it were one document. In addition to Markdown, MyST will also parse `.ipynb`, `.tex`, and `.html`.

See {myst:directive}`the {include} directive documentation <include>` for details about all the arguments you can give to `{include}`.

:::{proof:example} Equation Bank
:label: eg:equation-bank
It is common practice to keep complex equations out of the main document so that they can be shared between slides, papers, and different renderings of a document. The `equations` folder in our documentation has a `curl.tex` file:

```{literalinclude} equations/curl.tex
:filename: equations/curl.tex
```

We can `include` that content in this document using:

````markdown
```{include} equations/curl.tex

```
````

which includes the content with the LaTeX parser:

```{include} equations/curl.tex

```

You will notice that there is no difference visually in the content, it is as if the content were include directly in line in the source document.
:::

:::{warning} Relative Paths in Markdown vs LaTeX
The {myst:directive}`argument <include.arg>` of the include directive is the file path and is **relative** to the file from which it was referenced. When working in markdown, recursive includes follow that same pattern. In LaTeX, however, recursive includes are relative to the original source file. This difference is only apparent when you have nested imports and a non-flat folder structure. MyST will also give you helpful warnings if it cannot find the file you are referencing.
:::

By default the file will be parsed using MyST, you can also set the file to be {myst:directive}`include.literal`, which will show as a code-block; this is the same as using the {myst:directive}`literalinclude` directive which is documented in [](#docs:literalinclude).

:::{note} Auto Reload & Circular Dependencies
:class: dropdown
If you are working with the auto-reload (e.g. `myst start`), the file dependencies are auto-reloaded.
Circular dependencies are not allowed and MyST will issue a warning and not render the recursion.
:::

:::{tip} Math and abbreviation frontmatter from included files
:class: dropdown
When including a file that has frontmatter, only some of that frontmatter is used. For example, the `math` macros and `abbreviations` are brought up to the top level and will overwrite any macros or abbreviations that already exist.

For LaTeX, the commands like `\newcommand` and `\renewcommand` are shared in the same way that math macros are shared for markdown files.
:::

## `{embed}` vs. `{include}`

The {myst:directive}`include` directive is very similar to {myst:directive}`embed`, with a few key differences.

`{include}` and `{literalinclude}`
: parses source files (e.g. text files on your filesystem) and inserts them into the document structure as if you had written the content in your target source file. These files are not listed in your project table of contents, and generally only contain snippets.

`{embed}`
: Pulls any labelled MyST content or outputs already parsed in your project.

---

### Executable Plugins (`docs/executable-plugins.md`)

---
title: Write plugins in other languages
description: Plugins built as stand-alone applications can be written in languages such as Python, and may be more familiar to some developers.
---

MyST is able to invoke plugins written in different languages through standard IO protocols, for example, in Python. These are called **Executable Plugins** because they rely on scripts that are executed at build time.

(executable-plugins)=
## How executable plugins work

Executable Plugins use `STDIO` to allow plugins that are written in any language, so long as they can access `STDIO` and can be executed. You configure an executable plugin in `myst.yml` like so:

```{code} yaml
:filename: myst.yml
project:
  plugins:
    - type: executable
      path: picsum.py
```

Your Executable Plugin file should have a `PLUGIN_SPEC` variable that defines its name and any roles, directives, or transforms that it will use. [See this `PLUGIN_SPEC` for example](https://github.com/projectpythia-mystmd/cookbook-gallery/blob/5ffd06e15d0058f310ea52f84f79f4f1d5394f81/pythia-gallery.py#L123-L127).

Your Executable Plugin should be executable from the command line, and take the arguments `--role`, `--directive`, and `--transform`. These will be used by MyST. [Here's an example in Python](https://github.com/projectpythia-mystmd/cookbook-gallery/blob/5ffd06e15d0058f310ea52f84f79f4f1d5394f81/pythia-gallery.py#L133-L135).

When your MyST site is built, MyST will **execute** the file specified in `path:` and follows a process like the following:

- **Read in the MyST AST from STDIN**. Parse it as JSON. [Here's an example](https://github.com/projectpythia-mystmd/cookbook-gallery/blob/5ffd06e15d0058f310ea52f84f79f4f1d5394f81/pythia-gallery.py#L139)
- **Modify the JSON AST in your script**. You can make edits, add things, etc. Just make sure that it remains valid JSON, and that it continues to follow the {term}`MyST Specification`. [Here's an example of the kind of AST you could output](https://github.com/projectpythia-mystmd/cookbook-gallery/blob/5ffd06e15d0058f310ea52f84f79f4f1d5394f81/pythia-gallery.py#L57-L79).
- **Print the new MyST AST to STDOUT**. `mystmd` will read from STDOUT and insert the node at the proper location. [Here's an example](https://github.com/projectpythia-mystmd/cookbook-gallery/blob/5ffd06e15d0058f310ea52f84f79f4f1d5394f81/pythia-gallery.py#L140).

:::{warning} What happens in an Executable Plugin is a black box
Executable MyST plugins are treated as a [](wiki:black_box), whereby MyST only sees the data it passes to the plugin, and the response from the plugin itself.
:::

## Define a new directive

:::{note}
There are many different ways to create an executable plugin. Here we'll use Python to implement an `picsum-py` directive, but any programming language that can read and write from stdin, stdout, and stderr, and define a command line interface would work.
:::

First, we'll declare the plugin _specification_ that allows MyST to discover the directives, transforms, and/or roles that the plugin implements. This specification looks very similar to [the definition of a JavaScript plugin](javascript-plugins.md#picsum-js-source), except the implementation logic (e.g. the directive `run` method) is not defined.

:::{literalinclude} picsum.py
:caption: A plugin to add an `picsum-py` directive that includes a beautiful, random picture based on a size and optional ID string.
:::
this file should be executable, e.g.

```{code} shell
chmod +x ./picsum.py
```

and should be referenced from your `myst.yml` under the `projects.plugins`:

```{code} yaml
:filename: myst.yml
project:
  plugins:
    - type: executable
      path: picsum.py
```

then start or build your document using `myst start` or `myst build`, and you will see that the plugin is loaded.

```text
myst start
...
🔌 Lorem Picsum Images (picsum.py) loaded: 1 directive
...
```

you can now use the directive, for example:

```markdown
:::{picsum-py}
:size: 600x250
:::
```

:::{picsum-py}
:size: 600x250
:::

If you change the source code you will have to stop and re-start the server to see the results.

The types are defined in `myst-common` ([npm](https://www.npmjs.com/package/myst-common), [github](https://github.com/jupyter-book/mystmd/tree/main/packages/myst-common)) with the [`DirectiveSpec`](https://github.com/jupyter-book/mystmd/blob/9965925030c3fab6f34c20d11eeee7ffdafa73df/packages/myst-common/src/types.ts#L68-L77) and [`RoleSpec`](https://github.com/jupyter-book/mystmd/blob/9965925030c3fab6f34c20d11eeee7ffdafa73df/packages/myst-common/src/types.ts#L79-L85) being the main types to implement.

## Implementing a custom transform

Directives can be used to extend MyST with rich structured content. However, sometimes we want to _modify_ the existing behavior of MyST. One of the ways to do this is by writing a custom transform. In this section, we'll implement a transform that replaces **bold** text with **special bold text**.

First, let's define the transform
:::{literalinclude} markup.py
:caption: A plugin to add a transform that replaces strong nodes with emphasis nodes.
:::
this code should be referenced from your `myst.yml` under the `projects.plugins`:

```{code} yaml
:filename: myst.yml
project:
  plugins:
    - type: executable
      path: markup.py
```

then start or build your document using `myst start` or `myst build`, and you will see that the plugin is loaded.

```text
myst start
...
🔌 Strong to emphasis (markup.py) loaded: 1 directive
...
```

you can now use the directive, for example:

```markdown
I am **special bold text (python)**, whilst I am **normal bold text**
```

I am **special bold text (python)**, whilst I am **normal bold text**

---

### Execute Notebooks (`docs/execute-notebooks.md`)

---
title: Execute Notebooks at Build Time
subtitle: Generate figures and other rich content using Jupyter kernels
short_title: Execute During Build
description: MyST can execute Markdown files and Jupyter Notebooks, making it possible to build rich websites from computational documents.
thumbnail: thumbnails/execute-notebooks.png
---

:::{warning} MyST execution features are in Beta
By default, execution is disabled and computational outputs are only inserted if the notebook has already been executed (for text-based notebooks, there are no outputs!).
We are adding support for executing markdown notebooks and ipynb files, including inline execution.
As we are adding this functionality we appreciate any feedback from the community on how it is working in your environments. Please add [issues](https://github.com/jupyter-book/mystmd/issues/new) or join [Discord](https://discord.mystmd.org/) to give feedback.
:::

The MyST CLI can execute your notebooks and markdown files by passing the `--execute` flag to the `start` and `build` commands, i.e.:

```bash
myst start --execute
myst build --execute
```

:::{note} Other flags can be relevant as well
For example if you want to produce a static HTML output from your content, you may wish to pass the `--html` flag as well:

```bash
myst build --execute --html
```
:::

## What content will be executed?

If you enable execution with the `--execute` flag as above, the following content will be executed at build time:

- **Cells in a Jupyter Notebook (`.ipynb`)**. These will be executed in the order they appeared in a notebook.
- **Markdown code cells with [the `code-cell` directive](#code-cell)**. These will be executed similar to a code cell. See [](./notebooks-with-markdown.md) for more information.
- **Inline expressions with [the `eval` role](#myst:inline-expressions)**. These can be used to insert the outputs of a computation in-line with other text.

:::{note} Jupyter is required for execution
In order to execute your MyST content, you must install a Jupyter Server and the kernel needed to execute your code (e.g., the [IPython kernel](https://ipython.readthedocs.io/en/stable/), the [Xeus Python kernel](https://github.com/jupyter-xeus/xeus-python), or the [IRKernel](https://irkernel.github.io/).)
:::

## Limit simultaneous executions

By default, up to {math}`N-1` executable files are run concurrently, where {math}`N` is the number of available CPUs. 

You can change this by using the `--execute-parallel <n>` option in your build command, where `<n>` sets the maximum number of executable documents that can run at the same time. This option is useful when your project includes executable content that is resource intensive or starts multiple subprocesses that might interfere with one another when run in parallel.

For example, setting `--execute-parallel 2` will execute the documents two at a time.

**To disable parallel execution**: set `--execute-parallel 1` 

## Show raw Python objects like modules and classes

By default, MyST will suppress outputs from cells that return **raw** Python objects - like modules and classes - that don't have a string representation. For example with regular Python, you would observe this:

```{code} Python
:filename: Input
import math
math
```

```{code} Python
:filename: Output
<module 'math' from '/some/path/math.cpython-312-darwin.so'>
```

But within MyST, this output is suppressed by default. This also applies to results like matplotlib's Axes objects, pandas' GroupBy objects, etc..  
If you'd like to instead show these outputs, see [](#setting:output_matplotlib_strings).

## Allow a code-cell to error without failing the build

By default, MyST will stop executing a notebook if a cell raises an error.
If instead you'd like MyST to continue executing subsequent cells (e.g., in order to demonstrate an expected error message), add the `raises-exception` tag to the cell. If a cell with this tag raises an error, then the error is provided with the cell output, and MyST will continue executing the rest of the cells in a notebook.

:::{tip} How to manage cell tags
:class: dropdown

See [notebook cell tags](#notebook-cell-tags) for how to manage cell tags  
For example, in a [{myst:directive}`code-cell` directive](#code-cell), you would add the `raises-exception` tag as follows:

````markdown
```{code-cell}
:tags: [raises-exception]

print("Hello" + 10001)
```
````
:::

## Skip particular code cells

Sometimes, you might have a notebook containing code that you _don't_ want to execute. For example, you might have code-cells that prompt the user for input, which should be skipped during a website build. MyST understands the same `skip-execution` cell-tag that other Jupyter Notebook tools (such as Jupyter Book V1) use to prevent a cell from being executed.

:::{tip} Example of skipping a code cell
:class: dropdown
For example, in a [{myst:directive}`code-cell` directive](#code-cell), the `skip-execution` tag can be added as follows:

````markdown
```{code-cell}
:tags: [skip-execution]

name = input("What is your name?")
```
````

Here again, see [notebook cell tags](#notebook-cell-tags) for more details on how to manage cell tags  

:::

[Additional cell tags](#tbl:notebook-cell-tags), to hide or remove cells inputs or outputs, are also available.

## Skip entire notebooks

You may wish to disable execution for certain notebooks. This can be done by setting the `execute.skip` frontmatter option to `true`, e.g.

````markdown
---
kernelspec:
  name: python3
  display_name: Python 3

execute:
  skip: true
---

```{code-cell}
print("This will never be executed!")
```
````

See also [notebook tags](#notebook-tags-ipynb) for how to set notebook-level metadata on a Jupyter Notebook.

## Cache execution outputs

When MyST executes your notebook, it will store the outputs in a cache in a folder called `execute/` in your MyST build folder.
On subsequent builds, MyST will re-use this cache rather than re-execute.

If you change the computational content of a notebook or a markdown page (ie, code in a code cell, or in an inline expression), then this cache will be reset and the code will be re-executed at the next build.

### Force execution by deleting the cache

If you'd like to force re-execution of all the code in your MyST documents, use the following command:

```bash
myst clean --execute
```

Alternatively, you can manually delete the `execute/` folder in your build folder, e.g.:

```bash
rm -rf _build/execute
```

(install-jupyter-server)=

## Install Jupyter Server

MyST uses a [Jupyter Server](https://jupyter-server.readthedocs.io/) to execute your code.
Jupyter Server is distributed as a Python package, which can be installed from PyPI or conda-forge, e.g.

```bash
pip install jupyter-server
```

Jupyter Server is only responsible for orchestrating execution of your code. To actually perform execution, you must also install a kernel. For Python, this might be `ipykernel`, e.g.

```bash
pip install ipykernel
```

If Jupyter Server is installed and the `--execute` flag is passed to `myst start` or `myst build` MyST will attempt to launch a Jupyter Server using `python -m jupyter_server`.

## Manually launch a Jupyter server

You can manually launch a Jupyter server and instruct MyST to use it for computation (rather than having MyST start its own Jupyter server).
This gives you more control over the process that executes your content, including specifying Jupyter servers that exist on non-local hardware (e.g. running in the cloud).

To manually specify a server, you must set two variables:

- **`JUPYTER_BASE_URL`**: a URL where the server can be found. On a local machine, this is by default `http://localhost:8888`.
- **`JUPYTER_TOKEN`**: the token that allows access to the Jupyter server.

For example, the following code sets these variables, then starts a Jupyter server with them so that MyST will use them to execute code:

```bash
# Set the port for our local Jupyter process
port="8888"

# Define environment variables that will be used by MyST
# We'll use the values of these variables in our Jupyter server as well.
export JUPYTER_BASE_URL="http://localhost:${port}"
export JUPYTER_TOKEN="my-jupyter-token"

# Start the Jupyter server re-using the variables above
jupyter server --IdentityProvider.token="${JUPYTER_TOKEN}" --ServerApp.port="${port}" &

# Run the MyST build
# It will use the JUPYTER_* variables above to look for the server.
myst build --execute

# Stop the Jupyter server!
kill %1
```

---

### Exercises (`docs/exercises.md`)

---
title: Exercises and Solutions
short_title: Exercises
description: MyST supports adding exercises and solutions which can cross-reference each-other and include Jupyter Notebook outputs.
thumbnail: ./thumbnails/exercise.png
---

There are two directives available to add exercises and solutions to your documents: (1) an `exercise` directive; and (2) a `solution` directive.
The exercises are enumerated by default and can take in an optional title argument as well as be "gated" around Jupyter Notebook cells.

## Exercise Directive

::::{tab-set}
:::{tab-item} Example

```{exercise}
:label: my-exercise

Recall that $n!$ is read as "$n$ factorial" and defined as
$n! = n \times (n - 1) \times \cdots \times 2 \times 1$.

There are functions to compute this in various modules, but let's
write our own version as an exercise.

In particular, write a function `factorial` such that `factorial(n)` returns $n!$
for any positive integer $n$.
```

:::
:::{tab-item} MyST Syntax

````markdown
```{exercise}
:label: my-exercise

Recall that $n!$ is read as "$n$ factorial" and defined as
$n! = n \times (n - 1) \times \cdots \times 2 \times 1$.

There are functions to compute this in various modules, but let's
write our own version as an exercise.

In particular, write a function `factorial` such that `factorial(n)` returns $n!$
for any positive integer $n$.
```
````

:::
::::

_Source:_ [QuantEcon](https://python-programming.quantecon.org/functions.html#Exercise-1)

The following options for exercise directives are supported:

:::{myst:directive} exercise
:::

## Solution Directive

A solution directive can be included using the `solution` pattern.
It takes in the label of the directive it wants to link to as a required argument.
Unlike the `exercise` directive, the solution directive is not enumerable as it inherits numbering directly from the linked exercise.
The argument for a solution is the label of the linked exercise, which is required.

::::{tab-set}
:::{tab-item} Example

````{solution} my-exercise
:label: my-solution

Here's one solution.

```{code-block} python
def factorial(n):
    k = 1
    for i in range(n):
        k = k * (i + 1)
    return k

factorial(4)
```
````

:::
:::{tab-item} MyST Syntax

`````markdown
````{solution} my-exercise
:label: my-solution

Here's one solution.

```{code-block} python
def factorial(n):
    k = 1
    for i in range(n):
        k = k * (i + 1)
    return k

factorial(4)
```
````
`````

:::
::::

_Source:_ [QuantEcon](https://python-programming.quantecon.org/functions.html#Exercise-1)

The following options for solution directives are supported:

:::{myst:directive} solution
:::

## Referencing Exercises & Solutions

You can refer to an exercise using the standard link syntax:

- `[](#my-exercise)`, creates [](#my-exercise)
- `[{name}](#nfactorial)`[^note] creates [{name}](#nfactorial)
- `[{number}](#my-exercise)` creates [{number}](#my-exercise)
- `[See Exercise](#my-exercise)` creates [See Exercise](#my-exercise)

:::{tip} Compatibility with Sphinx Exercise
:class: dropdown

You can also refer to an exercise using the {myst:role}`ref` role like `` {ref}`my-exercise` ``, which will display the title of the exercise directive. In the event that directive does not have a title, the title will be the default "Exercise" or "Exercise {number}" like so: {ref}`my-exercise`.

Enumerable directives can also be referenced through the {myst:role}`numref` role like `` {numref}`my-exercise` ``, which will display the number of the exercise directive. Referencing the above directive will display {numref}`my-exercise`. In this case it displays the same result as the {myst:role}`ref` role as `exercise` notes are (by default) enumerated.

Furthermore, `numref` can take in three additional placeholders for more customized titles:

1. _%s_
2. _{number}_ which get replaced by the exercise number, and
3. _{name}_ by the exercise title.[^note]

For example,\
`` {numref}`My custom {number} and {name} <my-exercise-label>` ``.

[^note]: If the exercise directive does not have a title, the `label` will be used instead.

:::

### Referencing Solutions

You can refer to a solution directly as well using a Markdown link or using the {myst:role}`ref` role like: `` {ref}`my-solution` `` the output of which depends on the attributes of the linked directive.
If the linked directive is enumerable, the role will replace the solution reference with the linked directive type and its appropriate number like so: {ref}`my-solution`.

In the event that the directive being referenced is unenumerable, the reference will display its title: {ref}`nfactorial-solution`.

:::{note} Named Exercise & Solution
:class: dropdown simple
:icon: false

```{exercise} $n!$ Factorial
:label: nfactorial
:enumerated: false

Write a function `factorial` such that `factorial(int n)` returns $n!$
for any positive integer $n$.
```

````{solution} nfactorial
:label: nfactorial-solution

Here's a solution in Java.

```{code-block} java
static int factorial(int n){
    if (n == 0)
        return 1;
    else {
        return(n * factorial(n-1));
    }
}
````

:::

If the title of the linked directive being reference does not exist, it will default to {ref}`nfactorial-notitle-solution`.

:::{note} Unnumbered Exercise & Solution
:class: dropdown simple
:icon: false

```{exercise}
:label: nfactorial-notitle
:enumerated: false

Write a function `factorial` such that `factorial(int n)` returns $n!$
for any positive integer $n$.
```

````{solution} nfactorial-notitle
:label: nfactorial-notitle-solution

Here's a solution in Java.

```{code-block} java
static int factorial(int n){
    if (n == 0)
        return 1;
    else {
        return(n * factorial(n-1));
    }
}
````

:::

## Alternative Gated Syntax

To be able to be viewed as Jupyter Notebooks (e.g. in [JupyterLab MyST](./quickstart-jupyter-lab-myst.md)) `code-cell` directives must be at the root level of the document for them to be executed.
This maintains direct compatibility with the `jupyter notebook` and enables tools like `jupytext` to convert between `myst` and `ipynb` files.

As a result **executable** `code-cell` directives cannot be nested inside of exercises or solution directives.

The solution to this is to use the **gated syntax**.

```{note}
This syntax can also be a convenient way of surrounding blocks of text that may include other directives that you wish
to include in an exercise or solution admonition.
```

**Basic Syntax**
::::{tab-set}
:::{tab-item} Example

```{exercise-start}
:label: ex1
```

```python
# Some setup code that needs executing
```

and maybe you wish to add a figure

```{figure} https://github.com/rowanc1/pics/blob/main/sunset.png

```

```{exercise-end}

```

:::

:::{tab-item} MyST Syntax

````markdown
```{exercise-start}
:label: ex1
```

```python
# Some code to explain the figure
```

and maybe you wish to add a figure

```{figure} https://github.com/rowanc1/pics/blob/main/beach.png

```

```{exercise-end}

```
````

:::
::::

This can also be completed for solutions with `solution-start` and `solution-end` directives.
The `solution-start` and `exercise-start` directives have the same options as original directive.

```{warning} Mismatched Start & End
:class: dropdown
If there are missing `-start` and `-end` directives, this will cause an extension error,
alongside feedback to diagnose the issue in document structure.
```

## Hiding Directive Content

To visually hide the content, simply add `:class: dropdown` as a directive option, similar to an admonition.

::::{tab-set}
:::{tab-item} Example

```{exercise}
:class: dropdown

Recall that $n!$ is read as "$n$ factorial" and defined as
$n! = n \times (n - 1) \times \cdots \times 2 \times 1$.

There are functions to compute this in various modules, but let's
write our own version as an exercise.

In particular, write a function `factorial` such that `factorial(n)` returns $n!$
for any positive integer $n$.
```

:::

:::{tab-item} MyST Syntax

````markdown
```{exercise}
:class: dropdown

Recall that $n!$ is read as "$n$ factorial" and defined as
$n! = n \times (n - 1) \times \cdots \times 2 \times 1$.

There are functions to compute this in various modules, but let's
write our own version as an exercise.

In particular, write a function `factorial` such that `factorial(n)` returns $n!$
for any positive integer $n$.
```
````

:::
::::

### Remove Directives

Any specific directive can be hidden by introducing the `:hidden:` option. For example, the following example will not be displayed

````{myst}
```{exercise}
:hidden:

This is a hidden exercise directive.
```
````

:::{warning} Exercises are not supported in some PDF outputs
You'll encounter warnings when exporting exercises and solutions to pdf using either LaTeX or Typst.
This is because these directives are not natively supported in these formats.
See [this plugin](https://github.com/jupyter-book/myst-plugins/tree/main/plugins/exercise-admonition-pdf) to enable exporting these directives to pdf formats - including numeration.
:::


% TODO: Remove All Solutions
% TODO: Custom CSS

---

### External References (`docs/external-references.md`)

---
title: External References
description: External references dynamically include content into your MyST Markdown projects, from Wikipedia, intersphinx, DOIs, RRIDs, and any other MyST projects. Allowing your documents to be rich, interactive and automatically kept up to date.
thumbnail: ./thumbnails/external-references.png
---

MyST Markdown allows you to connect your <wiki:documents> to external [linked](wiki:Hyperlink) content like <wiki:Wikipedia>, which allow for [hover](wiki:Hovercraft)-references with external content.
External references are references to structured content or documents that are outside of your project.
MyST supports referencing rich content in a growing number of formats, including:

1. other `mystmd` projects, with rich cross-linking of content
1. integrating directly with **Wikipedia** articles to show tooltips,
1. linking to other **Sphinx** documentation using intersphinx,
1. link to files on **GitHub** and show inline previews,
1. showing structured content from scholarly sources like **DOIs** or **RRIDs**.

```{seealso}
[](./cross-references.md) for referencing content in your project and [](./citations.md) to cite scholarly work and create bibliographies.
```

(myst-xref)=

## External MyST projects

When using the HTML renderer for MyST, an API is provided for the deployed site.
This provides pre-parsed, structured content as an AST that can be included in other projects and rendered in a tooltip.

:::{tip} Add `.json` to any MyST URL to access the structured data
All MyST pages come with a structured data representation that provides authors, license information,
as well as the full content in a parsed form that can be used for an inline reference on external pages.
Try adding `.json` at the end of the URL on this page.
:::

In your project configuration, include the `references` object with links out to the external MyST projects that you will reference in your project. The keys in this object have no special meaning; they are just used within your project to look up the external project. The example below shows how you would load cross-references that are pulled from the MyST Specification documentation.

```{code-block} yaml
:label: myst-xref-config
:filename: myst.yml
:caption: Add `references` to your project configuration in your `myst.yml`, MyST will then provide access to all of content on those pages in links and embeds.
project:
  references:
    spec: https://mystmd.org/spec
```

When you specify these in your project configuration, MyST will load the cross-references and provide access to all of the pages and reference targets in that project.
References are cached to disk locally in the `_build` folder, eliminating duplicate web requests on subsequent builds.
To delete the cache and manually re-load the references, run `myst clean --cache`.

````{important}
# MyST Cross Reference Examples

```{list-table}
:label: tbl:syntax-xref
:header-rows: 1
* - MyST Syntax
  - Rendered
* - `[](xref:spec)`
    : A reference to the first page of the MyST Spec.
  - [](xref:spec)
* - `[](xref:spec#paragraph)`
    : A reference to the node "paragraph" target in the MyST Spec.
  - [](xref:spec#paragraph)
* - `<xref:spec/tables#example>`
    : Alternate link syntax that references a heading on a specific page of the spec documentation.
  - <xref:spec/tables#example>
```
````

To reference content in the linked MyST project, use the `xref:` protocol in a link, followed by the corresponding external project `key` you defined under `references`, the url path and the target.
For example, `<xref:spec/tables#example>` renders to:\
"<xref:spec/tables#example>"\
and is made of a `protocol` ("xref"), external project `key` ("spec"), `path` ("/tables") and `target` ("#example").

protocol
: The protocol for this type of link is `xref:`, and is what selects for cross-project referencing.

key
: the external project `key` above is "spec" which is defined in your local [project configuration](#myst-xref-config) above.

path
: the `path` is everything that follows the external project key before the `#`. It corresponds directly to the URL path in the MyST site. In the example above, path is `/tables`.
: Path is **optional** in most cases; the `target` can be resolved against the entire project without the path. An exception to this is headings without an explicit label in the source markdown — these will require path. Note that these references may not be intended to be persistent by the source author, so use caution in linking to them!

target
: The target is everything that follows the `#` and is a named reference in the project. In the example above it is "syntax".
: Target is also optional - if not provided, the cross reference will simply link to a page in the external MyST project. However, without the target, there will not be a rendered tooltip.
: When creating a cross reference, you can determine `path` and `target` by simply navigating to your target content in the external MyST project and copying the path and fragment from the URL.

If no link text is provided, e.g. `[](xref:...)`, text will be generated from the external project at build-time. You may override this behavior by providing you own text, `[text](xref:...)`.

:::{tip} References are stored in a [`myst.xref.json`](#myst-xref-json) file
:class: dropdown
All MyST sites published to the web expose a [`myst.xref.json`](#myst-xref-json) file that contains all of the cross-references information about a MyST site.
This file is what MyST pulls when you point to an external MyST site for cross-referencing.
It is also a machine-readable record that can be used for analyzing the cross-referencing behavior of MyST projects.
:::

(intersphinx)=

## Sphinx documentation

MyST can integrate directly with other Sphinx documentation, which is used in many Python projects including the [standard library](https://docs.python.org/).
This re-uses the reference specification defined by [the intersphinx plugin for Sphinx](https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html).

% TODO: Update this when we release Jupyter Book V2 because /stable will no longer be a Sphinx site.

Similar to [MyST cross references](#myst-xref), use the `references` object to list Sphinx projects. For example, in the demonstration below we will load the Python 3.13 documentation and Jupyter Book V1 docs, both of which use sphinx and expose cross references through an `objects.inv` file.

(intersphinx-config)=

```yaml
references:
  python: https://docs.python.org/3.13/
  jupyterbook: https://jupyterbook.org/en/stable/
```

```{tip}
In your `references` object, you may freely mix MyST and Sphinx projects. MyST will decipher which to use, based on the presence of `myst.xref.json` or `objects.inv` files at the specified URL.
```

The behavior of these entries is identical to MyST cross references: the remote `objects.inv` file, which contains all available project references, is downloaded and cached in the `_build` folder.

````{important}
# Sphinx Examples

```{list-table}
:header-rows: 1
* - MyST Syntax
  - Rendered
* - `[](xref:python#zipapp-specifying-the-interpreter)`
    : A reference to the reference documentation in Python.
  - [](xref:python#zipapp-specifying-the-interpreter)
* - `[](xref:jupyterbook#content:references)`
    : A reference to the Jupyter Book documentation, that brings you directly to the reference,
      as well as fills in the label text.
  - [](xref:jupyterbook#content:references)
```
````

To reference a function, class or label in the linked documentation, use the `xref:` protocol in a link followed by the project `key` and the target.
For example, `<xref:python#library/abc>` renders to:\
"<xref:python#library/abc>"\
and is made of a `protocol` ("xref"), `key` ("python") and `target` ("#library/abc").

protocol
: The protocol for this type of link is `xref:`, and is what selects for cross-project referencing.

key
: the external project `key` above is "python" which is defined in your local [project configuration](#intersphinx-config) above.

target
: The target is everything that follows the `#` and is a named reference in the project.
: In the example above it is "library/abc".

As with any link, the text can be overridden using markdown link syntax `[text](xref:...)`.

````{tip}
:class: dropdown
# How to find the Sphinx target?

The HTML IDs that are part of the documentation are not always the targets that are used in the documentation. The easiest way to find the target to use is to look at the source documentation in RST or MyST.

Look for the `(target)=` syntax or `:label:` on a directive.

MyST will warn you in the console if your target is not found.

You can also use the [intersphinx](https://www.npmjs.com/package/intersphinx) package, for example, `list`, or `parse` an intersphinx inventory:

```bash
>> intersphinx list https://docs.python.org/3.13 --domain std:doc --includes abc --limit 5

std:doc Abstract Base Classes (library/abc)
  https://docs.python.org/3.13/library/abc.html
std:doc Abstract Base Classes for Containers (library/collections.abc)
  https://docs.python.org/3.13/library/collections.abc.html
```

Use the target in the parenthesis, which would be `xref:python#library/abc` above.
````

## Wikipedia Links

MyST Markdown can directly integrate with <wiki:Wikipedia> to create hover-card information directly integrated into your myst documents. The syntax follows standard markdown links, under the `wiki:` protocol followed by the page title[^1]. As with any other link, you can either follow a `[text](wiki:Page_Title)` or `<wiki:Page_Title>`, which if no text is provided for the links will be replaced with the page title.

[^1]: Replace any spaces in the page title with underscores.

```{myst}
Primordial <wiki:gravitational_waves> are hypothesized to arise from <wiki:cosmic_inflation>, a faster-than-light expansion just after the <wiki:big_bang>.
```

The links will take you to Wikipedia, as well as provide a tooltip and description directly on the page.

To show different text you can use a similar technique to references:\
`[my **bold** text](wiki:reference)`

```{myst}
* [big bang](wiki:The_Big_Bang_Theory)
* [](wiki:big_bang)
```

```{tip}
:class: dropdown
# Finding and formatting the page title
To find the page title, browse Wikipedia and copy the last part of the URL, for example:\
`Page_Title` in `https://wikipedia.org/wiki/Page_Title`. If you do not supply text for the link specifically, then the case of the link will be preserved and shown without the underscores.

Usually the page titles resolve properly, so just try guessing when you are writing and then you can check them with the live hover preview.

Note that if the page title has spaces in it, simply replace them with underscores.
```

```{important}
:class: dropdown
# Different languages or wikis

There are many different official and unofficial wikis that use the same [Wikimedia](wiki:Wikimedia_Foundation) technology, including subdomains in various languages.

Wikipedia links, like `https://fr.wikipedia.org/wiki/Croissant_(viennoiserie)` will work fine out of the box, and point to [](https://fr.wikipedia.org/wiki/Croissant_(viennoiserie)) with the popup still working!

% TODO: Allow the ability to set the default language to use on your MyST site. This is already possible in the transformers.

% TODO: Set the default wiki links, or an additional wiki link in references, e.g. to something like https://wiki.seg.org/wiki/Knowledge_tree
```

## GitHub

### Issues and Pull Requests

MyST Markdown can directly link and show preview of GitHub issues and Pull Requests, for example, [#336](https://github.com/jupyter-book/mystmd/issues/336) and [#87](https://github.com/jupyter-book/myst-theme/pull/87). To enable this, just use a normal link to your

```markdown
[#87](https://github.com/jupyter-book/myst-theme/pull/87)
```

If you do not include children for the link, then the default text will become `owner/repo#123`.

### Linking to Code

MyST Markdown can directly integrate with links to GitHub to create hover-card information directly integrated into your MyST documents. For example, a link to the [linkTransforms](https://github.com/jupyter-book/mystmd/blob/78d16ee1a/packages/myst-transforms/src/links/plugin.ts#L12-L28) plugin code shows a preview of the code. The code preview works for both multiple line numbers and highlighting [single lines](https://github.com/jupyter-book/mystmd/blob/78d16ee1a/packages/myst-transforms/src/links/plugin.ts#L30), which shows the surrounding ten lines, with the referenced line highlighted. If you reference the [full file](https://github.com/jupyter-book/mystmd/blob/78d16ee1a/packages/myst-transforms/src/links/plugin.ts) then the first ten lines of the file are shown in the preview.

````{important}
:class: dropdown
# Creating GitHub links to code
GitHub links to code can be generated on the GitHub web application when browsing code and click on the line numbers, then copy the URL. To select multiple lines, click your first line then shift-click to select multiple lines, the URL will be updated to end with `#L4-L6`. The structure of the link should look like:

```text
https://github.com/{{org}}/{{repo}}/blob/{{reference}}/file.py#L4-L6
```

Any git `reference` will work, however, picking a branch like `main` may mean that your code line numbers will change, instead, you may want to go to navigate to a specific git commit or tag, which will show up in the URL.
````

% TODO: Add ability to reference issues and PRs with queries for the issue names, and PR information.

## Linking DOIs

It is possible to include DOIs as external content, and they are also added as citations to your project and show up in the references section at the bottom of a document. See [](./citations.md) for more details, specifically [](#doi-links), which explains linking DOIs with the `<doi:10.5281/zenodo.6476040>` or `[](doi:10.5281/zenodo.6476040)` to create a citation, for example (<doi:10.5281/zenodo.6476040>).

## Research Resource Identifiers

{abbr}`RRID (Research Resource Identifiers)`s are persistent, unique identifiers for referencing a research resource, such as an antibody, plasmid, organism, or scientific tool. These are helpful for ensuring reproducibility and exact communication in scientific studies. See the [RRID website](https://scicrunch.org/resources) for more information.

MyST Markdown allows you to directly integrate with the RRID database to pull information and validate the links are correct as you are writing documents. The metadata is passed to subsequent systems (e.g. PDF documents, compatible journals and preprint servers) and helps keep your science reproducible.

To create an RRID link, use the `rrid:` protocol followed by the resource identifier, for example:

- `[](rrid:SCR_008394)` becomes [](rrid:SCR_008394)
- `<rrid:SCR_008394>` becomes <rrid:SCR_008394>

````{note}
# Example Methods Section

An edited excerpt from _Impaired speed encoding and grid cell periodicity in a mouse model of tauopathy_
{cite:p}`10.7554/eLife.59045`. The authors used Matlab (<rrid:SCR_001622>) in their analysis.

Click on one of the RRIDs below to see additional metadata!

```{list-table}
:header-rows: 1

* - Resource type
  - Designation
  - Source
  - Identifiers

* - Strain (M. musculus)
  - rTg4510, Tg(Camk2a-tTA)
  - ENVIGO
  - <rrid:MGI:4819951>

* - Software, algorithm
  - Klusta suite
  - {cite}`10.1038/nn.4268`
  - <rrid:SCR_014480>

* - Software, algorithm
  - MATLAB R2019b
  - [Mathworks](https://uk.mathworks.com/)
  - <rrid:SCR_001622>\
    <rrid:SCR_005547>

* - Software, algorithm
  - OriginPro 2019b
  - [OriginLab](https://www.originlab.com/)
  - <rrid:SCR_014212>
```
````

## Research Organization Registry

The Research Organization Registry (ROR) is a global, community-led registry of open persistent identifiers for research organizations. You can add these to your MyST frontmatter or use the links directly in your documents.

To create an ROR link, use the `ror:` protocol followed by the identifier, for example:

- `[](ror:03rmrcq20)` becomes [](ror:03rmrcq20)
- `<ror:03rmrcq20>` becomes <ror:03rmrcq20>

You may also use a URL similar to `https://ror.org/03rmrcq20`. To find your organization use the search provided at [ror.org](https://ror.org)

---

### Figures (`docs/figures.md`)

---
title: Images, Figures and Videos
short_title: Images, Figures, & Videos
description: MyST Markdown allows you to create images and figures in your documents, including cross-referencing content throughout your pages.
thumbnail: ./thumbnails/figures.png
---

MyST Markdown can be used to include images and figures in your documents as well as referencing those images easily throughout your website, article or paper.

## Simple images

The simplest way to include an image is to use the standard Markdown syntax:

```md

```

You can explore a [demo of images](#md:image) in the discussion of [](./commonmark.md) features of MyST.

Using standard markdown to create an image will render across all output formats (HTML, TeX, Word, PDF, etc).
However, this markdown syntax is limited in the configuration that can be applied beyond `alt` text and an optional `title`.

There are two directives that can be used to add additional information about the layout and metadata associated with an image.
For example, {myst:directive}`image.width`, {myst:directive}`alignment <image.align>` or a {myst:directive}`figure caption <figure.body>`.

**image**
: The {myst:directive}`image` directive allows you to customize {myst:directive}`image.width`, {myst:directive}`alignment <image.align>`, and other {myst:directive}`classes <image.class>` to add to the image.

**figure**
: The {myst:directive}`figure` directive can contain a {myst:directive}`figure caption <figure.body>` and allows you to cross-reference this in other parts of your document.

(image-directive)=

## Image directive

The `{image}` directive lets you include a simple image on your page.
You can control the alt-text, style, etc.
Here's an example:

````{myst}
```{image} https://github.com/rowanc1/pics/blob/main/grapes-wide.png?raw=true
:alt: Grapes on a vineyard
:width: 500px
:align: center
```
````

(figure-directive)=

## Figure directive

Figures can wrap one-or-more images.
They'll be _numbered_, so referencing them creates links like `Figure 1`. 

````{myst}
```{figure} https://github.com/rowanc1/pics/blob/main/sunset.png?raw=true
:label: myFigure
:alt: Sunset at the beach
:align: center

Relaxing at the beach 🏝 🌊 😎
```
````

```{note}
You may also embed [notebook cell outputs as images or figures](#targeting-cells).
```

## Subfigures

Subfigures are created by putting one or more images in the **directive body** instead of as an argument.
These will be numbered as `Figure 1a` and `Figure 1b`, etc. For example:

:::{figure}
:label: subFigure
:align: left




We saw some great things on our trips this year to Banff, Canada 🇨🇦 and San Francisco, USA 🌉.
:::

You can cross-reference either the whole figure [@subFigure], or an individual subfigure [@subFigure-a] or [@subFigure-b].
Each subfigure is given an implicit reference that matches the figure label with a suffix of their letter. For example, let's say you have a parent figure and give it a label `my-figure`, and it has two sub-figures. Each subfigure can be referred to as `#my-figure-a` and `#my-figure-b`, respectively.

If you provide a [label for a specific subfigure](#label-anything), that label will be used instead of the implicit label.


```{myst}
:::{figure}
:label: my-figure
:align: left

(my-figure-fruit)=




Some pictures of fruit and the ocean!
:::

See [](#my-figure-fruit) for the fruit, and [](#my-figure) to reference both subfigures.
```

When referring to subfigures, the `{number}` that is used includes the parent enumerator by default (that is: `1a` rather than just `a`).
To use the sub-enumerator only, you can use the syntax `{subEnumerator}` in your text link which will be replaced with the sub-enumerator (that is: `a` rather than `1a`).

CSS classes can be applied to make subfigures appear side-by-side or in a grid layout.
`:class: grid grid-cols-2 items-end gap-4` 
can be used to create a two-column grid of images with aligned bottoms and a gap between them.

::::{figure}
:class: grid grid-cols-2 items-end gap-4
:label: fig_combined2
:width: 100%




Some lovely pictures
::::

### Control sub-figure layout with a grid

For responsive layouts, wrap the content in a `{grid}` directive.
In this case, the figure has a _single entry_, representing the grid of images that you provide.
It will not create implicit references for sub-figures as desecribed above.
The example below uses one column on narrow screens and two on wide ones (`1 1 2 2`).

::::{figure}
:label: fig-grid

:::{grid} 1 1 2 2




:::

Pictures of fruit and the ocean.
::::

## Supported Image Formats

MyST supports many images formats including `.png`, `.jpg`, `.gif`, `.tiff`, `.svg`, `.pdf`, and `.eps`.
Many of these image formats are easily supported for HTML themes including `.png`, `.jpg` and `.gif`.
However, the raster image formats can be further optimized to [improve site performance](./accessibility-and-performance.md), MyST translates these to the modern `.webp` format while the site is building.
The original file-format is also included your site, with a `srcset` and fallback for older web-browsers.

`````{tab-set}
````{tab-item} PNG
:::{figure} ./images/myst-image.png
:width: 50%
`.png` is natively supported in all exports. The image is converted to `.webp` for web-browsers.
:::
````

````{tab-item} JPG
:::{figure} ./images/myst-image.jpg
:width: 50%
`.jpg` or `.jpeg` is natively supported in all exports. The image is converted to `.webp` for web-browsers.
:::
````

````{tab-item} GIF
:::{figure} ./images/myst-image.gif
:width: 50%
`.gif` is supported web-browsers and Microsoft Word, the first frame is extracted for $\LaTeX$ and PDF exports. The image is converted to `.webp` for web-browsers.
:::
````

````{tab-item} TIFF
:::{figure} ./images/myst-image.tiff
:width: 50%
`.tiff` is not supported by most web-browsers, and is converted to `.png`. Microsoft Word, $\LaTeX$ and PDF exports can work with these `.png` images, which are also converted to `.webp` for web-browsers.
:::
````

````{tab-item} SVG
:::{figure} ./images/myst-image.svg
:width: 50%
`.svg` is supported by web-browsers and is not further optimized or rasterized. When exporting to $\LaTeX$ and PDF the images are translated to `.pdf` using `inkscape` or as a fallback to `.png` using `imagemagick`. Microsoft Word requires the `.png` export.
:::
````

````{tab-item} PDF
:::{figure} ./images/myst-image.pdf
:width: 50%
A `.pdf` image is not supported by web-browsers or Microsoft Word. The images are translated to `.png` using `imagemagick`. $\LaTeX$ and PDF use the `.pdf` image directly.
:::
````

````{tab-item} EPS
:::{figure} ./images/myst-image.eps
:width: 50%
An `.eps` image is not supported by web-browsers or Microsoft Word. The images are translated to `.png` using `imagemagick`. $\LaTeX$ and PDF use the `.eps` image directly.
:::
````
`````

### Image Transformers

There are formats that are not supported by web-browsers but are common in scientific writing like `.tiff`, `.pdf` and `.eps`. 
For site builds, these are converted to `.svg` or `.png` as appropriate and available.
For export to $\LaTeX$, PDF or Microsoft Word, the files are converted to an appropriate format that the export can handle (e.g. $\LaTeX$ can work directly with `.pdf` images).
For animated images, `.gif`, the first frame is extracted for static exports.

:::{tip} Installing Image Converters
:class: dropdown
The image transforms and optimizations requires you to have the following packages installed:

- [ImageMagick](https://imagemagick.org/) for conversion between raster formats
- [inkscape](https://inkscape.org/) for conversion between some vector formats
- [webp](https://developers.google.com/speed/webp) for image optimizations

:::

(figures:multiple-images)=

### Multiple Images

If you have manually converted your images or have different images for different formats, use an asterisk (`*`) as the extension.
All images matching the provided pattern will be found and the best image available will be used for the export:

```text

```

For example, when exporting to $\LaTeX$ the best format is a `.pdf` (if available); in a web export, a `.webp` or `.svg` will be chosen before a `.png`.
In all cases, if an appropriate format is not available the image will be converted.

## Videos

To embed a video you can either use a video platforms embed script or directly embed an `mp4` video file. For example:

```markdown
:::{figure} ./videos/links.mp4
An embedded video with a caption!
:::
```
or
```markdown

```

will copy the video to your static files and embed a video in your HTML output.

:::{figure} ./videos/links.mp4
An embedded video with a caption!
:::

If you have [ffmpeg](https://www.ffmpeg.org/) installed, you may also include `.mov` and `.avi` video files, and MyST will convert them to `.mp4` and include them.
Videos can also be used in the [image](#image-directive) or even in simple [Markdown image](#md:image).

### Use an image in place of a video for static exports

If you'd like an image to display for static exports (like PDFs), use the asterisk (`*`) wildcard matching described in [](#figures:multiple-images).

For example, if you had the following two files:

```text
myvideo.mp4  <-- A video of something
myvideo.png <-- A frame of the video as an image
```

Then you could link them both with:

```md

```

When you build an HTML output, the video will be used, and when you build a PDF output, the image will be used.

## YouTube Videos

If your video is on a platform like YouTube or Vimeo, you can use the {myst:directive}`iframe` directive that takes the URL of the video.

```{myst}
:::{iframe} https://www.youtube.com/embed/F3st8X0L1Ys
:width: 100%
Get up and running with MyST in Jupyter!
:::
```

You can find this URL when clicking share > embed on various platforms. You can also give the {myst:directive}`iframe` directive {myst:directive}`iframe.width`, {myst:directive}`iframe.title` (for accessibility), and a {myst:directive}`caption <iframe.body>`.

## Provide Light and Dark Mode images

To provide images for light and dark mode, use [Tailwind CSS classes for light and dark mode](#light-dark-css).

---

### Frontmatter (`docs/frontmatter.md`)

# Content frontmatter options

The following table lists the available frontmatter fields. If a field has sub-fields, see the relevant description on the page below.

## Where to put these fields

Placement depends on the **Field Behavior** column below:

- **page & project**: valid in both page frontmatter and `project` in `myst.yml`
- **page only**: valid only in page frontmatter
- **project only**: valid only under `project` in `myst.yml`
- **page can override project**: valid in both, with page values taking precedence

**In page frontmatter**: fields are top-level. For example:

```{code-block} md
:filename: page.md
---
edit_url: null
---
```

**In project-wide configuration**: fields are nested under the `project` key. For example:

```{code-block} yaml
:filename: myst.yml
project:
  edit_url: null
```

## All available frontmatter fields

```
/* Detailed source-code truncated for AI context efficiency. */
```

+++

(titles)=

## Titles

There are several fields to title MyST projects and pages. Primary page and project titles can be specified simply as `title`. Pages and projects also both have `short_title`; this should provide a summarized title in less than 40 characters. It is used where space is limited, for example a site navigation panel, running-head titles in an static export, etc. You may specify `subtitle`; this conveys complementary information to the title and may be displayed below the title.

````{note} Defining Page Title in Markdown

If `title` is not defined in the frontmatter, it will be pulled from the a heading at the top of the markdown instead. In this case, the heading will be removed from the content to the frontmatter for usage in a MyST site header or exported document title page.

```markdown
---
author: Marissa Myst
---

# My MyST Title

## Introduction

For this page, "My MyST Title" is the title!
...
```

If removing the title causes unexpected problems with the page formatting, you may set `title: null` in the frontmatter to prevent heading removal. The first heading will _still_ be copied as a placeholder title, but it will not be removed from the markdown. However, in these cases, it is probably easiest to simply define a title in frontmatter!
````

+++

(thumbnail-and-banner)=

## Thumbnail & Banner

The thumbnail is used in previews for your site in applications like Twitter, Slack, or any other link preview service. This should, by convention, be included in a `thumbnails` folder next to your content. You can also explicitly set this field to any other image on your local file system or a remote URL to an image. This image will get copied over to your public folder and optimized when you build your project.

```yaml
thumbnail: thumbnails/myThumbnail.png
```

If you do not specify an image the first image in the content of a page will be selected. If you explicitly do not want an image, set `thumbnail` to `null`.

You can also set a banner image which will show up in certain themes, for example, the `article-theme`:

```yaml
banner: banner.png
```

:::{figure} ./images/article-theme.png
:label: banner-example
Example of a banner in a site using the `article-theme`.
:::

(frontmatter:authors)=

## Authors

The `authors` field is a list of `author` objects. Available fields in the author object are:

````{list-table} Frontmatter information for authors
:header-rows: 1
:label: table-frontmatter-authors
* - Field
  - Description
* - `name`
  - a string OR CSL-JSON author object - the author's full name; if a string, this will be parsed automatically. Otherwise, the object may contain `given`, `surname`, `non_dropping_particle`, `dropping_particle`, `suffix`, and full name `literal`
* - `id`
  - a string - a local identifier that can be used to reference a repeated author
* - `orcid`
  - a string - a valid ORCID identifier with or without the URL
* - `corresponding`
  - boolean (true/false) - flags any corresponding authors, you must include an `email` if true.
* - `email`
  - a string - email of the author. Only displayed in the rendered output when `corresponding` is `true`. See [](#author:email)
* - `roles`
  - a list of strings - must be valid [CRediT Contributor Roles](https://credit.niso.org/). See [](#credit-roles) for more information.

    ```yaml
    authors:
      - name: Penny Crediton
        roles:
          - Conceptualization
          - Data curation
          - Validation
    ```
/* Detailed source-code truncated for AI context efficiency. */
```yaml
    authors:
      - name: Marissa Myst
        affiliations:
          - id: ubc
            institution: University of British Columbia
            ror: 03rmrcq20
            department: Earth, Ocean and Atmospheric Sciences
      	  - ACME Inc
      - name: Miles Mysterson
        affiliation: ubc
    ```

    See [](#affiliations) for more information on how to concisely write affiliations.
* - `equal_contributor`
  - a boolean (true/false), indicates that the author is an equal contributor
* - `deceased`
  - a boolean (true/false), indicates that the author is deceased
* - `note`
  - a string, a freeform field to indicate additional information about the author, for example, acknowledgments or specific correspondence information.
* - `phone`
  - a phone number, e.g. `(301) 754-5766`
* - `fax`
  - for people who still use these machines, beep, boop, beeeep! 📠🎶
* - `url`, `github`, and other social links
  - See @table-frontmatter-social-links for all social profile links for the author
````

(social-links)=

### Social Links

Contributors and affiliations can also have social links and URLs.

```{list-table} Social Links for contributors and affiliations.
:header-rows: 1
:label: table-frontmatter-social-links
* - Field
  - Description
* - `url`
  - a string - website or homepage of the author
* - `bluesky`
  - a Bluesky username or URL
* - `mastodon`
  - a Mastodon webfinger account (`@user@example.com`)
* - `threads`
  - a Threads/Instagram username
* - `linkedin`
  - a LinkedIn URL
* - `twitter` (or `x`)
  - an x/Twitter username (`user` or `@user`) or URL
* - `facebook`
  - a Facebook URL
* - `discord`
  - a Discord URL
* - `youtube`
  - a YouTube handle (`@handle`) or URL
* - `discourse`
  - a Discourse URL
* - `slack`
  - a Slack URL
* - `github`
  - a GitHub username (`@user` or `user`), repository (`ORG/REPO`) or organization URL (`https://github.com/orgs/ORG`)
```

### Affiliations

Below are all the possible fields for frontmatter affiliations.

````{list-table} Frontmatter information for affiliations
:header-rows: 1
:label: table-frontmatter-affiliations
* - Field
  - Description
* - `id`
  - a string - a local identifier that can be used to reference a repeated affiliation
* - `name`
  - a string - the affiliation name. Either `name` or `institution` is required
* - `institution`
  - a string - Name of an institution or organization (for example, a university or corporation)

    If your research group has a name, you can use both `name` and `institution`,
    however, at least one of these is required.
* - `department`
  - a string - the affiliation department (e.g. Chemistry 🧪)
* - `doi`, `ror`, `isni`, `ringgold`
  - Identifiers for the affiliation (DOI, ROR, ISNI, and Ringgold).

    We suggest using https://ror.org if possible to search for your institution.

    ```yaml
    affiliations:
      - name: Boston University
        ringgold: 1846
        isni: 0000 0004 1936 7558
        ror: 05qwgg493
        doi: 10.13039/100018578
    ```
* - `email`
  - a string - email of the affiliation, required if `corresponding` is `true`
* - `address`, `city`, `state`, `postal_code`, and `country`
  - affiliation address information. In place of `state` you can use `province` or `region`.
* - `url`, `github`, and other social links
  - See @table-frontmatter-social-links for all social profile links for the affiliation
* - `phone`
  - a phone number, e.g. `(301) 754-5766`
* - `fax`
  - A fax number for the affiliation
* - `collaboration`
  - a boolean - Indicate that this affiliation is a collaboration, for example, `"MyST Contributors"` can be both an affiliation and a listed author. This is used in certain templates as well as in [JATS](https://jats.nlm.nih.gov/archiving/tag-library/1.3/element/collab.html).
````

## Date

The date field is a string and should conform to a well-defined calendar date.
It should be quoted most of the time for notebook frontmatter to avoid parsing issues on the Jupyter side.
Examples of acceptable date formats are:

- `"2022-12-14"` - `YYYY-MM-DD`
- `"01 Jan 2000"` - `DD? MON YYYY`
- `Sat, 1 Jan 2000` - `DAY, DD? MON YYYY`

These dates correspond to two main formats:

- A strict (full, extended) calendar date defined by [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) (see also [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339))
- A date-only variant of [RFC 2822](https://datatracker.ietf.org/doc/html/rfc2822), built using the RFC gammar rules.

(frontmatter:exports)=

## Exports

Exports allow you to generate static versions of your MyST documents, often through intermediary build engines like Latex.
For usage information, see [](./documents-exports.md).

```{list-table} Frontmatter export definitions
:header-rows: 1
:label: table-frontmatter-exports
* - Field
  - Description
* - `id`
  - a string - a local identifier that can be used to reference the export
* - `format`
  - one of `pdf` (built with $\LaTeX$ or Typst, depending on the template), `tex` (raw $\LaTeX$ files), `pdf+tex` (both PDF and raw $\LaTeX$ files) `typst` (raw Typst files and built PDF file), `docx`, `md`, `jats`, or `meca`
* - `template`
  - a string - name of an existing [MyST template](https://github.com/myst-templates) or a local path to a template folder. Templates are only available for `pdf`, `tex`, `typst`, and `docx` formats.
* - `output`
  - a string - export output filename with a valid extension or destination folder
* - `zip`
  - a boolean - if `true`, zip the output - only applies for multi-file exports `tex`, `pdf+tex` and `typst`.
* - `articles`
  - a list of strings - path(s) to articles to include in your export - this is required for exports defined in project frontmatter; for page frontmatter, the default article will be the page itself. Not all exports currently support multiple articles.
* - `toc`
  - a string - path to jupyterbook `_toc.yml` file - may be used as an alternative to listing `articles`
* - `sub_articles`
  - a list of strings - path(s) to sub-articles for `jats` export
```

(frontmatter:downloads)=

## Downloads

Downloads allow you to include downloadable files with a MyST website.
They are specified in either:

+++ {"label": "frontmatter-downloads" }

In **project configuration**:

```{code-block} yaml
:filename: myst.yml
project:
  downloads:
    - file: ...
    - id: ...
```

In **page frontmatter**:

```{code-block} yaml
:filename: page.md
---
downloads:
  - file: ...
  - id: ...
---
```

+++

See [](./website-downloads.md) information about how to use this feature.
Below is a list of all possible downloads configuration.

```{list-table} Frontmatter download definitions
:header-rows: 1
:label: table-frontmatter-downloads
* - Field
  - Description
* - `id`
  - a string - reference to an existing `export` identifier. The referenced export may be defined in a different file. If `id` is defined, `file`/`url` are not allowed.
* - `file`
  - a string - a path to a local file. If `file` is defined, `id`/`url` are not allowed.
* - `url`
  - a string - either a full URL or a relative URL of a page in your MyST project. If `url` is defined, `id`/`file` are not allowed.
* - `title`
  - a string - title of the `downloads` entry. This will show up as text on the link in your MyST site. `title` is recommended for all downloads, but only required for `url` values; files will default to `filename` title
* - `filename`
  - a string - name of the file upon download. By default, this will match the original filename. `url` values do no require a `filename`; if provided, the `url` will be treated as a download link rather than page navigation.
* - `static`
  - a boolean - this is automatically set to `true` for local files and `false` otherwise. You may also explicitly set this to `false`; this will bypass any attempt to find the file locally and will keep the value for `url` exactly as it is provided.
```

(licenses)=

## Licenses

This field can be set to a string value directly or to a License object.

Available fields in the License object are `content` and `code` allowing licenses to be set separately for these two forms of content, as often different subsets of licenses are applicable to each. If you only wish to apply a single license to your page or project use the string form rather than an object.

If selecting a license from the [SPDX License List](https://spdx.org/licenses/), you may simply use the "Identifier" string; MyST will expand these identifiers into objects with `name`, `url`, and additional metadata related to open access ([OSI-approved](https://opensource.org/licenses), [FSF free](https://www.gnu.org/licenses/license-list.en.html), and [CC](https://creativecommons.org/)). Identifiers for well-known licenses are easily recognizable (e.g. `MIT` or `BSD`) and MyST will attempt to infer the specific identifier if an ambiguous license is specified (e.g. `GPL` will be interpreted as `GPL-3.0+` and a warning raised letting you know of this interpretation). Some common licenses are:

```{list-table}
:header-rows: 1
:label: table-common-licenses

* - Common Content Licenses
  - Common Code Licenses

* - - `CC-BY-4.0`
    - `CC-BY-SA-4.0`
    - `CC-BY-NC-SA-4.0`
    - `CC0-1.0`

  - - `MIT`
    - `BSD`
    - `GPL-3.0+`
    - `Apache-2.0`
    - `LGPL-3.0-or-later`
    - `AGPL`
```

By using the correct SPDX Identifier, your website will automatically use the appropriate icon for the license and link to the license definition. The simplest and most common example is something like:

```yaml
license: CC-BY-4.0
```

### Nonstandard licenses

Although not recommended, you may specify nonstandard licenses not found on the SPDX License List. For these, you may provide an object where available fields are `id`, `name`, `url`, and `note`. You can also extend the default SPDX Licenses by providing modified values for these fields. Here is a more complex example where content and code have different licenses; content uses an SPDX License with an additional note, and code uses a totally custom license.

```yaml
license:
  content:
    id: CC-BY-4.0
    note: When attributing this content, please indicate the Source was MyST Documentation.
  code:
    name: I Am Not A Lawyer License
    url: https://example.com/i-am-not-a-lawyer
```

(frontmatter:funding)=

## Funding

Funding frontmatter is able to contain multiple funding and open access statements, as well as award info.

It may be as simple as a single funding statement:

```yaml
funding: This work was supported by University.
```

Funding may also specify award id, name, sources ([affiliation object or reference](#affiliations)), investigators ([contributor objects or references](#other-contributors)), and recipients ([contributor objects or references](#other-contributors)).

```yaml
authors:
  - id: auth0
    name: Jane Doe
funding:
  statement: This work was supported by University.
  id: award-id-000
  name: My Award
  sources:
    - name: University
  investigators:
    - name: John Doe
  recipients:
    - auth0
```

Multiple funding objects with multiple awards are also possible:

```yaml
authors:
  - id: auth0
    name: Jane Doe
funding:
  - statement: This work was supported by University.
    awards:
      - id: award-id-000
        name: My First Award
        sources:
          - name: University
        investigators:
          - name: John Doe
        recipients:
          - auth0
      - id: award-id-001
        name: My Second Award
        sources:
          - name: University
        investigators:
          - name: John Doe
        recipients:
          - auth0
  - statement: Open access was supported by Consortium.
    open_access: Users are allowed to reproduce without prior permission
    awards:
      - id: open-award-999
        sources:
          - name: Consortium
```

## Venue

The term `venue` is borrowed from the [OpenAlex](https://docs.openalex.org/about-the-data/venue) API definition:

> Venues are where works are hosted.

For MyST frontmatter, the `venue` object holds metadata for journals and conferences where a work may be presented.

```{list-table} Available Venue fields
:header-rows: 1
:label: table-frontmatter-venue
* - Field
  - Description
* - `title`
  - full title of the venue
* - `short_title`
  - short title of the venue; often journals have a standard abbreviation that should be defined here
* - `url`
  - URL of the venue
* - `doi`
  - the _venue_ DOI
* - `number`
  - number of the venue in a series, for example the "18th Python in Science Conference"
* - `location`
  - physical location of a conference
* - `date`
  - date associated with the venue, for example the dates of a conference. This field is a string, not a timestamp, so it may be a date range.
* - `series`
  - title of a series that this venue or work is part of. Examples include a conference proceedings series, where each year a new conference-specific proceedings journal is created, or a category of articles across multiple issues, such as colloquium papers.
* - `issn`
  - ISSN for the publication
* - `publisher`
  - publisher of the journal
```

Some typical `venue` values may be:

```yaml
venue:
  title: Journal of Geophysics
  short_title: J. Geophys
  url: https://journal.geophysicsjournal.com
```

or

```yaml
venue:
  title: EuroSciPy 2022
  url: https://www.euroscipy.org/2022
```

(publication-metadata)=

## Publication Metadata

MyST includes several fields to maintain bibliographic metadata for journal publications. First, it has `first_page` and `last_page` - these are page numbers for the article in its printed form. Also, `volume` and `issue` are available to describe the journal volume/issue containing the article. Each of these properties has the same fields available, described in @table-frontmatter-biblio.

```{list-table} Available Volume and Issue fields
:header-rows: 1
:label: table-frontmatter-biblio
* - Field
  - Description
* - `number`
  - a string or a number to identify journal volume/issue
* - `title`
  - title of the volume/issue, if provided separately from number
* - `subject`
  - description of the subject of the volume/issue
* - `doi`
  - the volume/issue DOI
```

An example of publication metadata for an article may be:

```yaml
first_page: 1500
last_page: 1503
volume:
  number: 12
issue:
  name: Winter
  description: Special issue on software documentation
  doi: 10.62329/MYISSUE
```

These fields provide a more complete superset of publication metadata than the ["biblio" object defined by OpenAlex API](https://docs.openalex.org/api-entities/works/work-object#biblio):

> Old-timey bibliographic info for this work. This is mostly useful only in citation/reference contexts. These are all strings because sometimes you'll get fun values like "Spring" and "Inside cover."

If MyST frontmatter includes an OpenAlex `biblio` object, it will be coerced to valid publication metadata.

---

### Glossaries And Terms (`docs/glossaries-and-terms.md`)

---
title: Glossaries, Terms, Index Pages, and Abbreviations
short_title: Glossaries, Terms, & Index Pages
---

You can define Terms and generate reference pages for them with Glossaries and Index Pages. This allows you to centralize definitions and pointers to where various items are mentioned throughout your documents.

:::{seealso} See our index and glossary page

- The [glossary for these docs](#glossary-page)
- The [index for these docs](#index-page)

:::

## Glossaries

Glossaries are a collection of definitions for Terms in your documents.
Below is the example of a glossary defining the terms {term}`glossary`, {term}`term`, and {term}`Index`

:::{glossary}
glossary
: A glossary is a [list of terms and their definitions](https://en.wikipedia.org/wiki/Glossary).

term
: A term is a [word with a specialized meaning](https://en.wikipedia.org/wiki/Terminology).

index
: An [organized list of information in a publication](<https://en.wikipedia.org/wiki/Index_(publishing)>).

index entry
: A word or phrase that has been marked for inclusion in the index with the `index` directive or role.
:::

To add a glossary to your content, add the {myst:directive}`glossary` directive with the content as [definition lists](#definition-lists).

```{myst}
:::{glossary}
MyST
: An amazing markup language that supports glossaries
:::

You can use {term}`MyST` to create glossaries.
```

You can define multiple glossaries in your documents, as long as they do not re-define the same term.

:::{warning} Compatibility with {term}`Sphinx` and {term}`reStructuredText`
:class: dropdown
The glossary is very similar to the [reStructuredText glossary](https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#glossary), but uses [definition lists](#definition-lists) instead of indentation to indicate the terms[^drawback]. For working with glossaries in Sphinx, you can use the following syntax:

````markdown
```{glossary}
Term one
  An indented explanation of term 1

A second term
  An indented explanation of term 2
```
````

[^drawback]: Note that this has a challenge of not being able to have two terms for the same definition.

:::

## Terms

To reference a term in a glossary use the {myst:role}`term` role:

- `` {term}`MyST` `` produces {term}`MyST`
- `` {term}`MyST Markdown <MyST>` `` produces {term}`MyST Markdown <MyST>`

The label that you use for the term should be in the same case/spacing as it appears in the glossary. If there is additional syntax (e.g. a link) in the term, the text only representation will be used. The term is rendered as a cross-reference to the glossary and will provide a hover-reference.

## Index pages

Index pages show the location of various terms and phrases you define throughout your documentation.
They will show an alphabetized pointer to all {term}`Terms <term>` and {term}`Index entries <index entry>` that you define.

### Index entry directive

:::{warning}

The existing syntax for `index` directives and `index` roles has been taken directly from [Sphinx](https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#index-generating-markup). An improved MyST-specific syntax will likely be added in the future, and this Sphinx syntax may be removed.
:::

You can define index entries with Directives like so:

```
:::{index} my first index item
:::
```

% This won't show up in the content
:::{index} my first index item
:::

In this case, no text will be displayed with the directive, but an index entry will be created in your index that points to the location of the directive.

You can define a nested index entry with a semicolon (`;`)

```
:::{index} index parent; index child
:::
```

% This won't show up in the content
:::{index} index parent; index child
:::

Also, you can define multiple, non-nested index entries in the directive argument by delimiting with a comma:

```
:::{index} index one, index two, index three
:::
```

#### Pairs and Triples

You can generate two reciprocal, nested index entries with `pair:`, like so:

```
:::{index}
pair: index one; index two
:::
```

or for three related items:

```
:::{index}
triple: index one; index two; index three
:::
```

You can define multiple index entries in a single directive by putting them on multiple lines. In this case each entry must have a prefix of (`single`, `pair`, or `triple` to distinguish what specific nested entries are created).

```
:::{index}
single: index one
single: index parent; index child
pair: index two; index three
pair: index four; index five
triple: index six; index seven; index eight
:::
```

#### See and See Also

For one index entry to reference another index entry, you may use the `see` or `seealso` prefix. For example,

```
:::{index}
see: index 1; index one
:::
```

This creates an entry like "_index 1_: See _index one_"

The prefix `seealso:` behaves identically but uses the text "See also" instead of "See."

#### Emphasis

To emphasize any index entry, add an exclamation point before the index term. This will style the entry as either bold or italic and move it before other entries that refer to the same term but are not emphasized.

```
:::{index} ! index one
:::
```

### Index entry role

You can define an index entry with a role like so: `` {index}`my second index` ``.
This includes the text "{index}`my second index`" in your content and creates an entry.

If you want the text to be different than the index entry, you may use the syntax `` {index}`text on the page <index term>` ``.

Index roles can use all the same prefixes as described for the `{index}` directive, including `single`, `pair`, `triple`, `see`, and `seealso`. For example, `` {index}`pair: index one; index two` `` or `` {index}`text on the page <pair: index one; index two>` ``.

### Generate an index

You can show an index on a MyST page with the `{show-index}` directive.
For example:

````
```{show-index}
```
````

See [the index for this documentation](#index-page) for what this generates.

(abbreviations)=

## Abbreviations

To create an abbreviation, you can explicitly do this in your document with an [abbreviation role](#abbr-role), for example, `` {abbr}`HR (Heart Rate)` ``. You can also use the page or project frontmatter:

```{myst}

---
abbreviations:
  RHR: Resting Heart Rate
  HR: Human Resources
---

To lower your RHR, try meditating or contact your local HR representative?
```

The abbreviations are case-sensitive and will replace all instances[^1] in your document with a hover-tooltip and accessibility improvements. Abbreviations in cross-references, code, and links are not replaced. For example, in this project we have a lot of abbreviations defined in our [`myst.yml`](./myst.yml):

[^1]: Abbreviations must be at least two characters!

> Our OA journal ensures your VoR is JATS XML with a PID (usually a DOI) to ensure LTS.
>
> - TLA Soup

### Order of Abbreviations

Abbreviations defined in your frontmatter are applied in longest-sorted order. If you have two abbreviations with the same suffix (e.g. `RHR` and `HR`), the longer abbreviation will always take precedence.
To have longer abbreviations **not** be transformed, or if that string is included in another word, explicitly set them to `null` in your frontmatter. In the following example, `HTML` will not have the letters `ML` as an abbreviation.

```{myst}

---
abbreviations:
  ML: Machine Learning
  HTML: null
---

We use ML to parse HTML.
```

---

### Glossary (`docs/glossary.md`)

---
title: Glossary & Index
description: Glossary of terms used throughout the MyST ecosystem.
---

(glossary-page)=

## Glossary

:::{glossary}

[CommonMark](https://commonmark.org/)
: A standard syntax of Markdown that is used across many communities and projects.
It is the base flavour of Markdown for Jupyter Notebook, and the base flavour
for {term}`MyST Markdown <MyST>` and {term}`Jupyter Book`.

[Project Jupyter](https://jupyter.org)
: The project and [team](https://compass.jupyterbook.org/team) that supports {term}`Jupyter Book` and {term}`MyST Markdown <MyST>` and the tools and packages behind them.

[Executable Books Project](https://executablebooks.org)
: The project and [team](https://compass.executablebooks.org/en/latest/team/index.html) that used to support {term}`Jupyter Book` and {term}`MyST Markdown <MyST>`. The project is currently stewarded by {term}`Project Jupyter`.

[MyST](https://mystmd.org)
: MyST can either refer to {term}`MyST Markdown` or {term}`MyST-CLI`.

[MyST Markdown](https://mystmd.org)
: A flavour of Markdown that was designed for scientific and technical writing.
: Sometimes referred to simply as {term}`MyST`.

[MyST-CLI](https://mystmd.org/guide)
: The MyST Markdown CLI can be used to create a website, PDF documents, and generally structure and parse a MyST project. You can install across various package managers using `mystmd`.
: Sometimes referred to simply as {term}`MyST`.

[Sphinx](https://www.sphinx-doc.org)
: A documentation engine written in Python. Sphinx supports many features that are
necessary for scientific and scholarly publishing. It is currently used by {term}`Jupyter Book`.

[reStructuredText](https://docutils.sourceforge.io/rst.html)
: reStructuredText (RST) is a plain text markup syntax and parser system, the RST parser is a component of Docutils.

[Binder](https://mybinder.org)
: A free, public service for running reproducible interactive computing environments.
Binder is a 100% open source infrastructure that is run by members of the Jupyter
community. The underlying technology behind the Binder project is {term}`BinderHub`.

[BinderHub](https://binderhub.readthedocs.io)
: The underlying technology of <https://mybinder.org>, BinderHub is an open source tool that
runs on Kubernetes and utilizes a {term}`JupyterHub` in order to provide live, reproducible
interactive computing environments that users host on GitHub.

[Google Colab](https://colab.research.google.com/)
: A Jupyter Notebook service from Google that provides access to free computing resources,
including GPUs and TPUs.

[JupyterHub](https://jupyterhub.readthedocs.io/en/stable/)
: A core open source tool from the Jupyter community, JupyterHub allows you to
deploy an application that provides remote data science environments to multiple
users. It can be deployed in the cloud, or on your own hardware.

[Jupyter Book](https://jupyterbook.org/)
: Jupyter Book is a distribution of {term}`Sphinx` that allows you to write content
in markdown and Jupyter Notebooks, execute content and insert it into your book,
and build a variety of outputs for interactivity and document publishing.

MyST Markdown
: MyST stands for "Markedly Structured Text". It is a flavor of [Markdown](https://en.wikipedia.org/wiki/Markdown) that was designed to make it easy to write content that can be parsed by a {term}`MyST Document Engine`. MyST Markdown syntax was created to support functionality in the MyST specification like extensions, roles and directives, and cross-references. It was originally created for Jupyter Book via the [MyST Parser for Sphinx](https://myst-parser.readthedocs.io), but now serves as a standard markdown syntax across the MyST ecosystem.

MyST Document Engine
: A MyST Document Engine builds {term}`MyST AST` according to the {term}`MyST Specification`[^myst]. For example, a MyST Document Engine might know how to transform a text file written in {term}`MyST Markdown` into JSON output that follows the {term}`MyST Specification`. The official MyST Document Engine is documented at [mystmd.org/guide](https://mystmd.org/guide), and is maintained by the [Jupyter Book team](https://compass.jupyterbook.org)

[^myst]: Often we focus upon a MyST Engine's ability to parse {term}`MyST Markdown`. However, a MyST Engine may consume _any_ kind of input markup as long as the _result_ is a {term}`MyST AST` that follows the {term}`MyST Specification`. This is why the [official MyST Document Engine](https://mystmd.org) can parse other kinds of markup, such as a subset of LaTeX.

MyST Specification
: A specification that describes the structure and function of the MysT AST. It provides a framework for defining all of the kinds of content and metadata that a MyST document can contain. For example, the MyST specification defines how sections can contain paragraphs, how paragraphs can contain sentences, and how sentences can contain a "bolded" chunk of text. The specification is [defined at mystmd.org/spec](xref:spec#overview).

MyST AST
: A structured representation of a MyST Document, typically built from a markup language (like MyST Markdown) by a {term}`MyST Document Engine`, that adheres to the {term}`MyST Specification`. Usually, a MyST [Abstract Syntax Tree (AST)](wiki:Abstract_syntax_tree) is represented as a JSON data structure, with metadata attached to each piece of content that describes its role, relationships with other content, etc. The AST allows us to separate the steps of parsing content (such as {term}`MyST Markdown`) from generating output like HTML, PDF, docx, etc. For an introduction to its structure, see the [AST primer](xref:spec/ast-primer).

AST node
: A single node in the {term}`MyST AST`. It has an explicit `type` and contains 0 or more children.

Root AST node
: The top-level {term}`node <AST node>` in the {term}`MyST AST`. Its `type` is `"root"`.
A MyST AST can contain only one node with a `type` of `"root"`.

MyST Renderer
: An application that consumes {term}`MyST AST` and uses it to present the contents in a particular format. For example, the MyST Document Engine has a few built-in renderers. See [the HTML renderer](https://github.com/jupyter-book/mystmd/tree/840265e0c055d29b5d5ce80f391ccb1efba7a87e/packages/myst-to-html) for an example that converts {term}`MyST AST` to HTML.

MyST Theme
: A template for converting {term}`MyST AST` into structured output using a {term}`MyST Renderer`. For example, a theme provides the structure and rules by which you could convert {term}`MyST AST` to different kinds of LaTeX output based on a number of different journal templates. It could also be a way of converting {term}`MyST AST` into different kinds of HTML for various kinds of websites. The [MyST Templates GitHub Organization](https://github.com/myst-templates) is a community-maintained resource for many kinds of themes / templates.
:::

(index-page)=

## Index

```{show-index}

```

---

### Guiding Principles (`docs/guiding-principles.md`)

---
title: Guiding principles of MyST
description: A collection of ideas that helps guide the direction and decisions of the MyST ecosystem of tools.
---

This document describes some high-level principles that the MyST community follows in designing technology and deciding where we are going.
It is meant to align our team on the big ideas guiding the project, and provide visibility to others for the impact we're trying to have and where we are heading.


:::{note} This will evolve!
Our guiding principles are a constant work-in-progress, and will evolve as the community better-understands its opportunities and goals.
:::

## Who is MyST for and what problem does MyST try to solve? 

MyST builds composable tools and standards for people that communicate technical and computational narratives. These people need to communicate _throughout_ the lifecycle of discovery and learning, both within their local networks and to broader communities. Below are several key problems that MyST aims to solve for this group:

**Communicating with data:** These problems apply to data scientists in general.

- There is no document standard and engine that is well-defined, broadly adopted, and integrated with modern data science workflows. This results in a variety of formats for communication, which introduces friction to learning and re-using other people’s ideas and data.
- Tools for interactive computing (like Jupyter Notebooks or JupyterLab) focus primarily on data exploration and discovery. Tools specifically designed for authoring and reading tend to be created by different communities, and thus do not integrate with data science workflows. 
- Tools for communicating tend to have strong assumptions about the output format (e.g. HTML or PDF) or about the use-case (e.g., publishing in peer-reviewed journals vs. collectively-written documentation), which leads to workflow-specific tools that are not interoperable.

**Scholarly publishing:** Because of the scholarly community’s unique relationship with journals, we define several problems unique to this area that we design for:

- The publishing ecosystem is fractured, with a variety of formats and technology standards primarily focused on print-based mediums (e.g. PDFs). Authors lose time reformatting their content according to publisher needs, and static mediums do not well represent computational data.
- Tools for publishing and communication are often distinct from the tools used for exploration and analysis. This makes it harder for computation to inform the scholarship, and creates artificial barriers between the analyses that define and reproduce ideas, and the scholarship that describes ideas.
- Publishing systems are strongly linked to large-scale publishers, and do not optimize for accessible re-use of content. This makes it harder for researchers to learn and re-use one another's ideas.


## How does MyST uniquely solve this problem?

_What's the approach MyST takes that uniquely solves the problem(s) above? For example:_

- **Provide a reusable Source of Truth.** Define a "source of truth" document structure that is the primary output of MyST's build engine, and that can be flexibly rendered into many output formats.
- **Computation is a first class citizen.** Define a document standard that treats computational elements as first-class citizens, and provides an excellent web-native interface, allowing authors to bring their ideas to life with interactive computation.
- **Continuous communication throughout the data science lifecycle.** Build on pre-existing community standards for computational analysis, to ensure interoperability with pre-existing workflows and to allow users to communicate _via_ these workflows rather than adopting significant new ones. We integrate with the Jupyter ecosystem because it is an industry standard in interactive computing for data exploration and discovery. 
- **Extension points and customization get users over the last mile.** Don’t design MyST for specific scientific domains or questions, and provide tools that are broadly useful and composable. Create tools and standards that facilitate interoperability and enable customization so that users can extend MyST’s functionality for their specific needs.
- **Community-led tools and standards.** MyST should be led by its community in order to ensure it continues to represent the interests of its community members, and is not driven by a single stakeholder or organization.

**Design principles to promote a rich and interconnected scientific commons.**

- **Promote open science practices via good UX.** As a general guiding principle, encourage users to adopt best practices by removing friction, offering an excellent user experience, and incentivizing them with useful functionality. Assume users will use what gives them the best experience and features, and bring open science workflows throughout.
- **Pull for reproducibility through interactivity.** Build compelling ways for researchers to integrate computation into their narratives; this interactivity requires reproducible practices to be adopted and maintained.
- **Adding metadata and links creates immediate value.** We design features that encourage and showcase additional information when authors provide valuable metadata (DOIs, ORCIDs, RORs) as well as cross-reference other resources. For example, by pulling in references dynamically and providing rich hover information and contextual information.
- **Data should be easier to add than markup.** Given the choice of, for example, writing a text only reference in APA style or adding a single markdown link to a DOI, encourage authors to choose to work with data and linked metadata services. Our tools should encourage and reinforce using data as the primary source of information.
- **Bring contextual information to the reading experience.** The user interfaces we design should promote bringing information, such as equations, figures, abbreviations, citations, or terms and visualizations from another project directly into the reading experience. This design principle reinforces the community, standards-based ecosystem that we are curating.

## What does success look like for MyST?

We imagine a future where MyST is an industry-wide standard for communicating with computational narratives that provides a single toolchain for researchers to communicate their ideas wherever they wish.

## How do I pronounce MyST?

Here's an overly helpful collection of ways to say MyST:

Like the word "missed".

Like the [natural phenomenon caused by small droplets of water aerosols suspended in the cold air, usually by condensation](https://en.wikipedia.org/wiki/Mist).

Like [`/mɪst/`](https://dictionary.cambridge.org/us/pronunciation/english/mist).

Like [the video game](https://en.wikipedia.org/wiki/Myst).

---

### In Page Execution (`docs/in-page-execution.md`)

---
title: In-Page Execution
subtitle: Connecting Jupyter Kernels to your MyST website
description: MyST allows you to connect a website directly to a Jupyter Kernel, enabling interactive computation on your page.
thumbnail: thumbnails/integrating-jupyter.png
aliases:
  - integrating-jupyter
---

In-page execution allows you to connect a live Jupyter kernel to your website, allowing you to add interactive visualizations and interactivity that is powered with a live kernel. This allows your readers to reproduce the outputs of your document in real-time, and to add more complex interactive content via tools like [`ipywidgets`](https://ipywidgets.readthedocs.io/) or [Panel](https://github.com/holoviz/panel).

Here are a few back-ends that you can use to provide the computation for in-page execution:

- **Binder** (e.g., [mybinder.org](https://mybinder.org))
- **WASM-based in-browser kernels** with [JupyterLite](https://jupyterlite.readthedocs.io)
- **Local or remote Jupyter servers** you spin up locally or via a service like JupyterHub

```{attention} This is a beta feature
We are in active development and this feature should be considered `beta` - please help us out [report any issues that you find](https://github.com/jupyter-book/mystmd/issues).

Watch for the 🚧 icons on headings that are still work in progress.
```

## Enable in-page execution

To enable in-page execution, use the `project.jupyter: true` parameter like so:

```{code} yaml
:filename: myst.yml
version: 1
project:
  jupyter: true
```

By default, MyST will use [mybinder.org](https://mybinder.org) to build and provide the environment for computation. It will use the [`thebe-binder-base` repository](https://github.com/executablebooks/thebe-binder-base) to build the environment. If you have a GitHub repository defined for your project via `project.github`, then it will use that instead.

### Launch in-page execution

To launch in-page execution on the page, press the "power" button at the top of the page content.

This will launch a Binder session (or, [connect to a live Jupyter server](#thebe-jupyter-server) based on your configuration). If you launch a Binder server, you'll see a box in the bottom-right of the page showing the status of Binder launching your session.

You'll know that execution is now available when the in-page execution panel is visible at the top of the page. It looks like this:

```{figure} ./images/thebe-control-panel.png
This panel allows you to control the execution on the current page.
```

In addition, all cells on the page will execute when the server is available.

### Launch into the interactive Jupyter server

To change the browser window to the fully interactive Jupyter server that is powering your computation, click the "Launch Jupyter Server Window" button to the right of the in-page execution panel.

```{figure} ./images/thebe-control-panel.png
The right-most button will take you to the fully interactive Jupyter Server.
```

## Binder configuration options

By default, in-page computation uses a BinderHub service to provide computation.

### Options for Binder configuration

```{list-table}
:header-rows: 1

* - key
  - required?
  - description
  - default
* - `repo`
  - required
  - The repository to use as a base image for your Jupyter server as a `owner/reponame` string or a fully qualified url. See [](#binder-option-repository).
  - `executablebooks/thebe-binder-base`
* - `ref`
  - optional
  - The git ref to use from the repository, allow you to target a specific branch, tag or commit. See [](#binder-option-branch).
  - `HEAD`
* - `url`
  - optional
  - The base url of the binder service to connect to. See [](#binder-option-service).
  - `mybinder.org`
* - `provider`
  - optional
  - Tells `thebe` how to form urls for requesting binder services. Can be one of `github`, `gitlab` or `git`. See [](#binder-option-repoprovider).
  - `github`
```

```{attention} Be aware of multiple keys
There are two possible locations for `binder` keys:

1. `project.binder` is for [launch button configuration](./website-launch-buttons.md), and will take the user to a new page with a Binder session.
2. `project.jupyter.binder` is for in-page computation described here.
```

(binder-option-repository)=

### Choose the repository for your kernel environment

To choose the repository that is used for your kernel, use the `project.jupyter.binder.repo` key. Here's an example:

```{code} yaml
:filename: myst.yml
project:
  jupyter:
    binder:
      repo: https://github.com/binder-examples/requirements # default repo
```

By default, MyST will use the `HEAD` of the repository, which usually corresponds to the `main` branch. To choose a different branch, see [](#in-page-computation-choose-branch).

````{tip} Equivalent Syntax
:class: dropdown
The following cases are all equivalent:

```yaml
project:
  jupyter: true
```

```yaml
project:
  jupyter: 'binder'
```

```yaml
project:
  jupyter:
    binder: true
```

```yaml
project:
  jupyter:
    binder:
      repo: executablebooks/thebe-binder-base # default repo
```

```yaml
project:
  jupyter:
    binder:
      repo: https://github.com/executablebooks/thebe-binder-base # default repo
```

````

(binder-option-branch)=

### Choose a branch or ref for your environment

To choose a branch or git ref other than the default (`HEAD`), use the `ref` key like so:

```{code} yaml
---
filename: myst.yml
caption: A complete `thebe.binder` configuration
---
project:
  jupyter:
    binder:
      # ref can be the name of a branch or a commit hash
      ref: my-branch
```

(binder-option-service)=

### Choose the BinderHub service for computation

To choose a BinderHub service other than [mybinder.org](https://mybinder.org), use configuration like so:

```{code} yaml
---
filename: myst.yml
caption: A complete `thebe.binder` configuration
---
project:
  jupyter:
    binder:
      # The URL parameter controls the BinderHub serviec to use.
      url: https://binder.myorganisation.com/services/binder/
```

(binder-option-repoprovider)=

### Choose a repository provider other than GitHub

To choose a git repository provider other than GitHub, use the `provider` key like so:

```{code} yaml
---
filename: myst.yml
caption: A complete `thebe.binder` configuration
---
project:
  jupyter:
    binder:
      # See below for a list of available providers
      provider: gitlab
```

### Configure my Binder repository environment

See [the Binder documentation](https://docs.mybinder.org) for instructions on how to set up your repository to have the environment you need. Binder uses the [Reproducible Execution Environment Specification](https://repo2docker.readthedocs.io/en/latest/specification.html) to turn repository contents into a reproducible environment.

(thebe-jupyter-server)=

## Use a local or remote Jupyter server for in-page execution

If you have access to a Jupyter server that is already running (for example, by starting a server locally, or accessing a server via a JupyterHub), you can use this to provide in-page computation instead of Binder.

To use a server that is already running locally, use the `jupyter.server` key like so:

```{code-block} yaml
---
filename: myst.yml
caption: A unique connection token must be supplied to connect to a local server
---
project:
  jupyter:
    server:
      url: http://localhost:8888/
      token: <your-secret-token>
```

```{list-table} The configuration options and their defaults for local kernel computation.
:header-rows: 1

* - key
  - description
  - default
* - `url`
  - The base url of the Jupyter server you want to connect to
  - `http://localhost:8888`
* - `token`
  - The secret token string required by your Jupyter server
```

(start-a-local-jupyter-server)=

### Start a local Jupyter server for in-page computation

In addition to how you might normally start a JupyterLab session, it's necessary to provide two additional command line options, as follows.

```{code} bash
jupyter lab --NotebookApp.token=<your-secret-token> --NotebookApp.allow_origin='http://localhost:3000'
```

The command above is fine for local development. The `token` used should align with that provided in the `project.thebe.token` key and `allow_origin` should allow connections from your myst site preview, usually running on `http://localhost:3000`.

When starting a local Jupyter server for use with MyST it's also important to understand your computational environment and ensure that the Jupyter instance has access to that with the dependencies it needs to run. This is achieved by following normal best practices for reproducible environment configuration, if you're not familiar with these see [REES](https://repo2docker.readthedocs.io/en/latest/specification.html).

```{danger} Securing a Jupyter server
:class: dropdown
If you intend to run a dedicated single user Jupyter server accessible over a network please carefully read and follow [the advice provided by the Jupyter server team here](https://jupyter-server.readthedocs.io/en/stable/operators/security.html).

MyST Websites will work best, be safer and be more robust when backed by Jupyter services such as BinderHub or JupyterHub.
```

(jupyterlite)=

## Use JupyterLite and WebAssembly for in-page computation

The [JupyterLite project](https://jupyterlite.readthedocs.io/en/latest/) allows you to ship a lightweight computational environment that runs fully in your browser. To use JupyterLite for your in-page computation, use the configuration below:

```{code} yaml
project:
  jupyter:
    lite: true
```

This will load the server using the default environment described in the [JupyterLite docs](https://jupyterlite.readthedocs.io/en/latest/). For more configuration options with JupyterLite, see [](#jupyterlite).

```{important} TODO
Add the specific list options for custom wheel paths, etc.
```

## Enable or disable in-page computation on a single page

To configure in-page computation on a single page, use [document frontmatter](./frontmatter.md). For example:

To **enable in-page computation on a single page**, use configuration like so:

```{code} markdown
:filename: mypage.ipynb
---
jupyter:
  binder:
    # If you had one page that needed an R kernel
    repo: https://github.com/binder-examples/r
---

My page content.
```

To **disable in-page computation on a single page**, use configuration like so:

```{code} markdown
:filename: mypage.md
---
jupyter: false
---

My page content.
```

## Reference

### Complete options schema

```{code-block} yaml
project:
  jupyter: undefined(false) | boolean | object | 'lite' | 'binder'
    lite: boolean
    binder: undefined(false) | boolean | object
      url: string (url)
      provider: string (git | gitlab | github | or custom)
      repo: string (org-name/repo-name | url | string)
      ref: string (undefined | string)
    server:  undefined | object
      url: string (url)
      token: string (any)
    kernelName: string (any)
    disableSessionSaving: boolean (default: false)
    mathjaxUrl: string (url)
    mathjaxConfig: string (any)
```

### Additional options

The following keys can all be used under the `project.jupyter` configuration.

```{list-table}
:header-rows: 1

* - `key`
  - description
  - default
* - `kernelName`
  - The name of the kernel to request when starting a session
  - `python`
* - `disableSessionSaving`
  - When `false` (default) any server settings received from `binder` will be cached in local storage. On page refresh or future page load the save session info will be used provided the session is still activate and the max age (86400s) has not been exceeded
  - `false`
* - `mathjaxUrl`
  - Allows the default mathjax bundle loaded by the Jupyter Latex Typesetter to be changed
  - Mathjax 2.7.5 from `cdnjs.cloudflare`[^mathjax]
* - `mathjaxConfig`
  - Allows the default mathjax configuration string to be changed
  - `TeX-AMS_CHTML-full,Safe`
```

[^mathjax]: `https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js`

---

### Inline Options (`docs/inline-options.md`)

---
title: Inline Options
subtitle: Concise specification of CSS classes, IDs, and attributes
description: MyST Markdown has support for inline attributes for both roles and directives, allowing concise specification of CSS classes, IDs, and attributes. This complements other methods for defining options, making markup more expressive and flexible.
# thumbnail: thumbnails/inline-options.png
---

:::{warning} Inline Options are in Beta
The support for inline attributes is in beta and may have some bugs or limitations.
Please give feedback on [GitHub](https://github.com/orgs/jupyter-book/discussions).
:::

MyST Markdown has support for inline attributes for both roles and directives, allowing concise specification of CSS classes, IDs, and attributes. This complements other methods for defining options, making markup more expressive and flexible.

```markdown
:::{tip .dropdown open="true"} Title
Tip Content
:::
```

This can also be used for roles:

`` {span .text-red-500}`Red text` ``

{span .text-red-500}`Red text`

## Syntax Overview

The inline attribute syntax follows this pattern:

````text
{role #id .class key="value" key=value}`content`

```{directive #id .class key="value" key=value}
content
```
````

Name (e.g. `tip` or `cite:p`)
: The directive or role name must come first. There must only be a single "bare" token.

ID (`#id`)
: Defines the label/identifier of the node

Class (`.class`)
: Adds CSS class(es).

Quoted Attributes (`key="value"`)
: Supports attributes containing spaces or special characters.

Unquoted Attributes (`key=value` or `key=123`)
: Allows simpler attribute values when there are no spaces.

For directives, these can be mixed with other ways to define options on directives, classes are combined in a single space-separated string; other repeated directive options will raise a duplicate option warning.

---

### Install Node (`docs/install-node.md`)

---
title: Install NodeJS
subject: Advanced Installation
subtitle: Install the NodeJS runtime that powers MyST
description: The MyST Command Line Interface (CLI) is built on NodeJS, a JavaScript runtime that is widely used in many projects including well-known Python projects such as Jupyter Lab. MyST can be installed by the package manager npm, PyPI, Conda or Mamba.
---

The MyST Command Line Interface (CLI) is built on [NodeJS](https://nodejs.org/en/about) (`node`), a JavaScript runtime that is widely used in many projects including well-known Python projects such as Jupyter Lab. `node` comes with its own package manager called `npm`.

There are a number of ways to install `node` and you can choose one that is suitable depending on your platform and preferences.

:::{important} Node Versions

MyST currently supports `node` v22+. Note that odd-numbered releases of `node` are not long-lived and you should prefer even-numbered releases when installing (see [Node release schedule](https://nodejs.org/en/about/previous-releases)).
:::

Following any of the install methods below, verify your installation and ensure that `node` and `npm` are available on your system _PATH_ by opening a new terminal window or command line prompt and typing:

```shell
% node -v
vX.Y.Z
```

## Manual Installation (all platforms)

You can download an appropriate installer package for your platform by visiting <https://nodejs.org/>. _LTS_ refers to the current _Long Term Support_ version of `nodejs` and is the best choice for use with MyST.

Download the installer package, and follow instructions to execute the installer for your platform. The installer will automatically add `node` and `npm` to your system PATH.

🛠️ Next, up [Installing MyST](./installing.md)

## `node` via `conda` / `mamba` (all platforms)

`nodejs` is available as a package on `conda-forge`, although a limited number of versions are available on that channel. If you are a `conda` user, installation is straightforward but please note that MyST requires even-numbered node versions, and odd-numbered releases can be found on `conda-forge`.

🛠️ The following command can be used to lock down the version you are installing, adjust as necessary for the even-numbered version you are targeting:

```shell
(my-conda-env)% conda install -c conda-forge 'nodejs=24.*'
(my-conda-env)% node -v
v24.YY.Z
```

💡 Alternatively, you can create a new `conda` environment directly as a `node` environment:

```shell
% conda create -yn my-node-env 'nodejs>=20,<21'
% ....
#
# To activate this environment, use
#
#     $ conda activate my-node-env
#
# To deactivate an active environment, use
#
#     $ conda deactivate
```

🛠️ Next, up [Installing MyST](./installing.md)

## `nodeenv` via pip (all platforms)

`nodeenv` is a python package allowing you to create and manage `node` installations on your system via virtual environments. If you want to work in virtual environments for `node` alongside your python `virtualenv` this is the way to go.

🛠️ Install `nodeenv`\:

```shell
% pip install nodeenv
```

🛠️ Query available node versions:

```shell
% nodeenv --list
% ... XX.YY.Z ...
```

🛠️ Create a new environment based on a specific `node` version, and activate it:

```shell
% nodeenv -n XX.YY.Z node_env
% . node_env/bin/activate
(node_env) % node -v
vXX.YY.Z
```

Read more about `nodeenv` in [their docs](https://ekalinin.github.io/nodeenv/).

🛠️ Next, up [Installing MyST](./installing.md)

## Node Version Manager - Linux/MacOS (`nvm`)

`nvm` is a convenient way to manage multiple node installations on a POSIX compatible system.

🛠️ Install `nvm` using the install script ([docs](https://github.com/nvm-sh/nvm#installing-and-updating)):

```shell
% curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | bash
% nvm -v
0.40.8
```

💡 Note: on MacOS you can also install `nvm` via `brew`

🛠️ Next, install an initial (default) version of `node`\:

```shell
% nvm install 24
Downloading and installing node v24.YY.Z...
...
Now using node v24.YY.Z (npm vXX.YY.Z
%
```

Read more about `nvm` in [their docs](https://github.com/nvm-sh/nvm).

---

### Installing (`docs/installing.md`)

---
title: Install the MyST Markdown Command Line Interface
subtitle: Install the MyST CLI using your favourite package manager
short_title: Install MyST
description: MyST Markdown is available through Node and npm, install the package with `npm install mystmd`.
---

To install the MyST CLI, choose your preferred package manager. If you do not know what a package manager is, _it is recommended that you install MyST with `mamba` from conda-forge_.

(installing-myst-tabs)=
:::::{tab-set}
(installing-conda-forge)=
::::{tab-item} conda-forge

You can install using `mamba` (<https://mamba.readthedocs.io>), see [Getting started with Miniforge](xref:biapol#ref:miniforge_python).

🛠 Then install `mystmd` from `conda-forge`:

```shell
mamba install -c conda-forge mystmd
```

You may also use [conda](https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html) which comes packaged with the [Anaconda](https://www.anaconda.com/download/success) python distribution.

🛠 Then install `mystmd` from `conda-forge`:

```shell
conda install -c conda-forge mystmd
```

::::
::::{tab-item} PyPI

🛠 Install `mystmd`:

```shell
pip install mystmd
```

🛠 Ensure `mystmd` is ready for use:

MyST needs `node` (<https://nodejs.org>) in order to run correctly. If `node` is not already installed, starting `myst` will prompt you to install it:

```shell
$ myst -v
Node.js (node) is required to run MyST, but could not be found.
Install Node.js in '/root/.local/share/myst/XX.YY.Z'? (y/N): y
Attempting to install Node.js in /root/.local/share/myst/XX.YY.Z ...
Successfully installed Node.js XX.YY.Z
...
```

:::{note} Installing Node.js Manually
:class: dropdown

The `mystmd` package on PyPI ships with the ability to install `node` (<https://nodejs.org>). If you would prefer to install NodeJS manually, see [Installing NodeJS](./install-node.md):
:::

::::
::::{tab-item} NPM

Ensure your `node` (<https://nodejs.org>) is up to date, see [Installing NodeJS](./install-node.md).

🛠 Then install `mystmd` using npm, yarn or pnpm:

```shell
npm install mystmd
```

::::
:::::

This will install `myst` globally (`-g`) on your system and add a link to the main CLI tool. To see if things worked, try checking the version with:

```shell
myst --version
```

This command should print the current version of the package. If all is good, you can type `myst` again in your terminal and it will list the help with all of the options available to you.

```{note}
If you have any challenges installing, please [open an issue here](https://github.com/jupyter-book/mystmd/issues).
```

## Dependencies for $\LaTeX$ and PDF

If you are exporting to $\LaTeX$ with an open-source template specified (see all [templates](https://github.com/myst-templates)) or if you are creating a PDF you will need to install a version of [LaTeX](https://www.latex-project.org/get).

:::::{tab-set}
::::{tab-item} conda-forge

🛠 Install `mamba` (<https://mamba.readthedocs.io>), see <xref:biapol#ref:miniforge_python>.

```shell
$ mamba --version
mamba 1.5.8
conda 24.7.1
```

🛠 Install `texlive-core`, `latexmk`, and `imagemagick` from `conda-forge`:

```shell
$ mamba install -c conda-forge texlive-core latexmk imagemagick
```

`imagemagick` is optional, but recommended if your documents include images that need conversion for PDF output.

For Debian or Ubuntu based systems, the equivalent packages commonly include `texlive-xetex`, `texlive-fonts-recommended`, `texlive-plain-generic`, `latexmk`, and `imagemagick`.

::::
:::::

---

### Javascript Plugins (`docs/javascript-plugins.md`)

---
title: JavaScript Plugins
description: Plugins implemented in JavaScript are easily used across different projects, as they do not require any additional programs to be installed.
---

JavaScript plugins are native MyST plugins, which are loaded as modules into the MyST engine. Transforms defined in these modules have access to helpful AST manipulation routines made available by MyST. Edits to JavaScript plugins have no effect during execution of a MyST build, instead the build must be restarted.

(defining-a-new-directive)=
## Defining a new directive

To create a plugin, you will need a single JavaScript file[^esm] that exports one or more of the objects above. For example, a simple directive that pulls a random image from [Unsplash](https://picsum.photos/) can be created with a single file that exports an `picsum` directive.

[^esm]: The format of the JavaScript should be an ECMAScript modules, not CommonJS. This means it uses `import` statements rather than `require()` and is the most modern style of JavaScript.

:::{literalinclude} picsum.mjs
:label: picsum-js-source
:caption: A plugin to add an `picsum` directive that includes a beautiful, random picture based on a size and optional ID string.
:::

This code should be referenced from your `myst.yml` under the `projects.plugins`:

```{code} yaml
:filename: myst.yml
project:
  plugins:
    - picsum.mjs
```

Then start or build your document using `myst start` or `myst build`, and you will see that the plugin is loaded.

```text
myst start
...
🔌 Lorem Picsum Images (picsum.mjs) loaded: 1 directive
...
```

You can now use the directive, for example:

```markdown
:::{picsum}
:size: 600x250
:::
```

:::{picsum}
:size: 600x250
:::

If you change the source code you will have to stop and re-start the server to see the results.

Every field a directive or role can define is listed in [](./plugins-reference.md).

## Implementing a custom transform

Directives can be used to extend MyST with rich structured content. However, sometimes we want to _modify_ the existing behavior of MyST. One of the ways to do this is by writing a custom transform. In this section, we'll implement a transform that replaces **bold** text with _emphasis_.

First, let's define the transform
:::{literalinclude} markup.mjs
:caption: A plugin to add a transform that replaces strong nodes with emphasis nodes.
:::
this code should be referenced from your `myst.yml` under the `projects.plugins`:

```{code} yaml
:filename: myst.yml
project:
  plugins:
    - type: javascript
      path: markup.mjs
```

then start or build your document using `myst start` or `myst build`, and you will see that the plugin is loaded.
The `stage` field and the arguments a transform receives are described in [](#plugins:transform-spec).

```text
myst start
...
🔌 Strong to emphasis (markup.mjs) loaded: 1 directive
...
```

you can now use the directive, for example:

```markdown
I am **special bold text**, whilst I am **normal bold text**
```

I am **special bold text**, whilst I am **normal bold text**

(plugins:multi-page)=
:::{seealso} Aggregate information across multiple pages
A transform runs on one page at a time, but a plugin can still collect information from every page in a project and render it in one place - for example, for a site-wide glossary or a list of figures.
See the [multi-page plugin demo](https://github.com/myst-contrib/plugin-multi-page-demo) for a working example and a walk-through of the pattern.
:::

## Examples of plugins

The documentation you're reading now defines several of its own plugins to extend MyST functionality.
These are all registered in the documentation's [myst.yml configuration](myst.yml) with syntax like below:

```{literalinclude} myst.yml
:start-at: plugins
:end-before: error_rules
```

Each plugin is defined as a `.mjs` file in the same folder as the documentation's MyST content.
Below is the contents of each file for reference.

::::{dropdown} Plugin: Latex rendering

```{literalinclude} latex.mjs

```

::::

::::{dropdown} Plugin: Display an image

```{literalinclude} picsum.mjs

```

::::

::::{dropdown} Plugin: Custom directive for documenting roles and directives

```{literalinclude} directives.mjs

```

::::

::::{dropdown} Plugin: Render web template options as a table

```{literalinclude} templates.mjs

```

::::

---

### Math (`docs/math.md`)

---
title: Math and Equations
short_title: Math & Equations
description: Use LaTeX style math in your documents, including references, inline math, and equations.
thumbnail: ./thumbnails/math.png
---

There are several ways to make writing math in your documents as familiar as possible.
Math can either be (1) inline or (2) displayed as an equation block.[^katex]
In addition to the usual MyST syntax, you can also use "dollar math", which is derived from $\LaTeX$
and surrounds inline math with single dollar signs (`$`), and equation blocks with two dollar signs (`$$`).
The details of using inline math and equations are below.

[^katex]: The default MyST themes use [KaTeX](https://github.com/KaTeX/KaTeX) to render math in websites. This is similar to [MathJax](https://www.mathjax.org/), which was used by Jupyter Book 1, but has a few differences. Almost all math should work the exact same way, but if you were using more custom LaTeX or MathJax workflows, you may need to investigate how to port them to KaTeX. See [the KaTeX documentation](https://katex.org/docs/).

For example, here is an example of a cross-product, which we reference in the docs below!

$$
\mathbf{u} \times \mathbf{v}=\left|\begin{array}{ll}u_{2} & u_{3} \\ v_{2} & v_{3}\end{array}\right| \mathbf{i}+\left|\begin{array}{ll}u_{3} & u_{1} \\ v_{3} & v_{1}\end{array}\right| \mathbf{j}+\left|\begin{array}{ll}u_{1} & u_{2} \\ v_{1} & v_{2}\end{array}\right| \mathbf{k}
$$ (cross)

(inline-math)=
## Inline Math

There are two ways to write inline math; (1) with a `math` role or (2) by wrapping it in single dollar signs.

```{myst}
This math is a role, {math}`e=mc^2`, while this math is wrapped in dollar signs, $Ax=b$.
```

The output of these is the same (which you can see by looking at the AST and $\LaTeX$ outputs in the demo above).
Using a `math` role is much less likely to collide with your writing if it includes dollars (e.g. \$2.99).

Occasionally, dollar signs that you do not intend to wrap math need to be escaped.
These can be preceded by a backslash, that is `\$2.99`, and the `\` will not be displayed in your output.
If using $\LaTeX$ as an output, these dollar-signs will also be properly escaped again!

## Equations

There are three ways to create an equation block:
(1) a `math` directive (rather than a role for inline math);
(2) wrap the equation in two dollar-signs, `$$`; or
(3) use a `\begin{equation}` statement directly (i.e. using AMS math).

### Math directives

The math directive takes no arguments and the body of the directive is the $\LaTeX$ style math.
You can have an optional `label` parameter, which will label this equation for later cross-referencing, see [](#referencing-equations) below for more on that!

````{myst}
```{math}
:label: my-equation
w_{t+1} = (1 + r_{t+1}) s(w_t) + y_{t+1}
```

See [](#my-equation) for more information!
````

(dollar-math)=

### Dollar math equations

You can also create equations by wrapping content with two dollar signs (`$$`).
In this syntax, you can use the `\label{label-name}` command to add a label.
This can be quite convenient if your equations are small, the entire syntax can fit on a single line.

```{myst}
$$
\label{maxwell}
\begin{aligned}
\nabla \times \vec{e}+\frac{\partial \vec{b}}{\partial t}&=0 \\
\nabla \times \vec{h}-\vec{j}&=\vec{s}\_{e}
\end{aligned}
$$

$$ \label{one-liner} Ax=b $$

See [](#maxwell) for enlightenment and [](#one-liner) to do things on one line!
```


````{tip}
:class: dropdown
# Using AMS Math Environments

In addition to a `math` directive and dollar-math syntax, you can also use AMS math, which is specifically using [AMS Version 2.1](http://anorien.csc.warwick.ac.uk/mirrors/CTAN/macros/latex/required/amsmath/amsldoc.pdf).

```{myst}
\begin{equation}
\label{matrix}
Ax = b
\end{equation}

The general matrix equation is shown in [Equation %s](#matrix).
```

You can label your equation with the standard `\label{my-equation}` that you would do in $\LaTeX$.
The equation cross-referencing and numbering will work with the rest of your content.

```{warning}
The label implementation does not yet work for `sub-equations` and may not work if you have more than one label.
```

(ams-environments)=

## Supported AMS Environments

equation
: basic equation environment, similar to a math directive or dollar-math

multline
: variation equation, used for equations that don’t fit on a single line

gather
: a group of consecutive equations when there is no alignment desired among them

align
: used for two or more equations when vertical alignment is desired
: Note that `aligned` (i.e. with the `ed`) is **not** an AMS environment and only works inside of `\begin{equation}` or a math environment.

alignat
: allows the horizontal space between equations to be explicitly specified.

flalign
: stretches the space between the equation columns to the maximum possible width

matrix, pmatrix, bmatrix, Bmatrix, vmatrix, Vmatrix
: The pmatrix, bmatrix, Bmatrix, vmatrix and Vmatrix have (respectively)
`()`,`[]`,`{}`,`||`,and `‖‖` delimiters built in.

eqnarray
: eqnarray is another supported math environment, it is not part of amsmath, and it is better to use
align or equation+split instead
````

(referencing-equations)=

## Referencing Equations

As you have seen above, any equation can be labelled and cross-referenced in other parts of your document.
For example, the start of this document had [Equation %s](#cross), which can be referenced here with a link and inline-preview.
There are a few different ways to reference equations, with more details in [](./cross-references.md).

### Labelling equations

The examples above all show how to label an equation in the interactive demos.
With a directive, you can use the `label` option;
with dollar-math and AMS math, you can use the `\label{}` syntax that is native to $\LaTeX$.

For example, a directive can be labelled as follows:

````md
```{math}
:label: my_label
my_math
```
````

To reference equations you can use a markdown link with the target, for example:\
`[](#cross)` will create: [](#cross)

`````{note}
:class: dropdown
# Coming from Sphinx? How to use `eq` and `numref` roles.

We recommend using markdown links, as the syntax is consistent across all references and citations. You can also have markup inside of the text link and dynamically insert enumeration. However, if you are familiar with roles in Sphinx, you can also use the `eq` and `numref` roles to cross-reference equations.

The `eq` role can be used for referencing math, and by default inserts the number in parenthesis,
for example, {eq}`cross`. The label should be the first and only entry in the body of the role.
The `numref` directive should be used if you want to refer to your equation with text or a non-standard format.
As with other references you can use the `%s` or `{number}` to fill in the equation number (see [](./cross-references.md)).
Note that `{name}` does not work for equations as there is no text content to fill in.

````{myst}
```{math}
:label: my_label
w_{t+1} = (1 + r_{t+1}) s(w_t) + y_{t+1}
```

- Reference using `eq`: {eq}`my_label`
- Reference using `numref`: {numref}`my_label`
- Reference using `%s` `numref`: {numref}`Eq. %s <my_label>`
- Reference using `{number}` in `numref`: {numref}`Equation {number} <my_label>`
````

```{warning}
If you are using Jupyter Book or Sphinx, there are the following limitations:
(1) the `label` analysis of the source is not yet implemented;
(2) you can not reference equations using the {myst:role}`numref` role; and
(3) labels must not have spaces or start with a number (this is good practice anyways!).
```
`````

## Customizing Numbering

To change the reference format for math, you can use the frontmatter under the `numbering` field [see numbering](#numbering).
To override numbering for a specific equation you can use the {myst:directive}`math.enumerated` option on the math directive.

```markdown
:::{math}
:enumerated: false
Ax = b
:::
```

(math-macros)=

## Math Macros

Macros allow you to create reusable math components that can simplify the writing of a document.
These macros can be defined for a single document through the frontmatter, or shared in project frontmatter.
These macros are used throughout HTML and $\LaTeX$ exports and are written declaratively so that they can be easily parsed. Macros are the same as `\newcommand` or `\renewcommand` in $\LaTeX$, and use the `math` object in the frontmatter.

% Note: there must be a space here, or it is interpreted as {myst} options.
```{myst}

---
# Math frontmatter:
math:
  # Note the 'single quotes'
  '\dobs': '\mathbf{d}_\text{obs}'
  '\dpred': '\mathbf{d}_\text{pred}\left( #1 \right)'
  '\mref': '\mathbf{m}_\text{ref}'
---

The residual is the predicted data for the model, $\dpred{m}$, minus the observed data, $\dobs$. You can also calculate the predicted data for the reference model $\dpred{\mref}$.
```

The `math` macros are parsed as `yaml` in the frontmatter and can easily be shared or inherited through project to page frontmatter. These are also inserted into any $\LaTeX$ outputs for creating professional PDF documents.

```{important}
When using the YAML syntax for the `math` macros, use **single quotes** around the strings. The single quote yaml syntax means you do not have to text-escape the strings, otherwise backslashes `\f`, `\n`, `\b`, `\r`, `\t` and other symbols have to be escaped which is difficult to remember and leads to all sorts of strange errors.
```

The `key` is the command that you are defining, in the demo above `\dobs`, `\dpred`, and `\mref`; the command should include the leading `\`. The value of the entry should be the macro definition. If the definition contains `#1` then there will be one required argument for the macro that should be supplied in braces when you use it (e.g. `\dpred{m}`). The macros can be nested as in the example where `\dpred{\mref}` uses two macros.

In the macro in the example above, `\mathbf{d}_\text{pred}\left( #1 \right)`, the `#1` is the first and only required argument, and is placed in between left and right brackets. The numbering for arguments starts at one, and other arguments can be added with `#2`, `#3`, etc. and then input in a command using `\command{arg1}{arg2}`.

```{seealso}
In the future the information collected in the math macro will expand to include alt text, color, or interaction information (e.g. hover, substitution) to improve accessibility and interactivity.
```


(typst-math)=

### Typst-specific Math Content

When exporting to Typst format, you can provide Typst-specific math content using the `typst` option. This allows you to use native Typst syntax instead of relying on [`tex-to-typst`](https://github.com/continuous-foundation/tex-to-typst) conversion, which may give incorrect results.

Example with typst argument in a math block:

````{myst}
```{math}
:typst: root(3, x)
\sqrt[3]{x}
```
````

When the `typst` option is provided, it will be used directly in Typst output instead of converting the LaTeX content.

For inline math, you can also use the `typst` option with the math role:

```{myst}
{math typst="typst"}`latex`
```

:::{important} Improve the Math Conversion
If your LaTeX math does not convert automatically to typst, please open an [issue here](https://github.com/continuous-foundation/tex-to-typst/issues/new).
:::

---

### Md Vs Ipynb (`docs/md-vs-ipynb.md`)

# How to choose between `.ipynb` and `.md` when writing Jupyter notebooks

You can work with Jupyter notebooks in both the `.ipynb` format as well as in a text-based format like [MyST Markdown](./notebooks-with-markdown.md). This is a brief guide to help you choose when to use one vs. the other.

**This is a question of trade-offs, not right and wrong**. There are benefits and drawbacks to using either the more-structured `.ipynb` format, or the more human-readable `.md` format. We'll try to describe each of them below.

## Key differentiators between `.md` and `.ipynb`

**`.ipynb`** is a JSON-based format that captures the **entire interactive session**, including code, Markdown, **outputs**, and detailed **metadata**. It is designed for **machine readability** and preserving execution state. It often results in very complex `diff`s when doing code review, because there is a lot of machine-generated information inside an `.ipynb` file. However, this also means that it preserves more information about the result of your computations inside the file itself.

**`.md`** is a plain text file with Markdown inside. It is more human-readable, and slightly less-structured than JSON files. It focused on the **input cells** and **Markdown cells** of a Jupyter Notebook, as well as **human-generated metadata** (like cell tags). Markdown notebooks **do not store outputs**. If you execute a cell with a Markdown-based Jupyter Notebook, then outputs will exist in your interactive session but not be saved to the `.md` file. This makes **code review and version control much easier** because you're only looking at Markdown and some human-generated syntax for code cells. Finally, Jupyter UIs require installing either [Jupytext](https://jupytext.readthedocs.io/) or [JupyterLab-MyST](https://github.com/jupyter-book/jupyterlab-myst) to read Markdown-based notebooks.

## Is the experience of reading and writing any different between `.md` and `.ipynb`?

In general, there isn't any difference between reading and writing these two formats.
If you use [Jupytext](https://jupytext.readthedocs.io/en/latest/) or [JupyterLab-MyST](https://github.com/jupyter-book/jupyterlab-myst), then your experience in a Jupyter interface will be the exact same. It is only when you _save the notebook_ that it gets written to `.md` or `.ipynb`. Here is the process in either case:

One exception to this is **loading a notebook from disk**. If using a `.md` file, you may need to take an extra UI action to load the `.md` file as a notebook (instead of as a text file). In addition, if you're using a `.md` file then the outputs will be empty every time you load it (because they aren't stored with the file).

Finally, if you're using a `.md` file, then you'll be able to edit it from any text editor, rather than requiring a notebook UI to load. You can read and understand the structure of a `.md` file on your own without needing to render it in a browser.

## When to lean towards Markdown (`.md`)

- **Version control clarity:** When **tracking changes** to the notebook's content (code and narrative) in a collaborative setting is crucial. Markdown's readability makes `diff`ing straightforward.
- **Human-focused authoring:** If you prioritize writing and reviewing the **source content** in a highly readable, human-editable format.
- **Collaborative review:** For workflows involving frequent **reviews of the code and explanations**, where output changes are less critical to the review process.
- **Integration with text-based workflows:** When you intend to use notebooks with tools that excel with Markdown, such as static site generators or documentation pipelines.
- **When re-executing your content is important or easy:** When you want to re-execute your content at build-time, Markdown-based formats are usually easier to work with. This allows you to ensure your code is reproducible, so long as it isn't extremely complex or costly to do execute. This is often the preferred case in tutorials for libraries where notebooks are regularly executed in CI to ensure continued functionality.

## When to lean towards `.ipynb`

- **Output preservation:** When you need to store and share the **results of code execution** (text, tables, figures) without requiring re-running.
- **Out-of-the-box Jupyter UI support:** When you cannot assume that your reader can install `jupytext` or `jupyterlab-myst`.
- **Computational intensity:** For notebooks with **lengthy or resource-intensive computations**, saving outputs via `.ipynb` avoids redundant runs.
- **Self-contained execution history:** When the complete record of an interactive session, including execution order and timestamps, is important.
- **Rich interactive elements:** If your notebook heavily utilizes **complex widgets or interactive visualizations** whose state needs direct preservation.

## Reminder: there is not a single right answer

People have debated the "`.ipynb` vs. `.md`" question for many years. There is no single answer that works for every use-case. Hopefully the ideas above give a general idea for when to use one vs. the other.

---

### Myst.Yml (`docs/myst.yml`)

version: 1
project:
  title: MyST Markdown
  github: https://github.com/jupyter-book/mystmd
  # Uncomment to test launch buttons
  jupyter:
    binder:
      repo: https://github.com/jupyter-book/thebe-binder-base
  license:
    code: MIT
    content: CC-BY-4.0
  subject: MyST Markdown
  references:
    python: https://docs.python.org/3.13/
    jupyterbook: https://jupyterbook.org/en/stable/
    jtex: https://mystmd.org/jtex/
    spec: https://mystmd.org/spec/
    biapol: https://biapol.github.io/blog/

  plugins:
    - directives.mjs
    - picsum.mjs
    - latex.mjs
    - error-rules.mjs
    - versions.mjs
    - templates.mjs
    - type: executable
      path: picsum.py
    - type: executable
      path: markup.py
    - type: javascript
      path: markup.mjs

  error_rules:
    - rule: link-resolves
      severity: ignore
      keys:
        - /robots.txt
        - /sitemap.xml
        - /jtex/template-yml
        - /jtex
        - /jtex/create-a-latex-template
        - /jtex/create-a-beamer-template
        - /jtex/contribute-a-template

  toc:
    - file: index.md
    - file: installing.md
    - title: Tutorials
      children:
        - file: quickstart.md
        - file: quickstart-myst-documents.md
        - file: quickstart-executable-documents.md
        - file: quickstart-static-exports.md
        - file: quickstart-myst-markdown.md
        - file: quickstart-jupyter-lab-myst.md
    - title: Configuration and setup
      children:
        - file: configuration.md
        - file: frontmatter.md
        - file: settings.md
        - file: table-of-contents.md
        - file: document-parts.md
        - file: authorship.md
    - title: Authoring
      children:
        - file: typography.md
        - file: admonitions.md
        - file: figures.md
        - file: math.md
        - file: tables.md
        - file: code.md
        - file: cross-references.md
        - file: external-references.md
        - file: embed.md
        - file: citations.md
        - file: proofs-and-theorems.md
        - file: exercises.md
        - file: blocks.md
        - file: diagrams.md
        - file: asides.md
        - file: dropdowns-cards-and-tabs.md
        - file: glossaries-and-terms.md
        - file: writing-in-latex.md
        - file: inline-options.md
    - title: Executable Content
      children:
        - file: execute-notebooks.md
        - file: notebooks-with-markdown.md
        - file: reuse-jupyter-outputs.md
        - file: interactive-notebooks.ipynb
        - file: in-page-execution.md
        - file: website-launch-buttons.md
        - file: notebook-configuration.md
        - file: md-vs-ipynb.md
    - title: Websites
      children:
        - file: website-templates.md
        - file: website-navigation.md
        - file: website-metadata.md
        # - file: themes-and-extensions.md
        - file: seo-and-social.md
        - file: website-style.md
        - file: accessibility-and-performance.md
        # - file: search.md
        - file: analytics.md
        - file: website-downloads.md
        - file: deployment.md
          children:
            - file: deployment-github-pages.md
            - file: deployment-gitlab.md
            - file: deployment-curvenote.md
            - file: deployment-netlify.md
            - file: deployment-readthedocs.md
            - file: deployment-webserver.md
        - file: website-landing-pages.md

        # - file: publishing.md
    - title: Document exports
      children:
        - file: documents-exports.md
        - file: creating-pdf-documents.md
        - file: creating-word-documents.md
        - file: creating-jats-xml.md
        - file: creating-citation-cff.md
    - file: plugins.md
      children:
        - file: javascript-plugins.md
        - file: plugins-distribute.md
        - file: executable-plugins.md
        - file: widgets.md
        - file: plugins-debug.md
        - title: Use cases
          children:
            - file: plugins-ast.md
            - file: plugins-dry.md
        - title: Plugins Reference
          file: plugins-reference.md
    - title: Reference
      children:
        - file: install-node.md
        - file: update-myst.md
        - file: commonmark.md
        - file: syntax-overview.md
        - file: directives.md
        - file: roles.md
        - file: glossary.md
        - file: versions.md
    - title: About MyST
      children:
        - file: overview.md
        - file: guiding-principles.md
        - file: background.md
    - title: Contribute
      children:
        - file: contributing.md
        - file: developer.md
        - file: theme-developer.md
        - file: contribute-templates.md
        - file: contribute-docs.md
        - file: contribute-build-locally.md
        - file: contribute-add-feature.md
        - file: developer-api.md
    - file: cite.md

extends:
  - abbreviations.yml

site:
  title: MyST Markdown Guide
  #template: ../../myst-theme/.deploy/book/template.yml
  domains:
    - mystmd-guide.curve.space
  options:
    style: public/style.css
    analytics_plausible: jupyterbook.org
  parts:
    # This just tests this locally, it shouldn't be in the mystmd.org/guide site
    # Note the CSS won't work because we aren't pulling it in
    footer: https://github.com/jupyter-book/jupyterbook.org/raw/refs/heads/main/docs/_site/footer.md

---

### Notebook Configuration (`docs/notebook-configuration.md`)

---
title: Add metadata to notebooks
---

In addition to global controls that you can set in the [project settings](#project-settings), you can also add metadata to individual notebooks, or on notebook cells, to control how MyST handles them during execution and rendering.

(notebook-tags)=

## Tags for an entire notebook

The concrete syntax of notebook tags depends on the notebook format.

(notebook-tags-ipynb)=

### ipynb notebooks

Using Jupyter Lab, you can use the `Property Inspector` builtin extension to manage notebook-level metadata.

:::{image} /images/jupyterlab-property-inspector.png
:::

Using this tool you can add key-value pairs to the notebook metadata. For
example, to skip execution of a notebook, you would add the following key-value
pair inside the notebook metadata dictionary:

```json
"tags": [
        "skip-execution"
    ]
```

### Markdown notebooks

With Markdown notebooks, you can add notebook-level metadata using the YAML frontmatter at the top of the file. For example, to skip execution of a notebook, you would add the following to the frontmatter:

```markdown
---
kernelspec:
  name: python3
  display_name: Python 3

execute:
  skip: true
---
```

(notebook-cell-tags)=

## Tags for a cell in a notebook

Tags are a list of strings under the `tags` key in the cell metadata, which can
be set in JupyterLab, VSCode or in a {myst:directive}`code-cell` directive. Here
again the actual syntax depends on the notebook format.

### ipynb notebooks

In the JSON representation of a jupyter notebook, cell tags would look like:

```json
{
  "cell_type": "code",
  "source": ["print('hello world')"],
  "metadata": {
    "tags": ["my-tag1", "my-tag2"]
  }
}
```

You can use the `Property Inspector` builtin extension in Jupyter Lab to manage cell metadata, like so:

:::{image} /images/jupyterlab-cell-tags.png
:::

### Markdown notebooks

In addition, MyST also supports the {myst:directive}`code-cell` directive for [markdown notebooks](#code-cell); here is an example of adding the `raises-exception` tag on such a code cell:

In Markdown of a jupyter notebook these look like:

````markdown
```{code-cell} python
:tags: [remove-input]
print("This will show output with no input!")
```
````

for a single tag, or more generally, if you need to add multiple tags:

````markdown
```{code-cell} python
:tags: [my-tag1, my-tag2]
print("This will show output with no input!")
```
````

:::{table} Notebook cell tags with special meanings
:label: tbl:notebook-cell-tags

| Tag                | Description                                                                                                    |
| ------------------ | -------------------------------------------------------------------------------------------------------------- |
| `remove-cell`      | Remove the cell from the rendered output.                                                                      |
| `remove-input`     | Remove the code cell input/source from the rendered output.                                                    |
| `remove-output`    | Remove the code cell output from the rendered output.                                                          |
| `hide-cell`        | Hides the cell from the rendered output.                                                                       |
| `hide-input`       | Hides the code cell input/source from the rendered output.                                                     |
| `hide-output`      | Hides the code cell output from the rendered output.                                                           |
| `remove-stderr`    | Remove the code cell output stderr from the rendered output. See also [project config](#setting:output_stderr) |
| `remove-stdout`    | Remove the code cell output stdout from the rendered output. See also [project config](#setting:output_stdout) |
| `skip-execution`   | Skip this cell, when executing the notebook                                                                    |
| `raises-exception` | Expect the code cell to raise an Exception (and continue execution)                                            |

:::

---

### Notebooks With Markdown (`docs/notebooks-with-markdown.md`)

---
title: Executable Markdown Files
subtitle: Define Jupyter metadata to make Markdown files executable
description: MyST Markdown files can contain the necessary metadata required to execute their content.
kernelspec:
  name: python3
  display_name: Python 3
---

```{code-cell} python
:tag: remove-cell

import matplotlib.pyplot as plt
import numpy as np
```

Execution information can be added to MyST Markdown files, which allows you to perform computation using [MyST's notebook execution engine](./execute-notebooks.md). First, you will need to [define a kernel specification](#kernel-specification), after which you can introduce Markdown-based computation in several ways:

- [Code cells](#code-cell) for block-level content.
- [Inline expressions](#inline-expressions) for content inline with surrounding text.

:::{tip} Install Jupyter Server
:class: dropdown
To execute your code you will need to [](#install-jupyter-server).
:::

(kernel-specification)=

## Kernel specification

Defining a kernel specification (`kernelspec`) informs the Jupyter server of the name of the kernel that should execute your code. When you call `myst build --execute` or `myst start --execute`, the MyST CLI starts a Jupyter kernel to execute your code and gather the execution results. Defining different `kernelspec`s in each notebook makes it possible to flexibly switch the package environment and programming language (e.g. to use R in one notebook, and Julia in another).

The `kernelspec` configuration should be defined in the _page-level_ frontmatter of each executable Markdown file (see [](#field-behavior) for more information), and supports the same content that is validated by [`nbformat`'s schema](https://github.com/jupyter/nbformat/blob/main/nbformat/v4/nbformat.v4.5.schema.json):

```{list-table} A list of available kernelspec fields
:header-rows: 1
:label: table-kernelspec

* - field
  - description
* - `name`
  - name of the kernel, e.g. `python3`
* - `display_name`
  - human-readable name for the kernel, e.g. "Python 3.12"
```

The following content is a frontmatter that defines a document that uses the `python` kernel:

```{code} yaml
:filename: markdown-notebook.md
---
kernelspec:
  name: python3
  display_name: 'Python 3'
---
```

After we declare the frontmatter, the contents of each {myst:directive}`code-cell` directive and {myst:role}`eval` role will be executed by the `python` kernel during the building process.

### Use a different kernel

Furthermore, you can build MyST Markdown content with other programming languages like JavaScript, R, and Julia by installing the corresponding kernel. For example, to build a page that uses JavaScript in the {myst:directive}`code-cell`, we could:

1. Install a JavaScript kernel, e.g. [ijavascript](https://github.com/n-riesco/ijavascript).
2. Retrieve the kernel name with `jupyter kernelspec list`.
   In the default installation, the kernel name is `javascript`.
3. Set the kernelspec in your document's frontmatter:
   ```yaml
   kernelspec:
     name: javascript
     display_name: JavaScript
   ```
4. Define a code cell that uses the new kernel:
   ````markdown
   ```{code-cell} javascript
   console.log("hello javascript kernel");
   ```
   ````

(code-cell)=

## Code cells with the {myst:directive}`code-cell` directive

You can use the {myst:directive}`code-cell` directive to create block-level computational outputs in MyST Markdown.

{myst:directive}`code-cell` directives have the following form:

````
```{code-cell} LANGUAGE
:key: value

CODE TO BE EXECUTED
```
````

- `LANGUAGE` defines the language to be used in executing the code.
- `:key: value` pairs will be treated as cell-level metadata.
- `CODE TO BE EXECUTED` will be executed by the `LANGUAGE` kernel at build time.

For example, the following directive inserts a code cell into the page, and will be executed if you specify `--execute` with your MyST build.

````markdown
```{code-cell} python
hello = "hello"
there = "there"
phrase = f"{hello}, {there}!"
print(phrase)
```
````

```{code-cell} python
hello = "hello"
there = "there"
phrase = f"{hello}, {there}!"
print(phrase)
```

### Add tags to {myst:directive}`code-cell` directives

You can add tags to the {myst:directive}`code-cell` directive.
They will be parsed and used in the same way that cell tag metadata is used in `.ipynb` files.

For example, the following code defines a `remove-input` tag (See all [notebook tag options](#tbl:notebook-cell-tags)):

````markdown
```{code-cell} python
:tags: [remove-input]
print("This will show output with no input!")
```
````

and results in the following:

> ```{code-cell} python
> :tags: [remove-input]
> print("This will show output with no input!")
> ```

This can be particularly helpful for showing the output of a calculation or plot, which is reproducible in the {download}`source code <./notebooks-with-markdown.md>`, but not shown to the user like this `matplotlib` plot:

```{code-cell} python
:tags: [remove-input]
# Data for plotting
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)

fig, ax = plt.subplots()
ax.plot(t, s)

ax.set(xlabel='time (s)', ylabel='voltage (mV)',
       title='Waves in Time')
ax.grid()

fig.savefig("test.png")
plt.show()
```

For **multiple tags** you have two ways to provide them:

- If you specify argument options with `:`, tags will be parsed as a comma-separated list of strings.
  For example:

  ````markdown
  ```{code-cell} python
  :tags: [tag1, tag2,tag3]
  # Note that whitespace is removed from tags!
  print("howdy!")
  ```
  ````

- If you specify argument options with YAML, tags should be given as a YAML list.
  For example:

  ````markdown
  ```{code-cell} python
  ---
  tags:
  - tag1
  - tag2
  ---
  print("howdy!")
  ```
  ````

For more about how to specify directive options, see [](./syntax-overview.md).

:::{seealso} Controlling cell visibility with tags
See [](#notebooks:cell-visibility) for more information.
:::

(code-cell:linenos)=
### Add line numbers and highlighting to {myst:directive}`code-cell` directives

You can add line numbers and emphasize specific lines in code cells, just like in [code blocks](./code.md#numbering-and-highlighting).

````
```{code-cell} python
:linenos:
:emphasize-lines: 2,3

hello = "hello"
there = "there"
phrase = f"{hello}, {there}!"
print(phrase)
```
````

```{code-cell} python
:linenos:
:emphasize-lines: 2,3

hello = "hello"
there = "there"
phrase = f"{hello}, {there}!"
print(phrase)
```

You can also use {myst:directive}`code.lineno-start` to start numbering from a specific line, and {myst:directive}`code.filename` to display a filename.

(myst:inline-expressions)=

## Inline expressions with the {myst:role}`eval` role

You can use the {myst:role}`eval` role to evaluate code that is surrounded by text.
This allows you to quickly insert its output in a way that flows with the text around it.

:::{note} You can use inline expressions in the Markdown cells of an `.ipynb` file as well.
:::

For example, the following MyST Markdown would re-use the variable defined above.

```markdown
The phrase is: {eval}`phrase`.
```

This results in the following:

> The phrase is: {eval}`phrase`.

You can also modify the expression at the time of computation, for example:

```markdown
The phrase manually computed is: {eval}`f"{hello}, {there} everybody!"`
```

This results in the following:

> The phrase manually computed is: {eval}`f"{hello}, {there} everybody!"`

:::{seealso} Also works in JupyterLab
See [](./quickstart-jupyter-lab-myst.md) for how these eval statements also work in JupyterLab.

:::

## Markdown cells with block breaks

In [](#compatibility-jupytext), the `jupytext` tool for integrating text-based notebooks with existing Jupyter tools like JupyterLab is discussed. By default, when reading a MyST Markdown document, `jupytext` creates a single Markdown cell between adjacent code cells. The block-break (`+++`) syntax described in [](./blocks.md) can be used to separate blocks of Markdown into distinct Markdown cells.

(compatibility-jupytext)=

## Compatibility with `jupytext`

[jupytext](https://github.com/mwouts/jupytext) is a Python package that converts between Jupyter Notebooks (ipynb files) and plain text documents (like MyST Markdown files). It provides both a commandline tool to perform these conversions, and an extension for JupyterLab to facilitate opening text-based notebooks with the Notebook viewer. MyST Markdown is understood by jupytext, which defines a `md:myst` format for reading from / writing to MyST Markdown.

The following command will convert a MyST Markdown file `example.md` to the `.ipynb` notebook:

```shell
$ jupytext --from md:myst --to notebook example.md
```

(execute-config)=
## Control of execution

The top-level `execute` page frontmatter block accepts several properties for controlling build-time execution of the given page:

`skip`
: Skip execution of this notebook, even though it has a kernelspec.

`depends_on_env`
: Define the environment variables upon which this notebook depends. Changes to these variables will invalidate the execution cache.

`cache`
: Disable the execution cache for this notebook.

---

### Package.Json (`docs/package.json`)

{
  "name": "mystmd-docs",
  "private": true,
  "version": "0.0.0",
  "dependencies": {
    "myst-common": "workspace:*",
    "myst-directives": "workspace:*",
    "myst-ext-button": "workspace:*",
    "myst-ext-card": "workspace:*",
    "myst-ext-exercise": "workspace:*",
    "myst-ext-grid": "workspace:*",
    "myst-ext-proof": "workspace:*",
    "myst-ext-tabs": "workspace:*",
    "myst-migrate": "workspace:*",
    "myst-parser": "workspace:*",
    "myst-roles": "workspace:*",
    "tex-to-myst": "workspace:*",
    "unist-builder": "^3.0.0",
    "unist-util-select": "^4.0.3"
  }
}

---

### Plugins Ast (`docs/plugins-ast.md`)

---
title: Generate MyST AST with Plugins
---

A common use case with plugins involves generating {term}`MyST AST` and inserting it into the document.
This page covers a few ways that you can do so.

:::{tip} New to the MyST AST?
Start with the [AST primer](xref:spec/ast-primer) for an overview of how MyST documents are structured at a high- and low-level.
:::

(plugins:ctx)=

## Parse MyST markdown to AST in a directive or role

### With a function call

The `parseMyst` function (available in the `ctx` variable) provides an explicit method to parse MyST text into {term}`MyST AST`.
Here's an example of using the `parseMyst` function within a directive plugin to parse the _body_ of the directive into MyST AST:

```{code} javascript
:filename: myplugin.mjs
const myDirective = {
  name: "mydirective",
  doc: "My new directive!",
  // Here the body is passed as a string
  body: { type: String, doc: "To be parsed into MyST AST." },
  run(data, vfile, ctx) {
    // Here we parse the body into MyST AST
    const ast = ctx.parseMyst(data.body);
    return ast.children[0];
  },
};
```

`ctx.parseMyst` returns a {term}`root node <Root AST node>` which contains the parsed MyST as children.
The directive plugin example above returns `ast.children[0]` (the first child of the root node) to avoid creating a malformed document (there can only be one "root").

You can use the `parseMyst` function to construct MyST outputs from text generated with string interpolation, for example:

```{code} javascript
:filename: justacard.mjs
const myDirective = {
  name: "justacard",
  doc: "Basically does what a card directive does!",
  arg: { type: String, doc: "To be parsed into MyST AST." },
  body: { type: String, doc: "The body of the directive." },
  run(data, vfile, ctx) {
    // Here we parse a string that defines a multi-line card directive
    const ast = ctx.parseMyst(`:::{card} ${data.arg}\n${data.body}\n:::`);
    return ast.children[0];
  },
};
```

:::{tip} If you need to use multi-line strings you must dedent them
:class: dropdown

The example above puts a multi-line string onto one line by manually coding the `\n` characters.
If you instead want to show a multi-line string in your code, you will need to remove the indentation manually, for example like the following:

```{code} javascript
:filename: justacard.mjs
const myDirective = {
  name: "justacard",
  doc: "Basically does what a card directive does!",
  arg: { type: String, doc: "To be parsed into MyST AST." },
  body: { type: String, doc: "The body of the directive." },
  run(data, vfile, ctx) {
    // By removing the indentation white-space the string is correctly parsed
    const ast = ctx.parseMyst(`
:::{card} ${data.arg}
${data.body}
:::`);
    return ast.children[0];
  },
};
```

:::

### With automatic parsing

You can define a plugin's argument or body as `{type: 'myst'}` instead of `{type: String}` to enable those parameters to be autuomatically parsed into {term}`AST nodes <AST node>`.
In this case, `data.body` will be a list of AST nodes instead of text:

```{code} javascript
:filename: myplugin.mjs
:linenos:
:emphasize-lines: 5
const myDirective = {
  name: "mydirective",
  doc: "My new directive!",
  // By defining type: 'myst', the directive body will automatically be parsed into MyST AST
  body: {
    type: 'myst',
    doc: "Pre-parsed and immediately usable as MyST AST.",
  },
  run(data) {
    return data.body[0];
  },
};
```

## Use the MyST Sandbox to identify AST structure

The [MyST interactive sandbox](https://mystmd.org/sandbox) is a great way to explore what MyST looks like when it is rendered, and what its underlying AST structure looks like. This is particularly useful if you're generating MyST AST from scratch. For example, as part of a [plugin role or directive](./plugins.md).

:::{important}
Plugins must return "POST" AST, so ensure that the "POST" option at the top-right of the sandbox interface is selected!
:::

```{figure} videos/sandbox-demo.mp4
Here's how you can use [the MyST sandbox](https://mystmd.org/sandbox) to explore the structure of a `card` directive and preview its AST.
```

:::{note} Click here to see the full output of the MyST sandbox
:class: dropdown

The output of the sandbox AST generator can be seen in @code:ast. The highlighted outer `root` and `block` nodes are always included in the output, and contain the interesting AST (in this case, a `card`).

```{code} json
:linenos:
:emphasize-lines: 1-6,30-33
:label: code:ast
:caption: The AST of a card directive, produced by the MyST sandbox.
{
  "type": "root",
  "children": [
    {
      "type": "block",
      "children": [
        {
          "type": "card",
          "children": [
            {
              "type": "cardTitle",
              "children": [
                {
                  "type": "text",
                  "value": "My title"
                }
              ]
            },
            {
              "type": "paragraph",
              "children": [
                {
                  "type": "text",
                  "value": "My card body."
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
```

:::

---

--- METRICS ---
- Files Extracted: 105
- Estimated Token Budget: ~125180 tokens
- Canonical Reference: https://codewiki.google/github.com/jupyter-book/mystmd
