/docs/getting-started

Get started

Compile an MDX deck, mount the generated router in an existing Hono application, and verify it in your browser.

Start with a working Hono 4 app

You need npm, pnpm, Yarn, or Bun and a Hono 4 app that already runs. By the end of this guide, it will serve a two-slide deck at /decks/welcome.

Install the package and create the config

The example uses npm. init creates the shared hono-decks.config.ts and the app-owned src/decks.ts facade. It refuses to overwrite existing files.

Terminal
npm install hono-decks
npx hono-decks init
Package managerInstallRun the CLI
npmnpm install hono-decksnpx hono-decks <command>
pnpmpnpm add hono-deckspnpm exec hono-decks <command>
Yarnyarn add hono-decksyarn hono-decks <command>
Bunbun add hono-decksbunx hono-decks <command>

Replace <command> with init or compile, and use the same package manager for the remaining examples.

Create and compile the first deck

Create decks/welcome/deck.mdx. The first frontmatter block describes the whole deck; the next --- starts slide one.

decks/welcome/deck.mdx
---
title: Welcome
description: My first hono-decks presentation
---

---
layout: cover
---

# Welcome

This deck is served from my Hono app.

---

## Next slide

- Write slides in MDX
- Serve them with Hono

Compile the MDX into Hono JSX modules. A successful run creates src/generated/.

Terminal
npx hono-decks compile
Generated files
hono-decks.config.ts   # shared CLI/runtime config
decks/
└── welcome/
    └── deck.mdx
src/
├── decks.ts              # app-owned facade
└── generated/
    └── decks.ts          # generated; do not edit

Edit src/decks.ts and deck.mdx as needed. Never edit src/generated/; each compile replaces it.

Mount the generated router in Hono

Add the generated router to the existing Hono app.

TypeScript
// src/index.ts
import { Hono } from "hono"
import { decks } from "./decks"

const app = new Hono()
app.route(decks.mountPath, decks.router())

export default app

decks.mountPath comes from the shared config, keeping compile-time assets and runtime routes on the same public path.

Integrate compilation with the existing dev command

For HonoX or Vite, add the plugin to the existing Vite config. It compiles before Vite starts, regenerates modules when MDX changes, and reloads the browser after a successful compile.

vite.config.ts
import { honoDecks } from "hono-decks/vite"
import { defineConfig } from "vite"

export default defineConfig({
  plugins: [honoDecks()],
})
package.json
{
  "scripts": {
    "decks:compile": "hono-decks compile",
    "dev": "vite",
    "build": "vite build"
  }
}

For a Cloudflare Worker that runs Wrangler directly, register the compiler as a custom build. The --live-reload flag lets the ordinary dev command watch the deck root and refresh the browser.

wrangler.jsonc
{
  "build": {
    "command": "hono-decks compile",
    "watch_dir": ["decks"]
  }
}
package.json
{
  "scripts": {
    "dev": "wrangler dev --live-reload"
  }
}

Verify it in the browser

Terminal
npm run dev

Open /decks/welcome on the local URL printed by the dev server. The setup works when the Welcome slide appears and the controls or arrow keys move to slide two.

Troubleshooting

Missing src/generated/decks.ts
Run npx hono-decks compile again and check build.root and build.outDir in the config.
/decks returns 404
Mount decks.router() at decks.mountPath.
Node modules enter the Worker bundle
Import runtime APIs from hono-decks. Keep hono-decks/node in build scripts only.

Choose the next step

Continue with authoring slides. Open configuration or routes and UI only when you need environment bindings or different public surfaces.