Integration Guide

Add dioxus-docs-kit to your own Dioxus project step by step

Overview

This guide walks you through adding dioxus-docs-kit to an existing Dioxus 0.7 project. By the end, you'll have a fully functional documentation site with sidebar navigation, search, and optional OpenAPI reference pages.

Prerequisites

  • A working Dioxus 0.7 project with features = ["router", "fullstack"]
  • The Dioxus CLI (dx): curl -sSL http://dioxus.dev/install.sh | sh

Setup

1

Add dependencies

Add dioxus-docs-kit and the build helper to your Cargo.toml:

toml
[dependencies]
dioxus = { version = "0.7", features = ["router", "fullstack"] }
dioxus-docs-kit = "0.7"

[build-dependencies]
dioxus-docs-kit-build = "0.7"

[features]
default = ["web"]
web = ["dioxus/web", "dioxus-docs-kit/web"]
server = ["dioxus/server", "dioxus-docs-kit/server"]

The kit's defaults bring mermaid and openapi. Syntax highlighting is always on and needs no feature — see the crate README's Syntax Highlighting section. To ship less, set default-features = false and list the features you need.

2

Create the docs directory

Create your content structure:

text
docs/
├── _nav.json
├── getting-started/
│   └── introduction.mdx
└── api-reference/
    └── overview.mdx

Each .mdx file needs frontmatter:

mdx
---
title: Introduction
description: Welcome to the docs
sidebarTitle: Introduction
icon: book-open
---

Your content here.
3

Configure navigation

Create docs/_nav.json:

json
{
  "tabs": ["Docs", "API Reference"],
  "groups": [
    {
      "group": "Getting Started",
      "tab": "Docs",
      "pages": ["getting-started/introduction"]
    },
    {
      "group": "API Reference",
      "tab": "API Reference",
      "pages": ["api-reference/overview"]
    }
  ]
}
4

Create build.rs

Add a build.rs at the project root to parse all content at compile time:

rust
fn main() {
    dioxus_docs_kit_build::DocsBuild::new("docs/_nav.json").generate();
}

This reads _nav.json, emits cargo:rerun-if-changed for all MDX files, parses every page (rendering its prose to HTML), builds the search index, and writes docs_bundle.json to OUT_DIR.

To include an OpenAPI spec, chain .with_openapi() with the spec's path — it is parsed here, not in the browser:

rust
dioxus_docs_kit_build::DocsBuild::new("docs/_nav.json")
    .with_openapi("api-reference", "docs/api-reference/openapi.yaml")
    .generate();
5

Wire up the registry

In main.rs, load the bundle with the docs_bundle!() macro and create the DocsRegistry:

rust
use dioxus::prelude::*;
use dioxus_docs_kit::{
    DocsConfig, DocsContext, DocsLayout, DocsPageContent,
    DocsRegistry, use_docs_providers,
};
use std::sync::LazyLock;

static DOCS: LazyLock<DocsRegistry> = LazyLock::new(|| {
    DocsConfig::new(dioxus_docs_kit::docs_bundle!())
        .with_default_path("getting-started/introduction")
        .build()
});
6

Create the docs layout wrapper

Create a layout component that provides DocsContext and the registry. The use_docs_providers hook bundles all the context setup into a single call:

rust
#[component]
fn MyDocsLayout() -> Element {
    let nav = use_navigator();
    let route = use_route::<Route>();

    let current_path = use_memo(move || match route.clone() {
        Route::DocsPage { slug } => slug.join("/"),
        _ => String::new(),
    });

    // The constructor defaults the meta fields (`auto_meta: true`,
    // no site_url, no markdown alternate links); use the `with_*`
    // setters to override them.
    let docs_ctx = DocsContext::new(
        current_path,
        "/docs",
        Callback::new(move |path: String| {
            let slug: Vec<String> =
                path.split('/').map(String::from).collect();
            nav.push(Route::DocsPage { slug });
        }),
    )
    // Public origin used for canonical URLs and OG tags — set it
    // in production.
    .with_site_url("https://your-site.com");

    let providers = use_docs_providers(&*DOCS, docs_ctx);

    rsx! {
        DocsLayout {
            // Use providers.search_open / providers.drawer_open
            // in a custom header if needed
            Outlet::<Route> {}
        }
    }
}

The DocsProviders struct returned by the hook gives you access to search_open and drawer_open signals for wiring up custom header buttons.

7

Add routes

Add the docs routes to your Route enum:

rust
#[derive(Debug, Clone, Routable, PartialEq)]
enum Route {
    #[layout(MyDocsLayout)]
        #[redirect("/docs", || Route::DocsPage {
            slug: vec!["getting-started".into(), "introduction".into()]
        })]
        #[route("/docs/:..slug")]
        DocsPage { slug: Vec<String> },
}

#[component]
fn DocsPage(slug: Vec<String>) -> Element {
    rsx! {
        DocsPageContent { path: slug.join("/") }
    }
}
8

Build for production

Always bundle with debug symbols off:

bash
dx bundle --web --release --debug-symbols false

dx keeps DWARF by default, wasm-opt aborts on it, and dx then silently ships the unoptimized wasm — this site was 25 MB instead of 7 MB until that flag was added. Add brotli sidecars (.br next to each .wasm/.js/.css in the bundle) and dioxus-server serves them as content-encoding: br automatically; the wasm then costs about 1.4 MB on the wire.

What You Get

Once integrated, your docs site includes:

Sidebar Navigation

Auto-generated from _nav.json with tab switching and group headings

Full-Text Search

Built-in search modal (Cmd+K) across all doc content

API Reference

Two-column endpoint pages generated from OpenAPI specs

Page Navigation

Previous/next page links at the bottom of every page

Next Steps

Page metadata and not-found responses

With auto_meta enabled (the default), documentation and blog metadata updates during client navigation. The kit removes its previous canonical URL, description, social tags, Markdown alternate, and structured data when leaving a page. Consumer-supplied head tags are left alone. Use with_auto_meta(false) if your app manages page metadata itself.

Missing documentation paths, API operations, blog posts, and category pages render a not-found view with noindex. With the kit's server feature enabled, direct requests also return HTTP 404. The not-found title and noindex remain enabled when automatic metadata is off. Navigating to an existing page removes the not-found metadata.

Client-only hosting controls HTTP status codes separately; enable server rendering to use the kit's HTTP 404 handling.

Navigation