/docs/authoring

MDXでスライドを書く

利用できるMarkdown、MDX、hono-decks独自の記法をまとめています。

デッキごとにディレクトリを分ける

decks/<slug>/deck.mdxが基本形です。ディレクトリ名がURLの:slugになります。たとえばdecks/launch/deck.mdx/decks/launchで表示されます。

ファイル先頭の---ブロックはデッキ情報、その後の区切り線は新しいスライドの開始を表します。スライド内の水平線として単独の---は使えません。

decks/launch/deck.mdx
---
title: Hono at the edge
transition: fade
---

# Hono at the edge

---
title: Runtime boundary
layout: statement
---

Node for I/O. Hono for routes.

本文はGFMとMDXで書く

CommonMarkとGFM(テーブル、タスクリスト、打ち消し線、自動リンク)を使えます。MDXではJSX要素や式も記述できます。

MDX
# Runtime boundary

Use **bold**, *emphasis*, `inline code`, and [links](https://hono.dev/).

- Node for build-time I/O
- Hono for runtime routes

- [x] Compile the deck
- [ ] Deploy the Worker

| Layer | Responsibility |
| :-- | :-- |
| Node | Build-time I/O |
| Hono | Runtime routes |

~~Filesystem access at runtime~~

> Keep the Worker bundle filesystem-free.

```ts
const runtime = "Hono"
```
コードフェンス
開始行にtstsxcssなどの言語名を付けると、スライド内でシンタックスハイライトされます。
MDX
JSXコンポーネント、props、式を使えます。importexportはファイル先頭にまとめます。

デッキ全体と各スライドの設定を分ける

ファイル先頭のフロントマターはデッキ全体に適用されます。区切り線の直後に置いたフロントマターは、そのスライドだけに適用されます。未定義のキーはmetaに残り、コンパイル時に警告が表示されます。

デッキ
title, description, author, tags, date, theme, transition, transitionDuration, transitionEasing, draft, assets, presenter
スライド
title, layout, class, notes, background, transition, transitionDuration, transitionEasing
トランジション
none, fade, fade-out, slide-left, slide-right, slide-up, slide-down, view-transition
レイアウト
default、中央配置のcoverstatementが標準です。独自名はlayout-<name>クラスとしてtheme.cssから指定できます。

fireで内容を1つずつ表示する

コンポーネントにfireを付けると、送り操作に合わせて記述順に表示されます。Markdownには:::fire、リストには:::fire{each="item"}を使います。複数のJSX要素を同時に表示するときは、まとめて<Fire>で囲みます。fireはコンパイル時に取り除かれ、コンポーネントのpropsには渡りません。

MDX
<Card fire />

<Chart fire="scale" at="2" />

:::fire{at="+2"}
Markdown block
:::

:::fire{each="item" depth="2" every="2"}
- Parent one
  - Child one
- Parent two
  - Child two
:::

<Fire effect="fade-up">
  <Heading />
  <Description />
</Fire>

段階表示の考え方とatdeptheveryの仕組みは、Slidevのv-clickv-clicksを一部参考にしています。ただし、記法と実装はhono-decks独自であり、Slidevとの互換性は保証しません。at="2"は絶対位置、at="+2"は現在位置から2段先を指定します。リストでは、depthで対象の階層、everyで1回に表示する項目数を指定します。どちらも既定値は1です。

表示効果を選ぶ

コンポーネントではfire="scale":::fireではeffect="scale"と指定します。標準の効果はnonefadefade-upscaleです。独自の効果はtheme.cssで定義します。

MDX
<Chart fire="blur-in" />

:::fire{effect="blur-in"}
Markdown block
:::
theme.css
[data-fire-effect="blur-in"] {
  --fire-transform: scale(.98);
  --fire-filter: blur(12px);
  --fire-duration: .32s;
  --fire-easing: ease-out;
}

発表者ノートを書く

notes: |に書いた複数行テキストとMDXコメントは、発表者ノートにまとめられ、スライド本文には表示されません。MDXコメントは、コードの補足として書いた場合もノートとして扱われます。

MDX
---
notes: |
  Explain why generation runs before deployment.
---

# Build once, serve anywhere

{/* Mention the generated module boundary. */}

まずサーバーコンポーネントを使う

components/index.tsxの名前付きエクスポートは、同じデッキのMDXからタグとして使えます。デッキごとに登録されるため、別のデッキと同じ名前でも衝突しません。

TypeScript
// decks/welcome/components/index.tsx
export function Metric(props: { value: string; label: string }) {
  return <figure>
    <strong>{props.value}</strong>
    <figcaption>{props.label}</figcaption>
  </figure>
}
MDX
<Metric value="18 ms" label="Response time" />

ブラウザ操作が必要な部品だけをIslandにする

components/client/index.tsxはクリックや状態管理が必要な部品だけに使います。クライアント用コードは自動生成されるため、通常は配信用ルートを追加する必要はありません。

TypeScript
// decks/welcome/components/client/index.tsx
import { useState } from "hono/jsx/dom"

export function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>
    Count: {count}
  </button>
}

画像を置き、外部コンテンツを埋め込む

decks/launch/assets/に置いた画像は、deck.mdxからの相対パスで指定します。youtubexcardembediframeは専用記法を使います。

MDX
![Architecture](./assets/runtime-boundary.svg)

@[youtube](https://www.youtube.com/watch?v=VIDEO_ID)
@[x](https://x.com/honojs/status/POST_ID)
@[card](https://hono.dev/docs/)
@[embed](https://example.com/demo)
@[iframe](https://example.com/demo)

URLだけの行は通常のリンクになります。外部iframeを公開する前にCSPと許可オリジンを設定してください。R2配信へ変える場合は、MDXを変えずにwithR2Assets()で取得元を差し替えます。

デッキ単位でテーマを追加する

deck.mdxと同じディレクトリにtheme.cssを置くと、そのデッキだけに適用されます。まずCSS変数で色を調整し、必要な部分だけ通常のセレクターを追加します。

decks/welcome/theme.css
/* decks/welcome/theme.css */
:root {
  --hono-decks-accent-color: #ff5b1a;
}

.slide h1 {
  text-wrap: balance;
}

devコマンドで変更を自動反映する

Terminal
npm run dev

ViteまたはWranglerのdev実行中は、保存したMDXが自動で再コンパイルされ、成功後にブラウザへ反映されます。npm run decks:compileは、CIやコンパイラーだけを単独で確認するときに使います。コンパイルエラーには対象ファイルとスライド番号が表示されます。

表示を確認したら、公開画面を変える場合はルートと画面、環境変数やR2を使う場合は設定へ進みます。