Honeydeck Docs
Core

Customization

Customization documentation for Honeydeck.

Customization

Honeydeck starts with built-in layouts and a small base theme. Customize only what you need: CSS tokens, React components, or a layout map.

Mental model

ConcernWhat you writeHow you use it
ThemeCSS files with Honeydeck tokens and Tailwind utilitiesimport CSS from deck.mdx or from another CSS file
ComponentsReact componentsimport them in MDX
LayoutsReact layout components in a layout mapset layouts: in deck frontmatter, then choose layout: per slide

All references are explicit. Local files and installed packages work the same way: import the module you want.

Start with CSS

The starter deck imports ./styles.css from deck.mdx:

import './styles.css'

# Hello world

A typical styles file imports Tailwind and the Honeydeck base theme:

@import "tailwindcss";
@import "@honeydeck/honeydeck/theme.css";

Override tokens after the base theme:

@import "tailwindcss";
@import "@honeydeck/honeydeck/theme.css";

:root {
  --honeydeck-primary: oklch(55% 0.25 280);
  --honeydeck-font-heading: "Playfair Display", serif;
  --honeydeck-border-radius: 1rem;
}

Target light and dark modes when needed:

[data-honeydeck-color-mode="light"] {
  --honeydeck-primary: oklch(50% 0.2 250);
}

[data-honeydeck-color-mode="dark"] {
  --honeydeck-primary: oklch(70% 0.2 250);
}

Bundled themes and layouts

The default visual style is clean black, white, and grey:

@import "tailwindcss";
@import "@honeydeck/honeydeck/theme.css";

@honeydeck/honeydeck/themes/clean.css is available as an optional named clean layer.

The Bee theme adds the original playful palette:

@import "tailwindcss";
@import "@honeydeck/honeydeck/theme.css";
@import "@honeydeck/honeydeck/themes/bee.css";

Use the matching Bee layout set when you want Bee slide chrome too:

---
layouts: "@honeydeck/honeydeck/layouts/bee"
---

The default clean layout set is available through either path:

---
layouts: "@honeydeck/honeydeck/layouts"
---
---
layouts: "@honeydeck/honeydeck/layouts/clean"
---

Tailwind token utilities

Honeydeck maps theme tokens to Tailwind utilities:

<div className="rounded-honeydeck border border-border bg-surface p-6 text-surface-foreground">
  Styled with Honeydeck tokens.
</div>

Useful color utilities include primary, primary-foreground, accent, accent-foreground, background, foreground, surface, surface-foreground, and border.

Design tokens

Themes provide CSS custom properties. Colors derive from a primary using oklch relative color syntax, with separate values for light and dark modes:

[data-honeydeck-color-mode="light"] {
  --honeydeck-primary: oklch(50% 0.2 250);
  --honeydeck-background: oklch(from var(--honeydeck-primary) 98% 0.01 h);
  --honeydeck-foreground: oklch(from var(--honeydeck-primary) 15% 0.02 h);
  --honeydeck-surface: oklch(from var(--honeydeck-primary) 94% 0.02 h);
}
TokenPurpose
--honeydeck-primaryBrand color for this mode
--honeydeck-primary-foregroundText on primary backgrounds
--honeydeck-backgroundMain slide background
--honeydeck-foregroundMain text color
--honeydeck-surfaceCards, code blocks, callouts
--honeydeck-surface-foregroundText on surfaces
--honeydeck-borderBorder/divider color
--honeydeck-accentAccent, computed as complementary by default
--honeydeck-accent-foregroundText on accent backgrounds
--honeydeck-link-colorLink color, defaulting to inherit
--honeydeck-border-radiusDefault border radius
--honeydeck-font-headingHeading font family
--honeydeck-font-bodyBody font family
--honeydeck-font-monoMonospace font family
--honeydeck-font-baseBase font size, defaulting to 16px
--honeydeck-font-scaleHeading scale factor, defaulting to 1.25
--honeydeck-code-line-dim-opacityDim opacity for non-highlighted code lines

Use built-in layouts

Select a layout in slide frontmatter:

---
layout: Section
---

# Big idea

If no layout: is specified, Default is used. Layout names are PascalCase.

LayoutDescription
BlankEmpty slide with only children
DefaultTitle top-left, body flows below
SectionBig centered heading for section breaks
CoverOpening/closing slide with title, body, author, and date
TwoColTwo equal columns
ImageProminent image with optional title and caption/content
ImageLeftProminent left image with title and body on the right
ImageRightProminent right image with title and body on the left

Extra slide frontmatter fields are passed to the selected layout:

---
layout: Cover
author: You_Name_Here
---

# Honeydeck

A modern slide framework.

Two-column slides

TwoCol uses slot components from the active layout set:

---
layout: TwoCol
---

import { Left, Right } from '@honeydeck/honeydeck/layouts/TwoCol'

