Welcome to Zudoku preview! Open a GitHub issue if you have feature requests or find any issues.
Zudoku
Configuration

Navigation

Zudoku uses a single navigation array to control both the top navigation tabs and the sidebar. Items at the root of this array appear as tabs, and nested items build the sidebar tree. Navigation entries can be links, document references, categories or custom pages.

Basic configuration

The navigation is defined using the navigation array in the Zudoku config file. Each item can be one of several types. At the simplest level you may only have links and categories.

Code(json)
{ "navigation": [ { "type": "category", "label": "Documentation", "icon": "book", "items": [ { "type": "doc", "file": "documentation/introduction", "label": "Introduction", "icon": "file-text" }, { "type": "doc", "file": "documentation/getting-started", "path": "/docs/quick-start", "label": "Quick Start" } ] }, { "type": "link", "to": "/api", "label": "API Reference", "icon": "code", "description": "Complete API documentation", "badge": { "label": "v2.0", "color": "blue" }, "display": "always" } ] }

Navigation items can be of these types: category, doc, link, or custom-page.

  • link: A direct link to a page or external URL.
  • category: A group of links that can be expanded or collapsed.
  • doc: A reference to a document by it file path: file.
  • custom-pages: A custom page that is made of a React component, see Custom Pages

link is the most basic item, it directly links to a path or URL. Use this for external resources or standalone pages.

Code(json)
{ "type": "link", "label": "Support", "to": "/my/api" // or: https://example.com/my-external-link }
TypeScript type declaration
Code(ts)
type NavigationLink = { type: "link"; to: string; label: string; icon?: string; // Lucide icon name description?: string; badge?: { label: string; color: "green" | "blue" | "yellow" | "red" | "purple" | "indigo" | "gray" | "outline"; }; display?: "auth" | "anon" | "always" | "hide"; };

type: category

The category type groups related items under a collapsible section. The label is the displayed text, and the items array contains ids of documents, links, or other categories.

Code(json)
{ "type": "category", "label": "Getting Started", "collapsible": true, // optional "collapsed": false, // optional "items": [ { "type": "link", "label": "Support", "to": "https://support.example.com" } ] }
TypeScript type declaration
Code(ts)
type NavigationCategory = { type: "category"; icon?: string; // Lucide icon name items: Array< NavigationDoc | NavigationLink | NavigationCategory | NavigationCustomPage >; label: string; collapsible?: boolean; collapsed?: boolean; link?: string | { type: "doc"; file: string; label?: string }; display?: "auth" | "anon" | "always" | "hide"; };

type: doc

Doc is used to reference markdown files. The label is the text that will be displayed, and the file is the file path associated with a markdown file.

Code(json)
{ "type": "doc", "label": "Overview", "file": "docs/overview" }
TypeScript type declaration
Code(ts)
type NavigationDoc = { type: "doc"; file: string; path?: string; icon?: string; label?: string; badge?: { label: string; color: | "green" | "blue" | "yellow" | "red" | "purple" | "indigo" | "gray" | "outline"; }; display?: "auth" | "anon" | "always" | "hide"; };

Using shorthands

Documents can be referenced as strings (using their file path), which is equivalent to { "type": "doc", "file": "path" }:

Code(json)
{ "navigation": [ { "type": "category", "label": "Documentation", "icon": "book", "items": [ "documentation/introduction", "documentation/getting-started", "documentation/installation" ] }, { "type": "link", "to": "/api", "label": "API Reference", "icon": "code" } ] }

This is much more concise when you don't need custom labels, icons, or other properties for individual documents.

Learn more in the Markdown documentation

Custom paths

The path property allows you to customize the URL path for a document. By default, Zudoku uses the file path to generate the URL, but you can override this behavior by specifying a custom path.

type: custom-page

Custom pages allow you to create standalone pages that are not tied to a Markdown document. This is useful for creating landing pages, dashboards, or any other custom content.

Code(tsx)
{ type: "custom-page", path: "/a-custom-page", element: <MyCustomPage />, display: "always" }
TypeScript type declaration
Code(ts)
type NavigationCustomPage = { type: "custom-page"; path: string; label?: string; element: any; icon?: string; // Lucide icon name badge?: { label: string; color: | "green" | "blue" | "yellow" | "red" | "purple" | "indigo" | "gray" | "outline"; invert?: boolean; }; display?: "auth" | "anon" | "always" | "hide"; };

Display Control

All navigation items support a display property that controls when the item should be visible:

  • "always" (default): Always visible
  • "auth": Only visible when user is authenticated
  • "anon": Only visible when user is not authenticated
  • "hide": Never visible (useful for temporarily hiding items)
Code(json)
{ "type": "link", "label": "Admin Panel", "to": "/admin", "display": "auth" }

Badges

Navigation items can display badges with labels and colors. Badges support an optional invert property for styling:

Code(json)
{ "type": "doc", "file": "api/v2", "badge": { "label": "Beta", "color": "yellow" } }

Icons

Icons can be added to categories and documents by specifying an icon property. The value should be the name of a Lucide icon (e.g., book , code , file-text ).

Code(json)
{ "type": "category", "label": "Getting Started", "icon": "book" }

They can also be set on individual documents in their front matter:

Code(md)
--- title: My Document sidebar_icon: book ---

Title & Labels

All navigation items can have a label property that determines the displayed text. For doc items, the label is optional; if omitted, Zudoku uses the document's title from its front matter or the first # header.

To override the navigation label without changing the document's title, use the sidebar_label property in the front matter:

Code(md)
--- title: My Long Title sidebar_label: Short Title ---

In this example, the document's title remains "My Long Title," but the sidebar displays "Short Title."

Last modified on