<Left>
## Benefits
- Fast iteration
- Live reload
</Left>

<Right>
## Trade-offs
- Requires Node.js
</Right>

For Bee layouts, import slots from the Bee path:

import { Left, Right } from '@honeydeck/honeydeck/layouts/bee/TwoCol'

Image slides

Image, ImageLeft, and ImageRight accept image, darkImage, and alt frontmatter:

---
layout: ImageRight
image: /photos/launch.jpg
darkImage: /photos/launch-dark.jpg
alt: Launch moment
---

# Launch moment

Supporting context sits beside the image.

Create custom layouts

Custom layouts are React components. Use a layout map when you want layout: frontmatter to select them.

// layouts/Hero.tsx
import type { LayoutProps } from '@honeydeck/honeydeck/types'

export default function HeroLayout({ title, children }: LayoutProps) {
  return (
    <div className="grid h-full place-items-center bg-gradient-to-br from-purple-900 to-indigo-900 p-12 text-center text-white">
      <div>
        {title ? <h1>{title}</h1> : null}
        {children}
      </div>
    </div>
  )
}

Create a layout map:

// layouts/index.ts
import type { LayoutMap } from '@honeydeck/honeydeck/types'
import defaultLayouts from '@honeydeck/honeydeck/layouts'
import HeroLayout from './Hero'

export default {
  ...defaultLayouts,
  Hero: HeroLayout,
} satisfies LayoutMap

Reference it from deck frontmatter:

---
layouts: "./layouts"
---

Use it on any slide:

---
layout: Hero
---

# Special slide

With a custom gradient background.

You can also import a React component directly and wrap slide content when you do not need a layout map:

---

import { GradientPanel } from './components/GradientPanel'

<GradientPanel>
# Special slide
</GradientPanel>

---

Layout props

LayoutProps is generic so layouts can type their accepted frontmatter:

type LayoutProps<F extends Record<string, unknown> = Record<string, unknown>> = {
  title: ReactNode | null
  children: ReactNode
  rawChildren: ReactNode
  frontmatter: F
}

Example typed layout:

import type { LayoutProps } from '@honeydeck/honeydeck/types'

type CoverFrontmatter = {
  author?: string
  date?: string
}

export function CoverLayout({ title, children, frontmatter }: LayoutProps<CoverFrontmatter>) {
  const { author, date } = frontmatter
  return (/* ... */)
}

Layout demos

Layouts can export a demo constant for /#/layouts:

import type { LayoutDemo, LayoutProps } from '@honeydeck/honeydeck/types'

type HeroFrontmatter = {
  /** Short label shown above the title. */
  eyebrow?: string
}

export default function HeroLayout({ title, children, frontmatter }: LayoutProps<HeroFrontmatter>) {
  return (/* ... */)
}

export const demo: LayoutDemo<HeroFrontmatter> = {
  mdx: `---
layout: Hero
eyebrow: Launch
---

# Hero moment

This snippet and preview come from the same demo.`,
}

mdx is the single source for both the live preview and the copyable usage snippet in the layouts reference page. If no demo is exported, the layout still appears with a “No demo MDX provided” hint.

Slot components

Layouts that need content slots can export slot components alongside the layout:

// layouts/TwoCol.tsx
import type { ReactNode } from 'react'
import type { LayoutProps } from '@honeydeck/honeydeck/types'

export function Left({ children }: { children: ReactNode }) {
  return <div data-honeydeck-slot="left" className="col-start-1 overflow-hidden">{children}</div>
}

export function Right({ children }: { children: ReactNode }) {
  return <div data-honeydeck-slot="right" className="col-start-2 overflow-hidden">{children}</div>
}

export default function TwoColLayout({ title, children }: LayoutProps) {
  return (
    <div className="grid h-full grid-cols-2 gap-12">
      {children}
    </div>
  )
}

Users import slots from the layout module:

import { Left, Right } from './layouts/TwoCol'

Image helpers

Built-in placeholder images are available as URL exports for custom image layouts:

import {
  imagePlaceholder,
  imagePlaceholderDark,
  verticalImagePlaceholder,
  verticalImagePlaceholderDark,
} from '@honeydeck/honeydeck/layouts/placeholders'

Use ColorModeImage when a custom layout accepts separate light and dark image URLs:

import { ColorModeImage } from '@honeydeck/honeydeck'

<ColorModeImage src={image} darkSrc={darkImage} alt={alt} />

Runtime reference

During development, open the built-in reference pages:

  • /#/theme shows all --honeydeck-* CSS tokens with computed values and descriptions.
  • /#/layouts shows layouts from the active layout map, live visual previews, copyable snippets, and extracted frontmatter prop docs.
  • /#/components shows public built-in components exported from @honeydeck/honeydeck/components.

On this page