# Docula
Beautiful Website for Your Projects
Source Index: https://docula.org/llms.txt
## Documentation
### Getting Started
URL: https://docula.org/docs/
Description: A beginner-friendly guide to installing and setting up Docula, a documentation site generator, including project initialization, content management, and site building.
# Getting Started
## Install docula via init
> npx docula init
This will create a folder called site with the following structure:
```
site
├───logo.png
├───favicon.ico
├───README.md
├───docula.config.mjs
```
If your project has a `tsconfig.json`, docula will automatically generate a TypeScript config (`docula.config.ts`). To explicitly choose, use `docula init --typescript` or `docula init --javascript`.
## Add your content
Simply replace the logo, favicon, and css file with your own. For the README, docula will automatically read your project root `README.md` at build time and render it as the home page — no copying required. If you want to use a different README just for the site, place one in the site folder and docula will use that instead. This behavior is controlled by the `autoReadme` option (enabled by default).
## Build your site
> npx docula
This will build your site and place it in the `dist` folder. You can then host it anywhere you like.
## Single Page vs Multi Page
Docula supports two modes for organizing your site content:
### Single Page
By default, if no `docs/` folder exists in your site directory, Docula renders a single home page using your `README.md` as the content. This is the simplest setup — no extra configuration needed.
```
site
├───logo.png
├───favicon.ico
├───variables.css
├───README.md
└───docula.config.mjs
```
### Multi Page
To build a site with multiple documentation pages, add a `docs/` folder to your site directory. Docula automatically detects the folder and generates individual pages with sidebar navigation.
```
site
├───logo.png
├───favicon.ico
├───variables.css
├───docula.config.mjs
└───docs
├───index.md
├───configuration.md
└───guides
├───getting-started.md
└───advanced.md
```
Each markdown file becomes its own page. Use front matter to control the title and ordering:
```md
---
title: Configuration
order: 2
---
```
Subdirectories inside `docs/` automatically become sections in the sidebar navigation.
### Automatic Starting View
Docula automatically detects what content exists and picks the starting view for your site:
- **README.md exists** — A dedicated landing page renders at `/` using `home.hbs`, and docs are available at `/docs/`. Docula looks for a `README.md` in your site folder first, then falls back to your project root `README.md` via the `autoReadme` option. When using `autoReadme`, the leading `# Title` heading is automatically stripped from the rendered page to avoid duplicating the site title.
- **No README.md, but docs exist** — The first doc page renders directly as `/index.html`.
- **No README.md, no docs, but `api/swagger.json` exists** — The API page renders as `/index.html`.
### Using AI
URL: https://docula.org/docs/ai/
Description: Automatically fill missing OpenGraph and HTML meta tags using AI
# Using AI
Docula can automatically generate missing metadata for your documentation pages using AI. When configured, it fills gaps in OpenGraph tags, descriptions, and keywords so your pages are optimized for search engines and social sharing without manual effort.
## How It Works
During the build, Docula checks each document and changelog entry for missing metadata fields. If any are missing and AI is configured, it uses [Writr's AI features](https://writr.org) to generate the missing values. Results are cached so unchanged content never triggers redundant API calls.
Fields that are enriched (only when missing):
- `description` - page meta description
- `keywords` - search keywords
- `ogTitle` - OpenGraph title
- `ogDescription` - OpenGraph description
- `title` - changelog entry titles (if missing)
- `preview` - changelog entry previews (if missing)
Both documentation pages and changelog entries receive the full set of SEO fields (`description`, `keywords`, `ogTitle`, `ogDescription`). You can also set these fields manually in changelog entry frontmatter and AI will only fill the ones that are missing.
Existing frontmatter values are never overwritten.
## Configuration
Add the `ai` option to your `docula.config.mjs` or `docula.config.ts`:
```js
export const options = {
ai: {
provider: 'anthropic',
apiKey: process.env.ANTHROPIC_API_KEY,
},
};
```
### Options
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `provider` | `string` | Yes | AI provider: `"anthropic"`, `"openai"`, or `"google"` |
| `apiKey` | `string` | Yes | Your API key for the provider |
| `model` | `string` | No | Override the default model |
### Supported Providers
| Provider | Default Model |
|----------|--------------|
| `anthropic` | `claude-haiku-4-5` |
| `openai` | `gpt-4o-mini` |
| `google` | `gemini-2.5-flash-lite` |
### Custom Model
To use a specific model, set the `model` property:
```js
export const options = {
ai: {
provider: 'anthropic',
apiKey: process.env.ANTHROPIC_API_KEY,
model: 'claude-sonnet-4-6-20250217',
},
};
```
## Disabling AI
To disable AI enrichment, simply omit the `ai` property from your config (it is not set by default).
## Caching
AI results are cached in `.cache/ai/metadata.json` inside your site directory, keyed by a hash of each document's body content. This means:
- Unchanged content reuses cached metadata (no API call)
- Editing the body content triggers re-enrichment on the next build
- Deleting `.cache/ai/metadata.json` forces re-enrichment of all documents
The `.cache` directory is automatically added to `.gitignore`.
## Example
Given a document with minimal frontmatter:
```md
---
title: Getting Started
order: 1
---
# Getting Started
Follow these steps to install and configure Docula for your project...
```
After an AI-enriched build, the built page will include auto-generated meta tags:
```html
```
The source file is not modified - enrichment is applied in-memory during the build.
### Using the CLI
URL: https://docula.org/docs/cli/
Description: Comprehensive guide to Docula's command-line interface, covering all available commands, options, flags, and common workflows for initializing, building, and serving documentation sites.
# Using the CLI
Docula provides a command-line interface for initializing, building, and serving your documentation site. All commands are available via `npx docula` or, if installed globally, just `docula`.
## Commands Overview
| Command | Description |
|---------|-------------|
| `init` | Initialize a new Docula project |
| `build` | Build the site (default if no command is specified) |
| `dev` | Build, watch, and serve the project |
| `start` | Build and serve the project |
| `serve` | Serve the site locally |
| `help` / `--help` / `-h` | Print help information |
| `version` | Print the version number |
| `download` | Download template files to your site directory |
## Common Options
These options are shared across multiple commands:
| Flag | Description | Default |
|------|-------------|---------|
| `-s, --site ` | Set the path where site files are located | `./site` |
| `-c, --clean` | Clean the output directory before building | `false` |
| `-o, --output ` | Set the output directory | `./site/dist` |
| `-p, --port ` | Set the port number | `3000` |
| `-w, --watch` | Watch for file changes and rebuild automatically | `false` |
## help
Print usage information. Available as a subcommand or flag:
```bash
npx docula help
npx docula --help
npx docula -h
```
## init
Scaffolds a new Docula project in the current directory. Creates a `site/` folder with starter files including a logo, favicon, CSS, README, and config file.
```bash
npx docula init
```
By default, docula auto-detects whether your project uses TypeScript by checking for a `tsconfig.json` in the current directory. If found, it generates `docula.config.ts`; otherwise, it generates `docula.config.mjs`. You can override this with the `--typescript` or `--javascript` flags.
### Flags
In addition to the [Common Options](#common-options):
| Flag | Description | Default |
|------|-------------|---------|
| `--typescript` | Force a TypeScript config file (`docula.config.ts`) | auto-detect |
| `--javascript` | Force a JavaScript config file (`docula.config.mjs`) | auto-detect |
### Examples
```bash
# Initialize (auto-detects TypeScript from tsconfig.json)
npx docula init
# Force TypeScript config
npx docula init --typescript
# Force JavaScript config
npx docula init --javascript
# Initialize in a custom directory
npx docula init -s ./docs-site
```
## download
Downloads template files from the active template into your site directory. Use one of the subcommands below to choose what to download. If a target file or directory already exists, the command prints an error and exits. Use `--overwrite` to replace it.
### Subcommands
| Subcommand | Description |
|------------|-------------|
| `variables` | Copy `variables.css` to `site/variables.css` |
| `template` | Copy the full template to `site/templates//` |
### Flags
| Flag | Description | Default |
|------|-------------|---------|
| `--overwrite` | Overwrite existing files if they already exist | `false` |
### Examples
```bash
# Copy variables.css for the current (modern) template
npx docula download variables
# Copy variables.css in a custom site directory
npx docula download variables -s ./my-site
# Overwrite an existing variables.css
npx docula download variables --overwrite
# Copy the full modern template to site/templates/modern/
npx docula download template
# Copy the classic template
npx docula download template --template classic
# Overwrite an existing template copy
npx docula download template --overwrite
```
## build
Builds your site and outputs the result to the configured output directory. This is the default command — running `npx docula` without a subcommand is equivalent to `npx docula build`.
```bash
npx docula build
```
### Flags
In addition to the [Common Options](#common-options):
| Flag | Description | Default |
|------|-------------|---------|
| `-t, --templatePath ` | Set a custom template directory path | - |
| `-T, --template ` | Set the built-in template name (e.g., `modern`) | `modern` |
### Examples
```bash
# Build with defaults
npx docula
# Build with a custom site path and output directory
npx docula build -s ./my-site -o ./my-site/dist
# Build with a custom template
npx docula build --template classic
# Clean build
npx docula build --clean
```
## dev
Builds your site, starts watching for file changes, and serves it locally — all in one command. This is the recommended way to develop locally.
```bash
npx docula dev
```
### Flags
In addition to the [Common Options](#common-options):
| Flag | Description | Default |
|------|-------------|---------|
| `-t, --templatePath ` | Set a custom template directory path | - |
| `-T, --template ` | Set the built-in template name (e.g., `modern`) | `modern` |
### Examples
```bash
# Build, watch, and serve on default port 3000
npx docula dev
# Serve on a custom port
npx docula dev -p 8080
# Clean build, watch, and serve
npx docula dev --clean
```
## start
Builds the site and serves it locally. By default it does not watch for file changes, but you can pass `--watch` to enable live rebuilds.
```bash
npx docula start
```
All flags for `start` are covered by the [Common Options](#common-options).
### Examples
```bash
# Build and serve on default port 3000
npx docula start
# Build and serve on a custom port
npx docula start -p 8080
# Clean build and serve
npx docula start --clean
# Build, serve, and watch for changes
npx docula start --watch
```
## serve
Starts a local development server for your site. By default it listens on port 3000 and serves the existing output directory without running a build. Use `--build` to run a one-time build before serving, or `--watch` to build first and then automatically rebuild on file changes.
```bash
npx docula serve
```
### Flags
In addition to the [Common Options](#common-options):
| Flag | Description | Default |
|------|-------------|---------|
| `-b, --build` | Build the site before serving | `false` |
### Examples
```bash
# Serve the existing build on default port 3000
npx docula serve
# Serve on a custom port
npx docula serve -p 8080
# Build once and serve
npx docula serve --build
# Build, serve, and watch for changes
npx docula serve --watch
# Clean build, serve, and watch for changes
npx docula serve --clean --watch
```
## Watch Mode
Use the `--watch` flag with either `build` or `serve` to automatically rebuild your site when files change:
```bash
npx docula serve --watch
```
When watch mode is enabled:
1. An initial build runs at startup
2. The dev server starts and serves your site (when using `serve`)
3. File changes in the site directory (e.g., `./site`) are detected and trigger an automatic rebuild
4. Changes in the output directory are ignored to prevent rebuild loops
This is useful during development when you want to see changes reflected immediately without manually re-running the build.
## Common Workflows
```bash
# Quick start: scaffold and develop (auto-detects TypeScript)
npx docula init
npx docula download variables
npx docula dev
# Production build
npx docula build --clean
# Force TypeScript config
npx docula init --typescript
npx docula dev
# Custom paths
npx docula build -s ./website -o ./website/dist
```
### Configuration
URL: https://docula.org/docs/configuration/
Description: Complete guide to configuring Docula with TypeScript, JavaScript, or JSON formats, including lifecycle hooks, changelog manipulation, and all available configuration options.
# Configuration
Docula supports three config formats: TypeScript (`docula.config.ts`), ESM JavaScript (`docula.config.mjs`), and JSON (`docula.config.json`). TypeScript gives you type safety; JSON is the only format the [standalone binary](./binary-download) can read. When multiple are present in the same site, the priority is `.ts` → `.mjs` → `.json`.
## Initializing with TypeScript
When you run `npx docula init`, docula automatically detects TypeScript projects by checking for a `tsconfig.json` in the current directory. If found, it generates a `docula.config.ts` file. Otherwise, it generates `docula.config.mjs`.
You can also explicitly choose:
```bash
npx docula init --typescript # Force TypeScript config
npx docula init --javascript # Force JavaScript config
```
The TypeScript config provides full type support:
```typescript
import type { DoculaOptions } from 'docula';
export const options: Partial = {
templatePath: './template',
output: './site/dist',
sitePath: './site',
githubPath: 'your-username/your-repo',
siteTitle: 'My Project',
siteDescription: 'Project description',
siteUrl: 'https://your-site.com',
themeMode: 'light', // or 'dark' — defaults to system preference if omitted
googleTagManager: 'GTM-XXXXXX', // or 'G-XXXXXXXXXX' for GA4
// To target a Google Tag Manager environment, also set:
// googleTagManagerAuth: 'abc123',
// googleTagManagerEnv: 'env-3',
homeUrl: '/', // logo links to this URL instead of baseUrl
baseUrl: '/docs', // host under a subpath
autoReadme: true, // use project root README.md as the home page
docsPath: '', // place docs at the output root
apiPath: 'api',
changelogPath: 'changelog',
};
```
## Using Lifecycle Hooks with TypeScript
You can add typed lifecycle hooks to your config:
```typescript
import type { DoculaConsole, DoculaOptions } from 'docula';
export const options: Partial = {
siteTitle: 'My Project',
// ... other options
};
export const onPrepare = async (config: DoculaOptions, console: DoculaConsole): Promise => {
// Runs before the build process
console.info(`Building ${config.siteTitle}...`);
};
```
## Manipulating Release Changelog Entries
The `onReleaseChangelog` hook lets you modify, filter, or transform GitHub release entries before they are merged with file-based changelog entries and rendered. This is useful for cleaning up release notes, filtering out unwanted releases, or customizing tags.
```typescript
import type { DoculaChangelogEntry, DoculaConsole, DoculaOptions } from 'docula';
export const options: Partial = {
githubPath: 'your-username/your-repo',
enableReleaseChangelog: true,
};
export const onReleaseChangelog = (entries: DoculaChangelogEntry[], console: DoculaConsole): DoculaChangelogEntry[] => {
console.info(`Processing ${entries.length} release entries...`);
return entries
// Filter out pre-releases
.filter(entry => entry.tag !== 'Pre-release')
// Customize titles
.map(entry => ({
...entry,
title: entry.title.replace(/^v/, 'Version '),
}));
};
```
Each `DoculaChangelogEntry` has these fields you can read or modify:
| Field | Type | Description |
|-------|------|-------------|
| `title` | `string` | Entry title (from release name or tag) |
| `date` | `string` | Date string (YYYY-MM-DD) |
| `formattedDate` | `string` | Localized display date |
| `tag` | `string?` | Badge label (e.g., "Release", "Pre-release") |
| `tagClass` | `string?` | CSS class derived from tag |
| `slug` | `string` | URL-friendly identifier |
| `content` | `string` | Raw markdown content |
| `generatedHtml` | `string` | Rendered HTML |
| `preview` | `string` | Auto-generated preview HTML for the changelog index (300-500 chars, paragraph-aware, headings and images stripped) |
| `previewImage` | `string?` | Image URL displayed above the preview on the changelog listing page (set via front matter) |
| `urlPath` | `string` | Output file path |
| `description` | `string?` | SEO description for the entry page (set via front matter or AI enrichment) |
| `keywords` | `string[]?` | SEO keywords for the entry page (set via front matter or AI enrichment) |
| `ogTitle` | `string?` | OpenGraph title override (set via front matter or AI enrichment) |
| `ogDescription` | `string?` | OpenGraph description override (set via front matter or AI enrichment) |
The hook can be synchronous or async. If the hook throws an error, it is logged and the unmodified entries are used.
## Cleaning Up the Auto README
When `autoReadme` is enabled and docula falls back to your project root `README.md` for the home page, the `onAutoReadme` hook lets you transform that markdown before it is rendered. This is useful for stripping a shields/badges banner, removing an "Install" section that doesn't belong on the home page, or rewriting relative links.
```typescript
import type { DoculaConsole, DoculaOptions } from 'docula';
export const options: Partial = {
autoReadme: true,
};
export const onAutoReadme = (content: string, sourcePath: string, console: DoculaConsole): string => {
console.info(`Cleaning up README at ${sourcePath}`);
return content
// Drop everything from "## Install" up to the next H2
.replace(/^##\s+Install[\s\S]*?(?=^##\s)/m, '')
// Rewrite relative links to absolute
.replace(/\]\(\.\//g, '](https://github.com/your-username/your-repo/blob/main/');
};
```
The hook receives:
| Argument | Type | Description |
|----------|------|-------------|
| `content` | `string` | The resolved README markdown (with a `# name` title prepended if the README had none) |
| `sourcePath` | `string` | Absolute path of the root `README.md` |
| `console` | `DoculaConsole` | Logger (see below) |
The hook can be synchronous or async and must return the new markdown. If the hook throws, the error is logged and the original content is used. The hook only runs when `autoReadme` is enabled and there is no `README.md` in the site directory.
## DoculaConsole Logger
The `onPrepare`, `onReleaseChangelog`, and `onAutoReadme` hooks all receive a `DoculaConsole` instance as their last argument. This provides styled, consistent logging output:
| Method | Description |
|--------|-------------|
| `console.log(message)` | Plain text output |
| `console.info(message)` | Informational message with cyan prefix |
| `console.warn(message)` | Warning message with yellow prefix |
| `console.error(message)` | Error message with red prefix |
| `console.success(message)` | Success message with green prefix |
| `console.step(message)` | Step/progress message with blue prefix |
## Config File Priority
When both config files exist, Docula loads them in this order (first found wins):
1. `docula.config.ts` (TypeScript - takes priority)
2. `docula.config.mjs` (JavaScript)
## Available Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `templatePath` | `string` | `'./template'` | Path to custom template directory |
| `output` | `string` | `'{sitePath}/dist'` | Output directory for built site (defaults to `dist/` inside the site directory) |
| `sitePath` | `string` | `'./site'` | Directory containing site content |
| `githubPath` | `string` | `''` | GitHub repository path (e.g., `'user/repo'`). Optional — when empty, GitHub features are disabled. See [GitHub Integration](/docs/github-integration). |
| `siteTitle` | `string` | `'docula'` | Website title |
| `siteDescription` | `string` | - | Website description |
| `siteUrl` | `string` | - | Website URL |
| `port` | `number` | `3000` | Port for local development server |
| `sections` | `DoculaSection[]` | - | Documentation sections |
| `openApiUrl` | `string \| Array<{ name: string; url: string; order?: number }>` | - | OpenAPI spec for API documentation. Pass a string for a single spec, or an array for multiple specs. Auto-detected if `api/swagger.json` exists. See [API Reference](/docs/api-reference). |
| `enableReleaseChangelog` | `boolean` | `true` | Convert GitHub releases to changelog entries |
| `changelogPerPage` | `number` | `20` | Number of changelog entries to display per page |
| `enableLlmsTxt` | `boolean` | `true` | Generate `llms.txt` and `llms-full.txt` in the build output |
| `enableSearch` | `boolean` | `true` | Generate `search-index.json` and render the search modal (⌘K / Ctrl K) in the modern template. See [Search](/docs/search). |
| `themeMode` | `'light'` \| `'dark'` | - | Override the default theme. By default the site follows the system preference. Set to `'light'` or `'dark'` to use that theme when no user preference is stored. |
| `cookieAuth` | `{ loginUrl: string; logoutUrl?: string; authCheckUrl?: string; authCheckMethod?: string; authCheckUserPath?: string }` | - | Enables cookie-based authentication, which displays a Login/Logout button in the header. See [Cookie Auth](/docs/cookie-auth). |
| `headerLinks` | `Array<{ label: string; url: string; icon?: string }>` | - | Additional links to display in the site header navigation. See [Header Links](/docs/header-links). |
| `homeUrl` | `string` | - | URL for the logo/home link in the header. When set, the logo links to this URL instead of `baseUrl`. Useful when hosting docs under a subpath and the logo should link to the parent site. |
| `baseUrl` | `string` | `''` | Base URL path prefix for all generated paths (e.g., `'/docs'`). When set, all asset and navigation URLs are prefixed with this path. Useful when hosting docs under a subpath of another site. |
| `docsPath` | `string` | `'docs'` | Output subdirectory and URL segment for documentation pages. Set to `''` to place docs at the output root — useful with `baseUrl` to avoid `/docs/docs/` nesting. |
| `apiPath` | `string` | `'api'` | Output subdirectory and URL segment for API reference pages. |
| `changelogPath` | `string` | `'changelog'` | Output subdirectory and URL segment for changelog pages. |
| `googleTagManager` | `string` | - | Google Tag Manager container ID (e.g., `'GTM-XXXXXX'`) or Google Analytics 4 measurement ID (e.g., `'G-XXXXXXXXXX'`). Injects the appropriate tracking script on every page. |
| `googleTagManagerAuth` | `string` | - | Google Tag Manager environment auth token (`gtm_auth`). Applies to GTM container IDs only; requires `googleTagManagerEnv`. |
| `googleTagManagerEnv` | `string` | - | Google Tag Manager environment name (`gtm_preview`), e.g., `'env-3'`. Applies to GTM container IDs only; requires `googleTagManagerAuth`. |
| `autoReadme` | `boolean` | `true` | Automatically use the project root `README.md` as the home page when no `README.md` exists in the site directory. The leading `# Title` heading is stripped from the rendered page to avoid duplicating the site title. Set to `false` to disable this fallback. |
| `allowedAssets` | `string[]` | *(see [Assets & Public Folder](/docs/assets))* | File extensions to copy from `docs/` and `changelog/` to output |
### Templates
URL: https://docula.org/docs/templates/
Description: Comprehensive guide to Docula's built-in and custom templates, including Modern and Classic designs with feature comparisons and customization options.
# Templates
Docula ships with two built-in templates: **Modern** (default) and **Classic**. You can also provide your own custom template.
## Modern (default)
The Modern template is a contemporary, feature-rich design built for today's documentation sites. It is the default template when you create a new Docula project.
```js
export const options = {
template: 'modern',
};
```
### Documentation Page
Documentation pages use a sticky header bar with icon-based navigation links (Documentation, API Reference, Changelog), a collapsible left sidebar with grouped section navigation, a main content area, and a right-side Table of Contents panel. On mobile, the sidebar collapses into a dropdown selector.

### API Reference Page
When an OpenAPI URL is configured, the Modern template renders a full API reference with a left sidebar listing HTTP methods and endpoint categories, a main content area showing endpoint details with parameters and response codes, and an interactive "Test Request" panel on the right for trying endpoints directly in the browser.

### Key Features
| Feature | Details |
|---------|---------|
| **Theme toggle** | Built-in light/dark/system toggle stored in localStorage |
| **Mobile navigation** | Hamburger menu with slide-out sidebar and backdrop overlay |
| **Sticky header** | Always-visible navigation bar with Documentation, API Reference, and Changelog links |
| **Site title** | Displays the site title text next to the logo in the header |
| **Logo Home Link** | When `homeUrl` is configured, the logo links to that URL instead of `baseUrl` |
| **Copy code** | Code blocks show a copy-to-clipboard button on hover with a checkmark confirmation |
| **Image lightbox** | Clicking images in docs and changelog opens a fullscreen overlay for zoomed viewing |
| **Collapsible sidebar** | Uses `` elements for expandable section navigation |
| **System fonts** | No external font dependencies (`system-ui`, `-apple-system`, etc.) |
| **Syntax highlighting** | Docula code theme with light and dark variants |
| **CSS variables** | Full theming via `--bg`, `--fg`, `--border`, `--surface`, `--link`, and more |
---
## Classic
The Classic template provides a traditional documentation layout inspired by popular open-source project sites. It uses a grid-based design with a prominent sidebar.
```js
export const options = {
template: 'classic',
};
```
### Documentation Page
Documentation pages use a clean white layout with the project logo displayed prominently in the top-left corner, a flat left sidebar listing navigation links, and a main content area with an inline Table of Contents rendered at the top of the page. Code blocks use a dark theme for contrast.

### Key Features
| Feature | Details |
|---------|---------|
| **Grid layout** | Traditional two-column grid with sidebar and content area |
| **Google Fonts** | Uses Open Sans (weights 400, 600, 700) via Google Fonts |
| **Modular CSS** | Separate stylesheets for single-page, multi-page, and landing layouts |
| **Syntax highlighting** | Dracula code theme |
| **CSS variables** | Theming via `--color-primary`, `--color-secondary`, `--sidebar-background`, etc. |
---
## Comparison
| | Modern | Classic |
|---|--------|---------|
| **Theme toggle** | Built-in (light / dark / system) | Not included |
| **Mobile menu** | Hamburger with slide-out sidebar | Sidebar overlay |
| **Header navigation** | Sticky bar with SVG icons | Minimal |
| **Fonts** | System fonts (no external requests) | Google Fonts (Open Sans) |
| **Code theme** | Docula (light + dark) | Dracula |
| **Sidebar style** | Collapsible `` sections | Flat list |
| **CSS architecture** | Single `styles.css` with variables | Modular per-layout files |
---
## Using a Custom Template
If neither built-in template fits your needs, you can point Docula at your own template directory. The directory should contain Handlebars (`.hbs`) files matching the structure of the built-in templates.
### Via config
```typescript
import type { DoculaOptions } from 'docula';
export const options: Partial = {
templatePath: './my-template',
};
```
### Via the CLI
```bash
npx docula build --templatePath ./my-template
```
When `templatePath` is set it takes priority over the `template` option. Your custom template directory should include at minimum:
- `home.hbs` — Landing page
- `docs.hbs` — Documentation page
- `includes/` — Partials (header, footer, sidebar, etc.)
Refer to the built-in templates in the `templates/` directory of the Docula repository for a complete example of the expected structure and available Handlebars variables.
### Multiple Pages
URL: https://docula.org/docs/multiple-pages/
Description: Guide on how to create and organize multiple documentation pages in a site using markdown files and the docs folder structure.
# Building Multiple Pages
If you want to build multiple pages you can easily do that by adding in a `docs` folder to the root of the site folder. Inside of that folder you can add as many pages as you like. Each page will be a markdown file and it will generate a table of contents for you. Here is an example of what it looks like:
```
site
├───site.css
├───logo.png
├───favicon.ico
├───docula.config.mjs
├───docs
│ ├───getting-started.md
│ ├───contributing.md
│ ├───license.md
│ ├───code-of-conduct.md
```
Files in the `docs` directory become documentation pages. An `index.md` file inside `docs` will serve as the main page for the documentation section (e.g., at `/docs/`). The rest of the files will be added to the navigation. If you want to control the title or order of the pages you can do so by setting the `title` and `order` properties in the front matter of each markdown file. Here is an example:
```md
title: Getting Started
order: 2
```
If you want your docs to be the root home page (`/`) instead of the template landing page, remove any `README.md` from your site directory and set `autoReadme: false` in `docula.config.mjs` so docula does not fall back to your project root `README.md`. Docula will then automatically use the first doc as `/index.html`.
### Assets & Public Folder
URL: https://docula.org/docs/assets/
Description: Documentation on how to include and manage assets in markdown documentation, including automatic copying of files to build output and configuration of supported file types.
# Including Assets in Markdown
Non-markdown files placed inside the `docs/` or `changelog/` directories are automatically copied to the build output, preserving their relative paths. This lets you keep images and other assets alongside the markdown that references them.
For `docs/`, only assets that are actually referenced in a document's markdown content are copied. If a file exists in the `docs/` directory but is not referenced by any document, it will not be included in the build output. For `changelog/`, all assets are copied regardless of whether they are referenced.
```
site
├───docs
│ ├───getting-started.md
│ ├───images
│ │ ├───architecture.png
│ │ └───screenshot.jpg
│ └───assets
│ └───example.pdf
├───changelog
│ ├───2025-01-15-initial-release.md
│ └───images
│ └───release-banner.png
```
After building, these files appear at the same relative paths under `dist/`:
```
dist
├───docs
│ ├───getting-started
│ │ └───index.html
│ ├───images
│ │ ├───architecture.png
│ │ └───screenshot.jpg
│ └───assets
│ └───example.pdf
├───changelog
│ ├───initial-release
│ │ └───index.html
│ └───images
│ └───release-banner.png
```
Reference assets from your markdown using relative paths:
```md

[Download PDF](assets/example.pdf)
```
## Supported Extensions
By default the following file extensions are copied:
- **Images:** `.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`, `.webp`, `.avif`, `.ico`
- **Documents:** `.pdf`, `.zip`, `.tar`, `.gz`
- **Media:** `.mp4`, `.webm`, `.ogg`, `.mp3`, `.wav`
- **Data:** `.json`, `.xml`, `.csv`, `.txt`
Files with extensions not in this list are ignored. To customize the list, set `allowedAssets` in your config:
```js
export const options = {
allowedAssets: ['.png', '.jpg', '.gif', '.svg', '.pdf', '.custom'],
};
```
# Public Folder
If you have static assets like images, fonts, or other files that need to be copied directly to your built site, you can use a `public` folder. Any files placed in the `public` folder within your site directory will be automatically copied to the root of your `dist` output folder during the build process.
## Usage
Create a `public` folder inside your site directory:
```
site
├───public
│ ├───images
│ │ ├───screenshot.png
│ │ └───banner.jpg
│ ├───fonts
│ │ └───custom-font.woff2
│ └───downloads
│ └───example.pdf
├───docs
├───logo.svg
├───favicon.ico
└───docula.config.mjs
```
When you run the build command, all contents of the `public` folder will be copied to the `dist` folder:
```
dist
├───images
│ ├───screenshot.png
│ └───banner.jpg
├───fonts
│ └───custom-font.woff2
├───downloads
│ └───example.pdf
├───index.html
└───...
```
The build output will show each file being copied:
```
Public folder found, copying contents to dist...
Copied: images/screenshot.png
Copied: images/banner.jpg
Copied: fonts/custom-font.woff2
Copied: downloads/example.pdf
Build completed in 1234ms
```
This is useful for:
- Images referenced in your documentation
- Downloadable files (PDFs, zip archives, etc.)
- Custom fonts
- Any other static assets that need to be served from your site
### Styling
URL: https://docula.org/docs/styling/
Description: A comprehensive guide to styling and customizing your Docula site using CSS variables, custom stylesheets, and template overrides.
# Styling Your Site
Docula gives you full control over the look and feel of your site through CSS variables and a custom stylesheet. The built-in templates define a set of CSS variables that you can override in your `site/variables.css` file.
## Custom Stylesheet
Each template ships with a default `variables.css` that defines its CSS variables. To customize your site's appearance, create a `variables.css` file in your site directory. This file replaces the template's defaults during the build, so any values you set here take priority.
The quickest way to get started is to run:
```bash
npx docula download variables
```
This copies the current template's `variables.css` into your site directory with all default values in place, ready for you to edit. If the file already exists, pass `--overwrite` to replace it.
```
site/
variables.css <-- your overrides go here
logo.png
favicon.ico
docula.config.ts
```
## CSS Variables (Modern Template)
The Modern template uses the following CSS variables. Override any of these in `variables.css` to customize your site.
### Colors
| Variable | Dark Default | Light Default | Description |
|----------|-------------|---------------|-------------|
| `--bg` | `#121212` | `#ffffff` | Page background |
| `--fg` | `#ffffff` | `#1a1a1a` | Primary text color |
| `--border` | `rgba(255,255,255,0.1)` | `rgba(0,0,0,0.1)` | Border color |
| `--border-strong` | `rgba(255,255,255,0.2)` | `rgba(0,0,0,0.15)` | Stronger border for emphasis |
| `--border-hover` | `rgba(255,255,255,0.4)` | `rgba(0,0,0,0.3)` | Border color on hover |
| `--surface` | `#262626` | `#f0f0f0` | Card and surface backgrounds |
| `--surface-hover` | `rgba(255,255,255,0.1)` | `rgba(0,0,0,0.06)` | Surface hover state |
| `--muted` | `#c5cdd3` | `#6b7280` | Muted/secondary text |
| `--muted-fg` | `rgba(255,255,255,0.65)` | `rgba(0,0,0,0.5)` | Muted foreground |
| `--code-bg` | `rgba(255,255,255,0.075)` | `rgba(0,0,0,0.05)` | Inline code background |
| `--pre-bg` | `rgba(255,255,255,0.05)` | `rgba(0,0,0,0.03)` | Code block background |
| `--link` | `#6ea8fe` | `#0969da` | Link color |
| `--scrollbar` | `rgba(255,255,255,0.2)` | `rgba(0,0,0,0.2)` | Scrollbar thumb color |
### Example Override
```css
:root {
--bg: #0d1117;
--fg: #e6edf3;
--link: #58a6ff;
--surface: #161b22;
--border: rgba(240, 246, 252, 0.1);
}
[data-theme="light"] {
--bg: #f6f8fa;
--fg: #24292f;
--link: #0550ae;
--surface: #ffffff;
--border: rgba(0, 0, 0, 0.1);
}
```
## CSS Variables (Classic Template)
The Classic template uses a different set of variables focused on named semantic colors.
| Variable | Default | Description |
|----------|---------|-------------|
| `--font-family` | `'Open Sans', sans-serif` | Base font family |
| `--color-primary` | `#322d3c` | Primary brand color |
| `--color-secondary` | `#8cdc00` | Accent/highlight color |
| `--color-text` | `#322d3c` | Body text color |
| `--background` | `#ffffff` | Page background |
| `--home-background` | `#ffffff` | Home page background |
| `--header-background` | `#ffffff` | Header background |
| `--sidebar-background` | `#ffffff` | Sidebar background |
| `--sidebar-text` | `#322d3c` | Sidebar link color |
| `--sidebar-text-active` | `var(--color-secondary)` | Active sidebar link color |
| `--border` | `rgba(238,238,245,1)` | Border color |
| `--code` | `rgba(238,238,245,1)` | Code block background |
## Blockquote Alerts
Docula supports GitHub-style blockquote alerts via Writr's markdown plugins. Use the following syntax in any markdown file:
```md
> [!NOTE]
> Useful information that users should know.
> [!WARNING]
> Important information that could cause issues.
> [!CAUTION]
> Critical information about risks or destructive actions.
```
To style these alerts, add CSS rules targeting the `.markdown-alert` classes in your `variables.css`:
```css
.markdown-alert {
border-left: 4px solid var(--border);
border-radius: 8px;
margin: 1rem 0;
padding: 0.75rem 1rem;
background: var(--surface);
}
.markdown-alert-note {
border-left-color: #4c8ef7;
}
.markdown-alert-warning {
border-left-color: #f2b90c;
}
.markdown-alert-caution {
border-left-color: #e5534b;
}
```
## Copy Code Button
The Modern template adds a copy-to-clipboard button to every code block. The button appears in the top-right corner on hover and shows a checkmark after copying. Because `variables.css` loads before the template stylesheet, these class overrides require a [partial template override](/docs/partial-templates) of `css/styles.css` to take effect:
| Class | Description |
|-------|-------------|
| `.copy-code-btn` | The button element (positioned absolute inside `pre`) |
| `pre:hover .copy-code-btn` | Controls visibility — the button fades in on hover |
| `.copy-code-btn:hover` | Hover state for the button itself |
```css
.copy-code-btn {
background: var(--surface);
color: var(--muted);
border-radius: 6px;
opacity: 0;
}
pre:hover .copy-code-btn {
opacity: 1;
}
.copy-code-btn:hover {
color: var(--fg);
}
```
## Image Lightbox
Clicking an image in docs or changelog opens a fullscreen lightbox overlay. Like the copy code button, these overrides require a [partial template override](/docs/partial-templates) of `css/styles.css`:
| Class | Description |
|-------|-------------|
| `.lightbox-overlay` | The fullscreen backdrop (default `rgba(0,0,0,0.8)`) |
| `.lightbox-overlay img` | The zoomed image (max 90vw × 90vh, rounded corners, shadow) |
| `.lightbox-close` | The close button in the top-right corner |
```css
.lightbox-overlay {
background: rgba(0, 0, 0, 0.9);
}
.lightbox-overlay img {
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
}
.lightbox-close {
color: rgba(255, 255, 255, 0.8);
}
.lightbox-close:hover {
color: #fff;
}
```
## Logo and Favicon
Replace the default files in your site directory to use your own branding:
- `site/logo.png` (or `logo.svg`) -- displayed in the header and home page hero
- `site/favicon.ico` -- browser tab icon
If `site/favicon.ico` is not present, Docula automatically uses `site/logo.svg`
or `site/logo.png` (in that order) as the favicon.
### Changelog
URL: https://docula.org/docs/changelog/
Description: A comprehensive guide to setting up and using Docula's changelog feature for documenting project releases, updates, and changes.
# Changelog
Docula can generate a changelog section for your site from markdown files. This is useful for documenting release notes, updates, and changes to your project in a structured, browsable format.
## Setup
Create a `changelog` folder inside your site directory and add markdown (`.md` or `.mdx`) files for each entry:
```
site
├───changelog
│ ├───2025-01-15-initial-release.md
│ ├───2025-02-01-new-features.md
│ └───2025-03-10-bug-fixes.md
├───logo.svg
├───favicon.ico
└───docula.config.mjs
```
## Entry Format
Each changelog entry is a markdown file with front matter:
```md
---
title: "Initial Release"
date: 2025-01-15
tag: "Release"
---
We're excited to announce the initial release! Here's what's included:
- Feature A
- Feature B
- Bug fix C
```
### Front Matter Fields
| Field | Required | Description |
|-------|----------|-------------|
| `title` | No | Display title for the entry. Defaults to the filename if not provided. |
| `date` | Yes | Date of the entry (`YYYY-MM-DD`). Used for sorting (newest first). |
| `tag` | No | A label displayed as a badge (e.g., `Release`, `Bug Fix`, `Feature`). Gets a CSS class based on its value for styling. |
| `draft` | No | When `true`, the entry is excluded from the build output. Useful for work-in-progress entries. |
| `previewImage` | No | Image URL displayed above the preview on the changelog listing page. |
## Draft Entries
To hide a changelog entry from the build output, add `draft: true` to the front matter:
```md
---
title: "Upcoming Feature"
date: 2025-04-01
tag: "Feature"
draft: true
---
This entry won't appear on the site until `draft` is removed or set to `false`.
```
Draft entries are still parsed but excluded from the changelog listing, individual entry pages, sitemaps, and feeds. This is useful for preparing entries ahead of a release.
## File Naming
Files can optionally be prefixed with a date in `YYYY-MM-DD-` format. The date prefix is stripped to create the URL slug:
- `2025-01-15-initial-release.md` → `/changelog/initial-release/`
- `new-features.md` → `/changelog/new-features/`
## Generated Pages
When changelog entries are found, Docula generates:
- **Changelog listing page** at `/changelog/` — shows all entries sorted by date (newest first) with titles, dates, tags, and content
- **Individual entry pages** at `/changelog/{slug}/` — a dedicated page for each entry with a back link to the listing
Changelog URLs are also automatically added to the generated `sitemap.xml`.
## JSON Feeds
When changelog entries exist, Docula automatically generates two JSON Feed files at the root of your output directory:
- **`changelog.json`** — contains all changelog entries
- **`changelog-latest.json`** — contains only the most recent entries, limited by the `changelogPerPage` setting (default 20)
Both files follow the [JSON Feed v1.1](https://www.jsonfeed.org/version/1.1/) specification and include full entry content in both HTML and markdown formats, making them useful for programmatic consumption, integrations, or building custom changelog UIs.
### Example Structure
```json
{
"version": "https://jsonfeed.org/version/1.1",
"title": "My Project",
"description": "Project description",
"home_page_url": "https://your-site.com/",
"feed_url": "https://your-site.com/changelog.json",
"items": [
{
"id": "initial-release",
"title": "Initial Release",
"url": "https://your-site.com/changelog/initial-release",
"date_published": "2025-01-15",
"date_modified": "2025-01-15",
"summary": "We're excited to announce the initial release!",
"content_html": "
We're excited to announce the initial release!
",
"content_text": "We're excited to announce the initial release!",
"tags": ["Release"]
}
]
}
```
## Styling
Tags receive a CSS class based on their value (e.g., a tag of `"Bug Fix"` gets the class `changelog-tag-bug-fix`). Both the modern and classic themes include built-in colors for the following tags:
| Tag | CSS Class | Color |
|-----|-----------|-------|
| `Added` | `.changelog-tag-added` | Green |
| `Improved` | `.changelog-tag-improved` | Blue |
| `Fixed` | `.changelog-tag-fixed` | Amber |
| `Removed` | `.changelog-tag-removed` | Red |
| `Deprecated` | `.changelog-tag-deprecated` | Gray |
| `Security` | `.changelog-tag-security` | Purple |
| `Release` | `.changelog-tag-release` | Green |
| `Pre-release` | `.changelog-tag-pre-release` | Yellow |
Any custom tag value also works — it receives a CSS class derived from the tag name in kebab-case. You can style custom tags by adding classes in your `variables.css`:
```css
.changelog-tag-my-custom-tag {
background-color: #e0f2fe;
color: #0369a1;
}
```
### Using Announcements
URL: https://docula.org/docs/using-announcements/
Description: Guide on creating and configuring announcement banners on the home page using announcement.md file
# Home Page Announcements
You can display an announcement banner on your home page by creating an `announcement.md` file in your site directory. This is useful for highlighting important updates, new releases, or any time-sensitive information.
## Usage
Create an `announcement.md` file in your site folder:
```
site
├───announcement.md
├───docs
├───logo.svg
├───favicon.ico
└───docula.config.mjs
```
Add your announcement content using markdown:
```md
**New Release:** Version 2.0 is now available! Check out the [release notes](/releases) for details.
```
The announcement will automatically appear on the home page above the "Documentation" button, styled as an alert box with a colored left border.
## Styling
The announcement uses your theme's CSS variables and displays with:
- A subtle background using `--sidebar-background`
- A prominent left border using `--color-secondary`
- Links styled with `--color-primary`
You can customize the appearance by overriding the `.announcement` class in your `variables.css`:
```css
.announcement {
background-color: #fff3cd;
border-left-color: #ffc107;
}
```
## Removing the Announcement
Simply delete the `announcement.md` file when you no longer need the announcement. The home page will automatically return to its normal layout.
### Header Links
URL: https://docula.org/docs/header-links/
Description: Guide for configuring custom links in the Docula site header navigation to link to external resources.
# Header Links
Docula supports adding custom links to the site header navigation. This is useful for linking to external resources like blogs, support pages, community forums, or any other URL you want easily accessible from every page.
## Configuration
Add the `headerLinks` option to your `docula.config.ts`:
```typescript
import type { DoculaOptions } from 'docula';
export const options: Partial = {
siteTitle: 'My Project',
headerLinks: [
{ label: 'Blog', url: 'https://blog.example.com' },
{ label: 'Support', url: 'https://support.example.com' },
],
};
```
### Options
| Property | Type | Required | Default | Description |
|----------|------|----------|---------|-------------|
| `label` | `string` | Yes | - | Text displayed for the link |
| `url` | `string` | Yes | - | URL the link points to |
| `icon` | `string` | No | External link icon | Inline SVG string for a custom icon |
## How It Works
1. When `headerLinks` is configured, the links are rendered in the site header navigation after the built-in links (Documentation, API Reference, Changelog).
2. Links appear in both the desktop navigation bar and the mobile sidebar menu.
3. Each link opens in a new tab (`target="_blank"`) with `rel="noopener noreferrer"` for security.
### Custom Icons
By default each header link uses an external link icon. To override it, pass an inline SVG string as the `icon` property. For best results use 16x16 icons with `stroke="currentColor"` so they match the theme.
```typescript
headerLinks: [
{
label: 'Star',
url: 'https://github.com/your-org/your-repo',
icon: 'your svg code goes here',
},
{ label: 'Blog', url: 'https://blog.example.com' },
],
```
Links without an `icon` property will use the default external link icon automatically.
### Partial Templates
URL: https://docula.org/docs/partial-templates/
Description: Learn how to override individual template files in Docula without replacing the entire built-in template, enabling targeted customization of specific components.
# Partial Template Overrides
Docula lets you override individual template files from a built-in template without replacing the entire template. This is useful when you want to customize specific parts of a template (such as the footer, sidebar, or header) while keeping the rest of the default template intact.
## How It Works
Place your override files in a `templates/{templateName}/` directory inside your site folder. The directory structure mirrors the built-in template. Any file you include will replace its corresponding file in the built-in template during the build.
For example, if you are using the `modern` template and want to customize the footer:
```
site/
templates/
modern/
includes/
footer.hbs # overrides the built-in modern/includes/footer.hbs
docs/
index.md
docula.config.ts
```
## Overridable Files
You can override any file in the built-in template, including:
**Top-level templates:**
- `home.hbs` — Landing page
- `docs.hbs` — Documentation page
- `api.hbs` — API reference page
- `changelog.hbs` — Changelog listing page
- `changelog-entry.hbs` — Individual changelog entry page
**Includes (partials):**
- `includes/header.hbs` — Page header/meta tags
- `includes/header-bar.hbs` — Sticky header navigation bar
- `includes/footer.hbs` — Page footer
- `includes/sidebar.hbs` — Navigation sidebar
- `includes/doc.hbs` — Document content wrapper
- `includes/hero.hbs` — Hero section
- `includes/home.hbs` — Home page content
- `includes/scripts.hbs` — Page scripts
- `includes/theme-toggle.hbs` — Light/dark theme toggle
**Assets:**
- `css/` — Stylesheet files
- `js/` — JavaScript files
The available includes vary by template. Check the `templates/` directory in the [Docula repository](https://github.com/jaredwray/docula) for the complete list of files in each template.
## Example: Custom Footer
1. Create the override directory structure:
```bash
mkdir -p site/templates/modern/includes
```
2. Create your custom footer at `site/templates/modern/includes/footer.hbs`:
```handlebars
```
3. Build your site as usual:
```bash
npx docula build
```
During the build, Docula will log which files are being overridden:
```
▶ Applying template overrides...
ℹ Template override: includes/footer.hbs
```
## Notes
- **Built-in templates only** — Partial overrides work with the `template` option (e.g., `modern`, `classic`). If you use `templatePath` to provide a fully custom template, overrides are not applied since you already control the entire template.
- **Cache directory** — Docula merges overrides into a `.cache/templates/{templateName}/` directory inside your site folder. This directory is automatically managed and only rebuilt when override files change. Use `--clean` to remove it along with the output directory.
- **Automatic .gitignore** — When the `.cache` directory is first created, Docula automatically adds `.cache` to your site folder's `.gitignore` (creating the file if needed). Set `autoUpdateIgnores: false` in your config to disable this behavior.
- **Any file can be overridden** — The override directory structure mirrors the built-in template exactly. Any file you place in the override directory replaces the corresponding file from the built-in template.
### Custom Scripts
URL: https://docula.org/docs/custom-scripts/
Description: Learn how to inject custom scripts like Google Tag Manager and analytics into Docula documentation sites using partial template overrides.
# Adding Custom Scripts
Docula lets you inject custom scripts — such as Google Tag Manager, analytics, or any third-party snippet — using [partial template overrides](/docs/partial-templates). No extra configuration is needed; just create the right override file and add your code.
## Scripts at End of Body
Override `includes/scripts.hbs` to add scripts that load at the end of every page. This is the recommended placement for analytics and tracking snippets.
Create the override file:
```bash
mkdir -p site/templates/modern/includes
```
Then create `site/templates/modern/includes/scripts.hbs`:
```handlebars
```
> [!NOTE]
> When you override `scripts.hbs`, it **replaces** the built-in file entirely. If you still need the default scripts (theme toggle, syntax highlighting, etc.), copy the contents of the original `templates/modern/includes/scripts.hbs` from the [Docula repository](https://github.com/jaredwray/docula) and add your custom code alongside it.
## Scripts in the Head
Override `includes/header.hbs` to add scripts or meta tags inside the `` element. This is useful for snippets that must load before the page renders.
Create `site/templates/modern/includes/header.hbs` with the original header content plus your additions:
```handlebars
```
## Hosting Scripts Locally
If you prefer to self-host script files, place them in the `public/` folder and reference them from your template overrides:
```
site/
public/
js/
analytics.js
templates/
modern/
includes/
scripts.hbs
```
Then in your `scripts.hbs` override:
```handlebars
```
Files in `site/public/` are copied to the root of the build output, so `/js/analytics.js` will be available at that path on your site.
## Notes
- This uses the [partial template override](/docs/partial-templates) system. Overrides only apply to built-in templates (`modern`, `classic`). If you use `templatePath` for a fully custom template, add scripts directly in your template files.
- If you are using the `classic` template, replace `modern` with `classic` in the directory paths above.
### GitHub Integration
URL: https://docula.org/docs/github-integration/
Description: Guide to connecting Docula to GitHub repositories to display contributors and releases on your documentation site.
# GitHub Integration
Docula can connect to a GitHub repository to display contributors and releases on your site. This integration is **optional** — if no `githubPath` is configured, the build skips all GitHub API calls and the GitHub-related UI elements are hidden.
## Enabling GitHub Integration
Set the `githubPath` option in your config file to your repository's `owner/repo` path:
```typescript
export const options = {
githubPath: 'your-username/your-repo',
// ...other options
};
```
When `githubPath` is set, Docula fetches:
- **Contributors** — displayed as an avatar facepile on the home page
- **Releases** — shown as recent release cards on the home page
A "View source on GitHub" corner link also appears on every page.
## Building Without GitHub
If you omit `githubPath` or leave it as an empty string, the build works normally without any GitHub features:
- No GitHub API requests are made
- The contributor and release sections are not rendered
- The GitHub corner link is hidden
- Changelog pages still work with file-based entries from `site/changelog/`
This is useful for projects not hosted on GitHub, internal documentation, or when you want faster builds without network calls.
## Release Changelog
When `githubPath` is configured, Docula can merge GitHub releases into your changelog. This is controlled by the `enableReleaseChangelog` option (enabled by default).
```typescript
export const options = {
githubPath: 'your-username/your-repo',
enableReleaseChangelog: true, // default
};
```
Release entries appear alongside any file-based changelog entries in `site/changelog/`. To disable this, set `enableReleaseChangelog: false`.
See [Changelog](/docs/changelog) for more details on changelog configuration.
## Rate Limits
GitHub's public API allows 60 requests per hour without authentication. For higher limits (5,000/hour), set a `GITHUB_TOKEN` environment variable.
See [GitHub Token](/docs/github-token) for setup instructions.
### GitHub Token
URL: https://docula.org/docs/github-token/
Description: Guide for configuring GitHub tokens in Docula to authenticate with the GitHub API, increase rate limits, and access private repositories.
Docula fetches contributor and release data from the GitHub API during builds. A token is optional but recommended to avoid rate limits and to support private repositories.
## Why Use a Token
Without a token, GitHub's API limits requests to **60 per hour** per IP address. With a token, the limit increases to **5,000 per hour**. If you build frequently or your site has many releases and contributors, you will likely hit the unauthenticated limit.
A token is also **required** to access private repositories.
## Setting the Token
Docula reads the `GITHUB_TOKEN` environment variable. You can set it in several ways:
### Inline with the CLI
```bash
GITHUB_TOKEN=ghp_yourtoken npx docula build
```
### Export in your shell
```bash
export GITHUB_TOKEN=ghp_yourtoken
npx docula build
```
### Using a `.env` file
Add the token to a `.env` file in your project root and load it with a tool like `dotenv`:
```
GITHUB_TOKEN=ghp_yourtoken
```
Make sure `.env` is listed in your `.gitignore` so the token is never committed.
### GitHub Actions
In CI, use the built-in `GITHUB_TOKEN` secret or a personal access token:
```yaml
- name: Build docs
run: npx docula build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
## Required Permissions
Docula only reads public repository data (contributors and releases). A **fine-grained personal access token** with read-only access to the target repository is sufficient. No write permissions are needed.
To create a token:
1. Go to [GitHub Settings > Developer settings > Personal access tokens](https://github.com/settings/tokens)
2. Generate a new token with **read-only** repository access
3. Copy the token and set it as `GITHUB_TOKEN`
## What Happens Without a Token
Docula still works without a token. Contributors and releases are fetched from the public API. If the rate limit is exceeded, these sections will be empty in the build output but the rest of the site builds normally.
### API Reference
URL: https://docula.org/docs/api-reference/
Description: Guide to generating and configuring interactive API Reference pages from OpenAPI/Swagger specifications in Docula with support for multiple specs, authentication, and auto-detection.
# API Reference
Docula can generate an API Reference page from an OpenAPI (Swagger) specification. The spec is parsed at build time and rendered as a native, interactive API reference (inspired by [Scalar](https://github.com/scalar/scalar)) with grouped endpoints, method badges, schema tables, code examples, and search — all with no external dependencies. The page is available at `/api`.
## Auto-Detection
Docula automatically detects OpenAPI specs in your site directory — no configuration needed.
**Single spec** — place a `swagger.json` at `api/swagger.json`:
```
site
├───api
│ └───swagger.json
├───docs
├───logo.svg
├───favicon.ico
└───docula.config.mjs
```
**Multiple specs** — place each spec in its own subdirectory under `api/`:
```
site
├───api
│ ├───petstore
│ │ └───swagger.json
│ └───users
│ └───swagger.json
├───docs
└───docula.config.mjs
```
When multiple subdirectories are detected, each spec becomes a section on the API Reference page. The directory name is used as the display name (e.g., `petstore` becomes "Petstore").
## Explicit Configuration
Set the `openApiUrl` option to point to an OpenAPI spec. For a single spec, pass a string (local path or remote URL):
```js
export const options = {
openApiUrl: '/api/swagger.json',
// or a remote URL:
// openApiUrl: 'https://petstore.swagger.io/v2/swagger.json',
};
```
## Multiple API Specs
For multiple specs, pass an array to `openApiUrl`. All specs render as sections on a single `/api/` page, each with its own title, endpoints, and sidebar grouping:
```typescript
import type { DoculaOptions } from 'docula';
export const options: Partial = {
openApiUrl: [
{ name: 'Petstore API', url: 'petstore/swagger.json', order: 1 },
{ name: 'Users API', url: 'users/swagger.json', order: 2 },
],
};
```
Each entry has the following fields:
| Field | Type | Description |
|-------|------|-------------|
| `name` | `string` | Display name shown as the section heading |
| `url` | `string` | Path to the spec file relative to the api directory, or a remote URL |
| `order` | `number?` | Sort order — lower numbers appear first. Specs without `order` appear last. |
## Priority
When multiple configuration methods are used, Docula applies them in this order (first match wins):
1. `openApiUrl` (array) — explicit multi-spec configuration
2. `openApiUrl` (string) — explicit single-spec configuration
3. Auto-detection — `api/swagger.json` or `api/*/swagger.json`
## Spec Requirements
The file must be a valid OpenAPI 3.x or Swagger 2.0 JSON specification. A minimal example:
```json
{
"openapi": "3.0.0",
"info": {
"title": "My API",
"version": "1.0.0"
},
"paths": {}
}
```
## Authentication
Docula automatically parses `securitySchemes` from the OpenAPI spec's `components` section and displays them in an authorization panel on the API Reference page. Supported scheme types:
- **API Key** — sent as a header, query parameter, or cookie
- **HTTP Bearer** — sent as an `Authorization: Bearer ` header
- **OAuth2** — displays flow details (authorization code, client credentials, implicit, password)
When you use the "Try It" panel to test an endpoint, Docula injects the credentials automatically based on the selected scheme — as a header, query parameter, or cookie.
### Example
Add a `securitySchemes` section to your OpenAPI spec:
```json
{
"components": {
"securitySchemes": {
"ApiKeyAuth": {
"type": "apiKey",
"in": "header",
"name": "x-api-key"
},
"BearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
The authorization dropdown will be populated with these schemes. If no `securitySchemes` are defined, the authorization panel is hidden.
### Cookie-Based Authentication
If your spec defines an API Key scheme with `"in": "cookie"` and you have [`cookieAuth`](/docs/cookie-auth) configured, the API Reference page shows whether you are currently logged in. Requests made via "Try It" automatically include the cookie — no manual token entry is needed.
### Cookie Auth
URL: https://docula.org/docs/cookie-auth/
Description: Documentation on implementing cookie-based authentication in Docula with login/logout buttons and credential validation.
# Cookie Auth
Docula supports cookie-based authentication that displays a **Log In** or **Log Out** button in the site header. Authentication state is determined by fetching a configurable URL with credentials included.
This is useful for documentation sites that sit on a different domain from their auth provider, such as cross-domain OAuth setups.
## Configuration
Add the `cookieAuth` option to your `docula.config.ts`:
```typescript
import type { DoculaOptions } from 'docula';
export const options: Partial = {
siteTitle: 'My Project',
cookieAuth: {
loginUrl: '/login',
logoutUrl: '/api/auth/logout',
authCheckUrl: 'https://api.example.com/me',
authCheckUserPath: 'email',
},
};
```
### Options
| Property | Type | Required | Default | Description |
|----------|------|----------|---------|-------------|
| `loginUrl` | `string` | Yes | - | URL to redirect to when "Log In" is clicked |
| `logoutUrl` | `string` | No | - | URL to redirect to on logout. If not set, the page reloads |
| `authCheckUrl` | `string` | No | - | URL to fetch (with `credentials: 'include'`) to determine if the user is logged in. A 2xx response means logged in |
| `authCheckMethod` | `string` | No | `'GET'` | HTTP method to use when fetching `authCheckUrl` |
| `authCheckUserPath` | `string` | No | - | Dot-notation path to extract a display name from the JSON response (e.g. `'email'`, `'user.name'`) |
## How It Works
1. When `cookieAuth` is configured, a **Log In** link and a hidden **Log Out** button are rendered in the site header (both desktop and mobile).
2. On page load, if `authCheckUrl` is set, client-side JavaScript fetches the URL with `credentials: 'include'` so that cookies are sent cross-domain.
3. If the response is 2xx, the user is considered logged in. The "Log In" link is hidden and the "Log Out" button is shown.
4. If the response is not 2xx or the fetch fails, the "Log In" link is shown and the "Log Out" button is hidden.
### Cached Auth State
To avoid a flash of incorrect UI on page load, Docula caches the auth state in `localStorage`. On subsequent page loads, the cached state is applied immediately (before the page body renders) and then refreshed in the background by fetching `authCheckUrl` again. This means:
- First visit: brief delay before auth UI appears (waiting for the fetch)
- Subsequent visits: auth UI appears instantly from cache, then silently updates if the state has changed
### User Display Name
If `authCheckUserPath` is set, Docula extracts a display name from the JSON response using dot-notation path traversal. For example, if the response is:
```json
{
"email": "user@example.com"
}
```
Setting `authCheckUserPath` to `'email'` will display `user@example.com` in the header.
If the path doesn't resolve to a value, no name is displayed.
### Logout Behavior
**With `logoutUrl`**: Clicking "Log Out" redirects to the specified URL. Use this when your auth provider has a dedicated logout endpoint.
**Without `logoutUrl`**: Clicking "Log Out" reloads the page.
## API Reference Integration
When `cookieAuth` is configured and your OpenAPI spec defines an API Key security scheme with `"in": "cookie"`, the [API Reference](/docs/api-reference) page shows a login status indicator in the authorization panel. The selected authorization type and auth state are persisted in `localStorage` so they survive page refreshes. Requests made via the "Try It" panel automatically include cookies, so no manual token entry is needed.
### LLM Files
URL: https://docula.org/docs/llm-files/
Description: Documentation on how Docula generates LLM-focused files for AI model consumption, including configuration options and customization.
# LLM Files
Docula generates two LLM-focused files in the output directory by default:
- `/llms.txt` - a compact index of your docs, API reference, and changelog URLs.
- `/llms-full.txt` - expanded content including markdown bodies for docs/changelog and local OpenAPI spec text.
## What Gets Included
`/llms.txt` includes:
- Site title and description
- A link to `/llms-full.txt`
- Documentation links (absolute URLs)
- API Reference link when API docs are generated
- Changelog landing page and the latest 20 changelog entries
`/llms-full.txt` includes:
- Site title and description
- Full markdown body for each docs page
- Full markdown body for each changelog entry
- Full local OpenAPI spec text when available (for example `site/api/swagger.json`)
If `openApiUrl` points to a remote URL, `/llms-full.txt` includes only the URL reference instead of fetching content over the network.
## Configuration
To disable generation:
```js
export const options = {
enableLlmsTxt: false,
};
```
## Custom Overrides
You can override generated output by providing custom files in your site directory:
- `site/llms.txt`
- `site/llms-full.txt`
If present, Docula copies these files to output as-is.
## Notes
- These files are generated in the output root (`dist/llms.txt` and `dist/llms-full.txt`).
- They are not added to `sitemap.xml`.
### Search
URL: https://docula.org/docs/search/
Description: Documentation for Docula's built-in client-side search feature, including how it works, usage instructions, and configuration options.
# Search
Docula ships with a fast, fully client-side search built into the **modern**
template — no third-party service, API key, or external dependency required.
At build time Docula generates a `search-index.json` file from your
documentation and changelog, and the template renders a keyboard-driven search
modal that queries it in the browser.
## How it works
1. During the build, every documentation page and changelog entry is split into
sections — one record per heading — and written to `search-index.json` in the
output root.
2. Each record keeps the page title, the heading breadcrumb, the section text,
and a deep-link URL (including the `#anchor`) so results jump straight to the
matching heading.
3. The modern template renders a search button in the header and a modal that
loads the index on first open and ranks matches as you type.
## Using search
- Click the **Search** button in the header, press ⌘ K /
Ctrl K, or press / to open the modal.
- Type to filter — results are ranked by where the match occurs (titles rank
above body text) and matched terms are highlighted.
- Use ↑ / ↓ to move between results, ↵ to open
the highlighted result, and esc to close.
## Configuration
Search is enabled by default. Set `enableSearch` to `false` to skip generating
the index and hide the search UI:
```ts
import type { DoculaOptions } from 'docula';
export const options: Partial = {
enableSearch: false,
};
```
When `enableSearch` is `false`, no `search-index.json` is written and the search
button and modal are omitted from the rendered pages.
## What gets indexed
| Content | Indexed |
|---------|---------|
| Documentation pages (`docs/`) | Yes — one record per heading, plus a page-level record |
| Changelog entries | Yes — published entries (drafts are skipped) |
| API reference | No — the API page has its own built-in endpoint filter |
The injected "Table of Contents" section is automatically excluded from the
index so it never shows up as a result.
### Robots & Sitemap
URL: https://docula.org/docs/robots-and-sitemap/
Description: Documentation on how Docula automatically generates robots.txt, sitemap.xml, and feed.xml files for SEO and search engine discovery.
Docula automatically generates a `robots.txt`, `sitemap.xml`, and `feed.xml` in your output directory during every build. No configuration is required.
## robots.txt
The `robots.txt` file tells search engine crawlers which pages they are allowed to access. Docula generates a permissive default at `dist/robots.txt`:
```
User-agent: *
Disallow:
```
This allows all crawlers to index every page on your site.
### Custom Override
To use your own `robots.txt`, place a file at `site/robots.txt`. Docula will copy it to the output directory as-is instead of generating the default.
## sitemap.xml
The `sitemap.xml` file provides search engines with a structured list of all pages on your site, making it easier for crawlers to discover and index your content. Docula generates it at `dist/sitemap.xml`.
### What Gets Included
The sitemap automatically includes URLs for:
- **Home page** — your site root URL
- **RSS feed** — the generated docs feed at `/feed.xml` when documentation pages exist
- **Changelog JSON feeds** — `/changelog.json` and `/changelog-latest.json` when changelog entries exist
- **Documentation pages** — every page in `docs/`, using the full resolved URL path
- **API Reference** — included when `openApiUrl` is configured and the API template exists
- **Changelog** — the changelog landing page plus individual entries for each release
All URLs use the absolute `siteUrl` from your config (e.g., `https://your-site.com/docs/configuration`).
### Example Output
```xml
https://your-site.comhttps://your-site.com/feed.xmlhttps://your-site.com/changelog.jsonhttps://your-site.com/changelog-latest.jsonhttps://your-site.com/docs/https://your-site.com/docs/configurationhttps://your-site.com/apihttps://your-site.com/changeloghttps://your-site.com/changelog/v1.0.0
```
## feed.xml
When your site contains documentation pages, Docula also generates an RSS 2.0 feed at `dist/feed.xml`.
### What Gets Included
- One feed item per generated documentation page
- The document title as the item title
- The canonical documentation URL as the item link and GUID
- A lightweight summary using the document description, or a short markdown excerpt when no description is set
## Output Location
All files are written to the root of your output directory:
```
dist/
changelog.json
changelog-latest.json
feed.xml
robots.txt
sitemap.xml
```
### Caching
URL: https://docula.org/docs/caching/
Description: Documentation on how Docula's caching system works, what gets cached, and how to manage cache behavior.
# Caching
Docula uses a `.cache` directory inside your site folder to store intermediate build artifacts. This improves rebuild performance by avoiding redundant work when nothing has changed.
## What is cached
### Template overrides
When you use [partial template overrides](/docs/partial-templates), Docula merges your override files with the built-in template into `.cache/templates/{templateName}/`. On subsequent builds, Docula compares content hashes (stored in `.manifest.json`) and incrementally updates only the files that have been added, changed, or removed.
```
site/
.cache/
templates/
modern/ # merged template (built-in + your overrides)
home.hbs
docs.hbs
includes/
footer.hbs # your custom override
sidebar.hbs # from the built-in template
...
```
### GitHub API data
When your site is configured with a [GitHub integration](/docs/github-integration), Docula caches the API responses for releases and contributors to `.cache/github/github-data.json`. On subsequent builds, Docula checks the file's age against the configured TTL and skips the API call if the cache is still fresh.
```
site/
.cache/
github/
github-data.json # cached releases and contributors
```
By default the cache TTL is **3600 seconds (1 hour)**. You can change this in your config:
```typescript
import type { DoculaOptions } from 'docula';
export const options: Partial = {
cache: {
github: {
ttl: 7200, // 2 hours
},
},
};
```
Set `ttl` to `0` to disable GitHub caching entirely and always fetch fresh data from the API.
### Build manifest (differential builds)
Docula tracks content hashes for all source files (documents, changelog entries, assets, config, and templates) in a build manifest. On subsequent builds, only changed content is re-processed:
- **Documents and changelog entries** — Parsed markdown objects are cached to disk. Unchanged files are loaded from cache instead of being re-parsed through the Writr renderer.
- **Assets** — Unchanged assets (favicon, logo, CSS, JS, public folder files) are not re-copied to the output directory.
- **Full build skip** — If nothing has changed and the output directory exists, the build returns immediately. This is especially useful in `--watch` mode.
```
site/
.cache/
build/
manifest.json # content hashes for all source files
documents.json # cached parsed document objects
changelog.json # cached parsed changelog entry objects
```
A config change (e.g., changing `siteTitle`) invalidates the entire manifest and forces a full rebuild. A template change re-renders all pages but reuses cached parsed documents.
## Clearing the cache
Use the `--clean` flag to remove **all** caching along with the output directory:
```bash
npx docula build --clean
```
This deletes both the output directory (e.g., `dist/`) and the entire `.cache/` directory (including template and GitHub caches), forcing a full rebuild on the next run.
You can also manually delete the `.cache` directory at any time. Docula will recreate it as needed.
## Git and the cache
The `.cache` directory contains only generated files and should not be committed to version control. By default, Docula automatically adds `.cache` to your site folder's `.gitignore` the first time the cache is created. If the `.gitignore` file does not exist, Docula creates it.
If you prefer to manage your `.gitignore` manually, you can disable this behavior in your config:
```typescript
import type { DoculaOptions } from 'docula';
export const options: Partial = {
autoUpdateIgnores: false,
};
```
When disabled, you should add `.cache` to your `.gitignore` yourself:
```
# .gitignore
.cache
```
## Configuration reference
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `autoUpdateIgnores` | `boolean` | `true` | Automatically add `.cache` to the site folder's `.gitignore` on first cache creation |
| `cache.github.ttl` | `number` | `3600` | Time-to-live in seconds for cached GitHub API data. Set to `0` to disable. |
### Helper Utilities
URL: https://docula.org/docs/helper-utilities/
Description: Guide to using Writr helper utilities in Docula for markdown file operations, frontmatter management, and HTML rendering.
# Helpers
Docula provides powerful helper utilities through its integration with [Writr](https://writr.org). For all markdown operations including reading files, manipulating content, managing frontmatter, and rendering, you should use the `Writr` class that's exported from Docula.
**Instead of custom helper functions, use Writr for:**
- Loading and saving markdown files
- Getting and setting frontmatter (metadata)
- Rendering markdown to HTML
- Working with markdown content programmatically
# Working with Markdown using Writr
Docula exports [Writr](https://writr.org) for powerful markdown operations including loading files, rendering, and managing frontmatter. Writr provides a simple API for working with markdown content.
## Creating and Loading Markdown
```js
import { Writr } from 'docula';
// Create a new instance with markdown content
const writr = new Writr('# Hello World\n\nThis is my content');
// Or load from a file
const writr = new Writr();
await writr.loadFromFile('./README.md');
// Synchronous version
writr.loadFromFileSync('./README.md');
```
## Getting and Setting Front Matter
Front matter is metadata at the top of markdown files in YAML format. Writr makes it easy to read and modify:
```js
import { Writr } from 'docula';
const writr = new Writr();
await writr.loadFromFile('./docs/guide.md');
// Get the entire front matter object
const frontMatter = writr.frontMatter;
console.log(frontMatter.title); // 'My Guide'
// Get a specific front matter value
const title = writr.getFrontMatterValue('title');
const order = writr.getFrontMatterValue('order');
// Set front matter
writr.frontMatter = {
title: 'Updated Guide',
order: 1,
author: 'John Doe'
};
// Save the changes back to the file
await writr.saveToFile('./docs/guide.md');
```
## Accessing Markdown Content
```js
// Get the full content (front matter + markdown)
const fullContent = writr.content;
// Get just the markdown body (without front matter)
const markdown = writr.body;
// or use the alias
const markdown = writr.markdown;
// Get the raw front matter string (including delimiters)
const rawFrontMatter = writr.frontMatterRaw;
// Set new content
writr.content = '---\ntitle: New Title\n---\n# New Content';
```
## Rendering Markdown to HTML
```js
// Render to HTML
const html = await writr.render();
// Synchronous rendering
const html = writr.renderSync();
// Render with options
const html = await writr.render({
emoji: true, // Enable emoji support (default: true)
toc: true, // Generate table of contents (default: true)
highlight: true, // Code syntax highlighting (default: true)
gfm: true, // GitHub Flavored Markdown (default: true)
math: true, // Math support (default: true)
mdx: true // MDX support (default: true)
});
// Render directly to a file
await writr.renderToFile('./output.html');
```
### Binary Download
URL: https://docula.org/docs/binary-download/
Description: Guide to downloading and using Docula standalone binaries for Linux, macOS, and Windows without requiring Node.js installation.
# Binary Download
Docula publishes standalone binaries — a single executable file containing both Node.js and docula itself — for Linux, macOS (x64 and arm64), and Windows. Binaries are produced by the [`build-binaries` GitHub Actions workflow](https://github.com/jaredwray/docula/actions/workflows/build-binaries.yaml) and attached to each release.
Use a binary when you want to run docula without installing Node.js or pnpm/npm — for example, on a minimal CI image or a machine where you can't add a global npm dependency.
## Download
Grab the artifact matching your platform from the [latest release](https://github.com/jaredwray/docula/releases/latest):
| Platform | Artifact |
|----------|----------|
| Linux x64 | `docula-linux-x64` |
| macOS arm64 (Apple Silicon) | `docula-macos-arm64` |
| Windows x64 | `docula-windows-x64.exe` |
On macOS and Linux, mark the file as executable after downloading:
```bash
chmod +x docula-linux-x64
./docula-linux-x64 version
```
## JSON Config Only
The standalone binary loads configuration from **`docula.config.json`** only. TypeScript (`.ts`) and ESM JavaScript (`.mjs`) config files are not supported when running the binary; if one is present and no `docula.config.json` exists, the binary exits with an error explaining the limitation.
This restriction is intentional. Node.js's single-executable-application runtime can't dynamic-import file URLs, which is how `.ts` and `.mjs` configs are loaded under regular Node. Rather than ship a fragile transpiler inside the binary, the SEA path only reads JSON — which is data, not code.
The practical consequence: **no lifecycle hooks** (`onPrepare`, etc.) in the binary. JSON can't carry functions. If you need `onPrepare`, run docula from Node.js with a `.ts` or `.mjs` config instead.
### Example
`docula.config.json` at the root of your site directory:
```json
{
"githubPath": "your-username/your-repo",
"siteTitle": "My Project",
"siteDescription": "Project description",
"siteUrl": "https://your-site.com",
"themeMode": "light",
"template": "modern"
}
```
The top-level object is the options bag — the same shape as the `options` export in a `.ts`/`.mjs` config. Every field documented on the [Configuration page](./configuration) is supported, except for the function fields like `onPrepare`.
Then build:
```bash
./docula-linux-x64 build -s ./site -o ./dist
```
## Using JSON Outside the Binary
`docula.config.json` is supported under regular Node too. It's checked after `docula.config.ts` and `docula.config.mjs`, so if you have both a `.ts` and a `.json` file in the same site directory, the `.ts` config wins.
This means you can author one `docula.config.json` and use it from both:
- The standalone binary (only `.json` is read)
- A Node-installed docula (`.ts`/`.mjs` take priority if present, otherwise `.json` is used)
## When to Use Which
| Scenario | Recommended config |
|----------|-------------------|
| Standalone binary | `docula.config.json` (required) |
| Node.js project with type checking | `docula.config.ts` |
| Node.js project without TypeScript | `docula.config.mjs` |
| Plain data, no hooks, run anywhere | `docula.config.json` |
### Contributing
URL: https://docula.org/docs/project-guidelines/contributing/
Description: Guidelines for contributing to the Docula repository, including pull request process, code standards, and community expectations.
# Contributing
When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change.
Please note we have a [Code of Conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.
We release new versions of this project (maintenance/features) on a monthly cadence so please be aware that some items will not get released right away.
# Pull Request Process
You can contribute changes to this repo by opening a pull request:
1) After forking this repository to your Git account, make the proposed changes on your forked branch.
2) Run tests and linting locally.
- Ensure you have Node.js >= 20 and pnpm installed.
- Run `pnpm install`.
- Run `pnpm test` (runs Biome linting and Vitest with coverage — 100% code coverage is required).
3) Commit your changes and push them to your forked repository.
4) Navigate to the main `Docula` repository and select the *Pull Requests* tab.
5) Click the *New pull request* button, then select the option "Compare across forks"
6) Leave the base branch set to main. Set the compare branch to your forked branch, and open the pull request.
7) Once your pull request is created, ensure that all checks have passed and that your branch has no conflicts with the base branch. If there are any issues, resolve these changes in your local repository, and then commit and push them to git.
8) Similarly, respond to any reviewer comments or requests for changes by making edits to your local repository and pushing them to Git.
9) Once the pull request has been reviewed, those with write access to the branch will be able to merge your changes into the `Docula` repository.
If you need more information on the steps to create a pull request, you can find a detailed walkthrough in the [Github documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)
# Code of Conduct
Please refer to our [Code of Conduct](https://github.com/jaredwray/docula/blob/main/CODE_OF_CONDUCT.md) readme for how to contribute to this open source project and work within the community.
### Code of Conduct
URL: https://docula.org/docs/project-guidelines/code-of-conduct/
Description: The Contributor Covenant Code of Conduct establishes community standards for respectful participation, defines unacceptable behavior, and outlines enforcement procedures for community violations.
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
me@jaredwray.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
### Security
URL: https://docula.org/docs/project-guidelines/security/
Description: Security policy and practices for Docula, including vulnerability reporting procedures, continuous security scanning layers, and npm package provenance verification.
# Security Policy
## Reporting a Vulnerability
To report a security vulnerability, please send an email to me@jaredwray.com. Once the report has been validated, we will open a [Github Security Advisory](https://docs.github.com/en/code-security/repository-security-advisories/about-github-security-advisories-for-repositories), if necessary.
## Continuous Security Scanning
We take the security of Docula seriously and have multiple layers of automated scanning in place to detect vulnerabilities as early as possible:
- **Aikido Security**: We use [Aikido](https://www.aikido.dev/) to continuously scan our codebase, dependencies, and infrastructure for vulnerabilities. You can review our public audit report by clicking the badge above.
- **Pull Request Scans**: Every pull request opened against the `main` branch is automatically scanned for security issues before it can be merged. This ensures that no new code lands in `main` without first being reviewed for known vulnerabilities, insecure dependencies, and common security pitfalls.
- **CodeQL Analysis**: We run [GitHub CodeQL](https://codeql.github.com/) static analysis on pushes to `main` and on every pull request targeting `main` to identify potential security issues in our source code.
## npm Package Provenance
Docula is published to [npmjs.org](https://www.npmjs.com/package/docula) with [npm package provenance](https://docs.npmjs.com/generating-provenance-statements) enabled via GitHub Actions. Provenance statements provide cryptographically verifiable links between published packages and the source code and build process that produced them.
This means that when you install Docula from npm, you can verify:
- The exact source repository and commit the package was built from.
- The GitHub Actions workflow that built and published the package.
- That the package has not been tampered with between build and publish.
Our release workflow (`.github/workflows/release.yaml`) uses the `--provenance` flag when publishing, and the GitHub Actions runner is granted the `id-token: write` permission required to generate the signed provenance statement. You can verify the provenance of any published version directly on the [Docula npm page](https://www.npmjs.com/package/docula) or via `npm audit signatures`.
## API Reference
URL: https://docula.org/api
- Not available.
## Changelog
URL: https://docula.org/changelog
### v2.2.0
URL: https://docula.org/changelog/v2-2-0
Date: July 8, 2026
Tag: Release
## docula@2.2.0 — 2026-07-08
Google Tag Manager environment support, plus a nav-highlight fix and release/deploy CI fixes.
### Features
- add support for Google Tag Manager environments (70a3fac, #451)
```ts
// docula.config.ts — target a specific GTM environment (staging, QA, …)
export const options: Partial = {
googleTagManager: 'GTM-XXXXXX',
googleTagManagerAuth: 'abc123', // → gtm_auth
googleTagManagerEnv: 'env-3', // → gtm_preview
};
```
### Bug Fixes
- documentation nav link staying highlighted when embedded under a base path (2952de4, #450)
### Internal
- ci: pass Cloudflare accountId to wrangler pages deploy (310aef9, #449)
- ci: give release binaries unique asset filenames (ea462c7, #448)
- ci: approve sharp and workerd build scripts for wrangler deploy (dc08718, #447)
### Contributors
- @jaredwray (5)
- @Terryda (3)
### Full List of Changes
- Fix deploy: approve sharp and workerd build scripts for wrangler by @jaredwray in #447
- fix(ci): give release binaries unique asset filenames by @jaredwray in #448
- fix: pass Cloudflare accountId to wrangler pages deploy by @jaredwray in #449
- Fix Documentation nav link staying highlighted when embedded under a base path by @jaredwray in #450
- feat: add support for google tag manager environments by @Terryda in #451 (first-time contributor)
**Full diff:** [https://github.com/jaredwray/docula/compare/v2.1.0...v2.2.0](https://github.com/jaredwray/docula/compare/v2.1.0...v2.2.0)
### v2.1.0
URL: https://docula.org/changelog/v2-1-0
Date: June 19, 2026
Tag: Release
## docula@2.1.0 — 2026-06-19
Client-side search (⌘K), SSRF hardening, SEA binary fixes, and a dependency refresh.
### Features
- add built-in client-side search (⌘K) to the modern template (a3d3c1c, #445)
```jsonc
// docula.config.json — search is on by default for the modern template;
// build emits search-index.json and renders the ⌘K / Ctrl-K modal.
{ "enableSearch": true } // set to false to disable
```
### Bug Fixes
- search: robust HTML stripping and Enter-key race in client search (5d4392c, #445)
- search: match lenient script/style end tags; enable search for changelog-only sites (d6ac6e9, #445)
- api: mitigate SSRF in remote OpenAPI spec fetch (1ca11c5, #431)
- safe-fetch: handle both lookup signatures; destroy dispatcher inline on redirect (396618c, #431)
- binary: support docula.config.json; SEA mode loads JSON only (083ed53, #428)
- binary: load .mjs configs without dynamic import() in SEA mode (6fcecc5, #428)
- binary: use createRequire instead of new Function; preserve aliases and scope (10edf8b, #428)
- binary: dedupe require() calls and verify multi-line import handling (1d2e758, #428)
- binary: build SEA as ESM to enable dynamic import of file URLs (eef80ee, #426)
- binary: drop githubPath from smoke fixture to skip GH API call (eabbada, #429)
- binary: skip site config loading for version command (077f4cd, #425)
- release: grant id-token: write for npm OIDC trusted publishing (7ae3269, #424)
### Documentation
- security: add Aikido badge and expand SECURITY.md (6352d7e, #432)
- security: qualify PR scan coverage to main branch (7b55ddd, #432)
- readme: move Aikido badge into dedicated Security section (c2eabf7, #433)
- security: switch vulnerability reports to private email only (4690e60, #433)
- readme: drop vulnerability reporting line from summary (4cb858f, #433)
- add Binary Download page documenting JSON-only SEA config (985cc1f, #428)
- add rel="noopener noreferrer" to Aikido badge link (1f6d5a6, #427)
- add Aikido security audit report badge to README (b5d2d2d, #427)
- re-add Aikido Security Audit badge (1d96c29, #435)
### Internal
- upgrade hashery to 3 — no public API change; Node ≥22.18 already satisfied (dfd72a1, #443)
- upgrade undici to 8; bump engines.node to ^22.19.0 (0f38083, #442)
- upgrade ipaddr.js (1721a15, #441)
- upgrade ecto (5eae9fd, #440)
- upgrade @cacheable/net (9e0e5b0, #439)
- upgrade AI SDK dependencies (211bb19, #438)
- upgrade GitHub Actions — checkout v7, codecov v7 (e8e0d3b, #437)
- upgrade TypeScript and build tooling (b9cc26d, #436)
- upgrade code quality dependencies — biome, vitest (5880166, #435)
- test: rebuild test harness for isolation, determinism, and 100% coverage (bcd6d9c, #444)
- test: harden harness per review — no failure-hiding, no env leaks, safer cloneSite (4f72069, #444)
- test: address Codex review findings on the migrated tests (b78007a, #444)
- ci(binary): drop macOS x64 build, keep only macos-latest arm64 (33619a6, #430)
- ci(binary): replace deprecated macos-13 runner with macos-15-intel (c8308d2, #430)
- ci(release): drop NPM_TOKEN fallback now that OIDC publishes (21607ac, #424)
### Contributors
- @jaredwray (21)
### Full List of Changes
- fix(release): grant id-token: write so pnpm OIDC publish succeeds by @jaredwray in #424
- fix(binary): skip site config loading for `version` command by @jaredwray in #425
- fix(binary): build SEA as ESM to enable dynamic import of file URLs by @jaredwray in #426
- docs: add Aikido security audit report badge to README by @jaredwray in #427
- fix(binary): load .mjs configs without dynamic import() in SEA mode by @jaredwray in #428
- fix(binary): drop githubPath from smoke fixture to skip GH API call by @jaredwray in #429
- ci(binary): drop macOS x64 build, keep only macos-latest (arm64) by @jaredwray in #430
- fix(api): mitigate SSRF in remote OpenAPI spec fetch by @jaredwray in #431
- docs(security): add Aikido badge and expand SECURITY.md by @jaredwray in #432
- docs(readme): move Aikido badge into dedicated Security section by @jaredwray in #433
- root - chore: upgrade code quality dependencies by @jaredwray in #435
- root - chore: upgrade TypeScript and build tooling by @jaredwray in #436
- root - chore: upgrade GitHub Actions (breaking) by @jaredwray in #437
- root - chore: upgrade AI SDK dependencies by @jaredwray in #438
- root - chore: upgrade @cacheable/net by @jaredwray in #439
- root - chore: upgrade ecto by @jaredwray in #440
- root - chore: upgrade ipaddr.js by @jaredwray in #441
- root - chore: upgrade undici to 8 (breaking) by @jaredwray in #442
- root - chore: upgrade hashery to 3 (breaking) by @jaredwray in #443
- test: rebuild test harness for isolation, determinism, and 100% coverage by @jaredwray in #444
- feat: built-in client-side search (⌘K) for the modern template by @jaredwray in #445
**Full diff:** [https://github.com/jaredwray/docula/compare/v2.0.0...v2.1.0](https://github.com/jaredwray/docula/compare/v2.0.0...v2.1.0)
### v2.0.0
URL: https://docula.org/changelog/v2-0-0
Date: May 19, 2026
Tag: Release
## docula@2.0.0 — 2026-05-19
Node 20 → 22 minimum, pnpm 11 supply-chain hardening, AI SDK + tooling refresh, and favicon auto-generation.
### ⚠ BREAKING CHANGES
- Drop Node 20 support; minimum engines are now `^22.18.0 || >=24.0.0` (3420df2, #416)
Migration: upgrade to Node 22 LTS or Node 24+. pnpm is now managed via corepack; run `corepack enable` and pnpm 11.1.3 is pinned via `packageManager`.
### Features
- auto-generate favicon from logo when `favicon.ico` is missing (ba2f40c, #414)
```text
site/
favicon.ico ← used as-is if present
logo.svg ← else used as favicon
logo.png ← else used as favicon
← else no emitted
```
### Bug Fixes
- skip lightbox and zoom-in cursor for images wrapped in links (84667c3, #411)
- simplify sidebar — all sections open by default, user preference still persisted in localStorage (25f86e8, #412)
- ai: fall back to env vars and handle empty model strings (6630c35, #413)
- ai: use valid OpenAI model name `gpt-4o-mini` (drop `-latest` suffix) (fc74979, #413)
### Internal
- upgrade to pnpm 11 with defense-in-depth supply chain controls — 7-day minimumReleaseAge, strict mode, blockExoticSubdeps, allowBuilds allow-list (3420df2, 8af7fe0, #416)
- migrate binary build from hand-rolled SEA pipeline to tsdown's `exe` option; switch SEA detection to `node:sea.isSea()` (45b48c5, #423)
- upgrade GitHub Actions to latest majors — checkout v6, setup-node v6, upload-artifact v7, codecov v6, codeql v4, wrangler v4 (81dd0d1, #419)
- upgrade Vercel AI SDK dependencies — `ai` 6.0.178; anthropic, google, openai providers (e89fbf4, 670e0d7, #420)
- upgrade code quality dependencies — biome 2.4.15, vitest 4.1.6, playwright 1.60.0 (99d436e, #417)
- upgrade TypeScript 6.0.3 and tsdown 0.22.0; align `@types/node` with `.nvmrc` (42afae6, 27eedd9, #418)
- upgrade ecto 4.8.5 (dedupes writr in tree) (d209639, #421)
- upgrade jiti 2.7.0 (b50bfe3, #422)
- refactor builder: use `path.join` for favicon and logo.png paths (cec4bcc, #414)
### Contributors
- @jaredwray (12)
### Full List of Changes
- fix: zoom-in cursor for images inside links by @jaredwray in #411
- fix: simplify sidebar section default open state logic by @jaredwray in #412
- Auto-generate favicon from logo when favicon.ico is missing by @jaredwray in #414
- Update default OpenAI model from gpt-4o-mini-latest to gpt-4o-mini by @jaredwray in #413
- chore: upgrade to pnpm 11 with defense-in-depth supply chain controls by @jaredwray in #416
- root - chore: upgrade code quality dependencies by @jaredwray in #417
- root - chore: upgrade TypeScript and build tooling by @jaredwray in #418
- root - chore: upgrade GitHub Actions (breaking) by @jaredwray in #419
- root - chore: upgrade Vercel AI SDK dependencies by @jaredwray in #420
- root - chore: upgrade ecto by @jaredwray in #421
- root - chore: upgrade jiti by @jaredwray in #422
- build: migrate binary build to tsdown exe option by @jaredwray in #423
**Full diff:** [https://github.com/jaredwray/docula/compare/v1.14.0...v2.0.0](https://github.com/jaredwray/docula/compare/v1.14.0...v2.0.0)
### v1.14.0
URL: https://docula.org/changelog/v1-14-0
Date: April 18, 2026
Tag: Release
## What's Changed
* feat: add onAutoReadme hook to transform resolved README content by @jaredwray in [https://github.com/jaredwray/docula/pull/402](https://github.com/jaredwray/docula/pull/402)
* chore: upgrading biome, playwright, types, and vitest by @jaredwray in [https://github.com/jaredwray/docula/pull/403](https://github.com/jaredwray/docula/pull/403)
* chore: upgrading ai and the ai-sdk providers by @jaredwray in [https://github.com/jaredwray/docula/pull/404](https://github.com/jaredwray/docula/pull/404)
* chore: upgrading writr, ecto, and @cacheable/net to latest by @jaredwray in [https://github.com/jaredwray/docula/pull/405](https://github.com/jaredwray/docula/pull/405)
* chore: upgrading dotenv to 17.4.2 by @jaredwray in [https://github.com/jaredwray/docula/pull/406](https://github.com/jaredwray/docula/pull/406)
* chore: upgrading tsdown to 0.21.9 by @jaredwray in [https://github.com/jaredwray/docula/pull/407](https://github.com/jaredwray/docula/pull/407)
* chore: upgrading hashery to 2.0.0 by @jaredwray in [https://github.com/jaredwray/docula/pull/408](https://github.com/jaredwray/docula/pull/408)
* chore: upgrading to typescript 6.0.2 by @jaredwray in [https://github.com/jaredwray/docula/pull/409](https://github.com/jaredwray/docula/pull/409)
* feat: api reference and documentation nav cleanup by @jaredwray in [https://github.com/jaredwray/docula/pull/410](https://github.com/jaredwray/docula/pull/410)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.13.0...v1.14.0](https://github.com/jaredwray/docula/compare/v1.13.0...v1.14.0)
### v1.13.0
URL: https://docula.org/changelog/v1-13-0
Date: April 13, 2026
Tag: Release
## What's Changed
* fix: Remove site title text from header logo by @jaredwray in [https://github.com/jaredwray/docula/pull/397](https://github.com/jaredwray/docula/pull/397)
* fix: autoReadme to render root README in place without copying by @jaredwray in [https://github.com/jaredwray/docula/pull/398](https://github.com/jaredwray/docula/pull/398)
* fix: Add AI-powered README metadata enrichment for OG/meta tags by @jaredwray in [https://github.com/jaredwray/docula/pull/399](https://github.com/jaredwray/docula/pull/399)
* feat: ai enrichment for release notes by @jaredwray in [https://github.com/jaredwray/docula/pull/400](https://github.com/jaredwray/docula/pull/400)
* feat: Strip leading h1 from autoReadme content to avoid duplication by @jaredwray in [https://github.com/jaredwray/docula/pull/401](https://github.com/jaredwray/docula/pull/401)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.12.0...v1.13.0](https://github.com/jaredwray/docula/compare/v1.12.0...v1.13.0)
### v1.12.0
URL: https://docula.org/changelog/v1-12-0
Date: April 2, 2026
Tag: Release
## What's Changed
* fix: move temp-* test folders to test/temp/ directory by @jaredwray in [https://github.com/jaredwray/docula/pull/387](https://github.com/jaredwray/docula/pull/387)
* fix: Refactor test helpers into shared utilities module by @jaredwray in [https://github.com/jaredwray/docula/pull/388](https://github.com/jaredwray/docula/pull/388)
* feat: Add standalone binary build support using Node.js SEA by @jaredwray in [https://github.com/jaredwray/docula/pull/390](https://github.com/jaredwray/docula/pull/390)
* fix: Update Google Gemini model to gemini-2.5-flash-lite by @jaredwray in [https://github.com/jaredwray/docula/pull/391](https://github.com/jaredwray/docula/pull/391)
* feat: Add standalone binary support via tsdown SEA by @jaredwray in [https://github.com/jaredwray/docula/pull/392](https://github.com/jaredwray/docula/pull/392)
* feat: Add Google Tag Manager integration support by @jaredwray in [https://github.com/jaredwray/docula/pull/393](https://github.com/jaredwray/docula/pull/393)
* fix: sea binary by @jaredwray in [https://github.com/jaredwray/docula/pull/394](https://github.com/jaredwray/docula/pull/394)
* feat: google tag manager fixes and ai logging by @jaredwray in [https://github.com/jaredwray/docula/pull/395](https://github.com/jaredwray/docula/pull/395)
* fix: doing simple fixes on tests by @jaredwray in [https://github.com/jaredwray/docula/pull/396](https://github.com/jaredwray/docula/pull/396)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.11.1...v1.12.0](https://github.com/jaredwray/docula/compare/v1.11.1...v1.12.0)
### v1.11.1
URL: https://docula.org/changelog/v1-11-1
Date: March 27, 2026
Tag: Release
## What's Changed
* Fix auth controls for multi-spec API pages by @half-ogre in [https://github.com/jaredwray/docula/pull/386](https://github.com/jaredwray/docula/pull/386)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.11.0...v1.11.1](https://github.com/jaredwray/docula/compare/v1.11.0...v1.11.1)
### v1.11.0
URL: https://docula.org/changelog/v1-11-0
Date: March 26, 2026
Tag: Release
## What's Changed
* feat: add support for multiple OpenAPI/Swagger specs by @jaredwray in [https://github.com/jaredwray/docula/pull/383](https://github.com/jaredwray/docula/pull/383)
* fix: Remove automatic copying of referenced assets in README by @jaredwray in [https://github.com/jaredwray/docula/pull/384](https://github.com/jaredwray/docula/pull/384)
* fix: removing return to home button as logo has link by @jaredwray in [https://github.com/jaredwray/docula/pull/385](https://github.com/jaredwray/docula/pull/385)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.10.1...v1.11.0](https://github.com/jaredwray/docula/compare/v1.10.1...v1.11.0)
### v1.10.1
URL: https://docula.org/changelog/v1-10-1
Date: March 25, 2026
Tag: Release
## What's Changed
* feat: adding styling documentation for copy code and lightbox by @jaredwray in [https://github.com/jaredwray/docula/pull/381](https://github.com/jaredwray/docula/pull/381)
* feat: Allow raw HTML in changelog entries by @half-ogre in [https://github.com/jaredwray/docula/pull/382](https://github.com/jaredwray/docula/pull/382)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.10.0...v1.10.1](https://github.com/jaredwray/docula/compare/v1.10.0...v1.10.1)
### v1.10.0
URL: https://docula.org/changelog/v1-10-0
Date: March 24, 2026
Tag: Release
## What's Changed
* feat: draft changelog, copy code, lightbox, homeUrl, and changelog link fix by @half-ogre in [https://github.com/jaredwray/docula/pull/380](https://github.com/jaredwray/docula/pull/380)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.9.1...v1.10.0](https://github.com/jaredwray/docula/compare/v1.9.1...v1.10.0)
### v1.9.1
URL: https://docula.org/changelog/v1-9-1
Date: March 23, 2026
Tag: Release
## What's Changed
* fix: changelog entry url was wrong by @jaredwray in [https://github.com/jaredwray/docula/pull/379](https://github.com/jaredwray/docula/pull/379)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.9.0...v1.9.1](https://github.com/jaredwray/docula/compare/v1.9.0...v1.9.1)
### v1.9.0
URL: https://docula.org/changelog/v1-9-0
Date: March 23, 2026
Tag: Release
## What's Changed
* feat: add editPageUrl option for Edit this page button by @jaredwray in [https://github.com/jaredwray/docula/pull/373](https://github.com/jaredwray/docula/pull/373)
* feat: Add OpenGraph meta tags support for social sharing by @jaredwray in [https://github.com/jaredwray/docula/pull/374](https://github.com/jaredwray/docula/pull/374)
* feat: Add JSON-LD schema generation for SEO by @jaredwray in [https://github.com/jaredwray/docula/pull/375](https://github.com/jaredwray/docula/pull/375)
* feat: Extract builder logic into modular files by @jaredwray in [https://github.com/jaredwray/docula/pull/376](https://github.com/jaredwray/docula/pull/376)
* feat: Add autoReadme feature to automatically copy project README to site by @jaredwray in [https://github.com/jaredwray/docula/pull/377](https://github.com/jaredwray/docula/pull/377)
* feat: adding in ai offering for opengraph via frontmatter by @jaredwray in [https://github.com/jaredwray/docula/pull/378](https://github.com/jaredwray/docula/pull/378)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.8.0...v1.9.0](https://github.com/jaredwray/docula/compare/v1.8.0...v1.9.0)
### v1.8.0
URL: https://docula.org/changelog/v1-8-0
Date: March 19, 2026
Tag: Release
## What's Changed
* chore: upgrading biome, types, and vitest by @jaredwray in [https://github.com/jaredwray/docula/pull/368](https://github.com/jaredwray/docula/pull/368)
* chore: upgrading @cacheable/net by @jaredwray in [https://github.com/jaredwray/docula/pull/369](https://github.com/jaredwray/docula/pull/369)
* chore: upgrading ecto and writr by @jaredwray in [https://github.com/jaredwray/docula/pull/370](https://github.com/jaredwray/docula/pull/370)
* chore: upgrading serve_handler by @jaredwray in [https://github.com/jaredwray/docula/pull/371](https://github.com/jaredwray/docula/pull/371)
* feat: adding in docula downloads by @jaredwray in [https://github.com/jaredwray/docula/pull/372](https://github.com/jaredwray/docula/pull/372)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.7.0...v1.8.0](https://github.com/jaredwray/docula/compare/v1.7.0...v1.8.0)
### v1.7.0
URL: https://docula.org/changelog/v1-7-0
Date: March 17, 2026
Tag: Release
## What's Changed
* feat: adding in changelog json feed by @jaredwray in [https://github.com/jaredwray/docula/pull/367](https://github.com/jaredwray/docula/pull/367)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.6.0...v1.7.0](https://github.com/jaredwray/docula/compare/v1.6.0...v1.7.0)
### v1.6.0
URL: https://docula.org/changelog/v1-6-0
Date: March 17, 2026
Tag: Release
## What's Changed
* Configurable base URL and content paths by @half-ogre in [https://github.com/jaredwray/docula/pull/366](https://github.com/jaredwray/docula/pull/366)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.5.0...v1.6.0](https://github.com/jaredwray/docula/compare/v1.5.0...v1.6.0)
### v1.5.0
URL: https://docula.org/changelog/v1-5-0
Date: March 16, 2026
Tag: Release
## What's Changed
* feat: adding in variables.css for simpler styling by @jaredwray in [https://github.com/jaredwray/docula/pull/350](https://github.com/jaredwray/docula/pull/350)
* feat: changelog with preview, paging, and individual pages by @jaredwray in [https://github.com/jaredwray/docula/pull/351](https://github.com/jaredwray/docula/pull/351)
* feat: adding build date to the templates by @jaredwray in [https://github.com/jaredwray/docula/pull/352](https://github.com/jaredwray/docula/pull/352)
* feat: builder hooks now have access to the console by @jaredwray in [https://github.com/jaredwray/docula/pull/353](https://github.com/jaredwray/docula/pull/353)
* feat: documentation on how to add custom scripts by @jaredwray in [https://github.com/jaredwray/docula/pull/354](https://github.com/jaredwray/docula/pull/354)
* feat: init auto detection of typescript and javascript flag by @jaredwray in [https://github.com/jaredwray/docula/pull/355](https://github.com/jaredwray/docula/pull/355)
* feat: adding robust cache and hash differentials for template overrides by @jaredwray in [https://github.com/jaredwray/docula/pull/357](https://github.com/jaredwray/docula/pull/357)
* feat: adding differential builds by @jaredwray in [https://github.com/jaredwray/docula/pull/358](https://github.com/jaredwray/docula/pull/358)
* fix: the output path should be in the sitePath like cache is by @jaredwray in [https://github.com/jaredwray/docula/pull/359](https://github.com/jaredwray/docula/pull/359)
* feat: Add 'start' command that builds, watches, and serves the site by @jaredwray in [https://github.com/jaredwray/docula/pull/360](https://github.com/jaredwray/docula/pull/360)
* feat: Add `dev` command that builds, watches, and serves the site by @jaredwray in [https://github.com/jaredwray/docula/pull/361](https://github.com/jaredwray/docula/pull/361)
* fix: start and dev are two different options by @jaredwray in [https://github.com/jaredwray/docula/pull/362](https://github.com/jaredwray/docula/pull/362)
* feat: smart handling of views by @jaredwray in [https://github.com/jaredwray/docula/pull/363](https://github.com/jaredwray/docula/pull/363)
* feat: Cookie auth improvements and cached auth state by @half-ogre in [https://github.com/jaredwray/docula/pull/356](https://github.com/jaredwray/docula/pull/356)
* fix: confg docs and some flaky tests by @jaredwray in [https://github.com/jaredwray/docula/pull/364](https://github.com/jaredwray/docula/pull/364)
* fix: side bar ordering and css fixes by @jaredwray in [https://github.com/jaredwray/docula/pull/365](https://github.com/jaredwray/docula/pull/365)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.3.0...v1.5.0](https://github.com/jaredwray/docula/compare/v1.3.0...v1.5.0)
### v1.2.0
URL: https://docula.org/changelog/v1-2-0
Date: March 12, 2026
Tag: Release
## What's Changed
* feat: adding in feed.xml generation by @jaredwray in [https://github.com/jaredwray/docula/pull/343](https://github.com/jaredwray/docula/pull/343)
* fix: adding some fixes to generating feed.xml by @jaredwray in [https://github.com/jaredwray/docula/pull/344](https://github.com/jaredwray/docula/pull/344)
* fix: API operation rendering by @half-ogre in [https://github.com/jaredwray/docula/pull/346](https://github.com/jaredwray/docula/pull/346)
* fix: Improve API reference auth handling by @half-ogre in [https://github.com/jaredwray/docula/pull/345](https://github.com/jaredwray/docula/pull/345)
* fix: making theme unique between sites by @jaredwray in [https://github.com/jaredwray/docula/pull/347](https://github.com/jaredwray/docula/pull/347)
* feat: updating footer to have llms and feed by @jaredwray in [https://github.com/jaredwray/docula/pull/348](https://github.com/jaredwray/docula/pull/348)
## New Contributors
* @half-ogre made their first contribution in [https://github.com/jaredwray/docula/pull/346](https://github.com/jaredwray/docula/pull/346)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.1.0...v1.2.0](https://github.com/jaredwray/docula/compare/v1.1.0...v1.2.0)
### v1.1.0
URL: https://docula.org/changelog/v1-1-0
Date: March 10, 2026
Tag: Release
## What's Changed
* feat: Add configurable header links with optional custom icons by @jaredwray in [https://github.com/jaredwray/docula/pull/342](https://github.com/jaredwray/docula/pull/342)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v1.0.0...v1.1.0](https://github.com/jaredwray/docula/compare/v1.0.0...v1.1.0)
### v1.0.0
URL: https://docula.org/changelog/v1-0-0
Date: March 9, 2026
Tag: Release
## What's Changed
* fix: mobile home page vertical scroll for both themes by @jaredwray in [https://github.com/jaredwray/docula/pull/338](https://github.com/jaredwray/docula/pull/338)
* feat: adding oath cookie logon by @jaredwray in [https://github.com/jaredwray/docula/pull/339](https://github.com/jaredwray/docula/pull/339)
* Add file-based caching for GitHub API data in .cache folder by @jaredwray in [https://github.com/jaredwray/docula/pull/341](https://github.com/jaredwray/docula/pull/341)
* fix: adding fixes to oath by @jaredwray in [https://github.com/jaredwray/docula/pull/340](https://github.com/jaredwray/docula/pull/340)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v0.90.0...v1.0.0](https://github.com/jaredwray/docula/compare/v0.90.0...v1.0.0)
### v0.90.0
URL: https://docula.org/changelog/v0-90-0
Date: March 7, 2026
Tag: Release
## What's Changed
* feat: adding try it now to api reference by @jaredwray in [https://github.com/jaredwray/docula/pull/325](https://github.com/jaredwray/docula/pull/325)
* feat: collapse side navigation by default in api by @jaredwray in [https://github.com/jaredwray/docula/pull/326](https://github.com/jaredwray/docula/pull/326)
* feat: adding in --p and --port for docula serve by @jaredwray in [https://github.com/jaredwray/docula/pull/327](https://github.com/jaredwray/docula/pull/327)
* feat: ability to include assets in markdown by @jaredwray in [https://github.com/jaredwray/docula/pull/328](https://github.com/jaredwray/docula/pull/328)
* feat: adding in x-api-key support for try it by @jaredwray in [https://github.com/jaredwray/docula/pull/329](https://github.com/jaredwray/docula/pull/329)
* chore: adding tests to verify light / dark toggle by @jaredwray in [https://github.com/jaredwray/docula/pull/330](https://github.com/jaredwray/docula/pull/330)
* fix: playright fix with light theme by @jaredwray in [https://github.com/jaredwray/docula/pull/331](https://github.com/jaredwray/docula/pull/331)
* feat: adding in better watch functionality by @jaredwray in [https://github.com/jaredwray/docula/pull/332](https://github.com/jaredwray/docula/pull/332)
* feat: adding in a default light or dark mode by @jaredwray in [https://github.com/jaredwray/docula/pull/333](https://github.com/jaredwray/docula/pull/333)
* feat: updating docs to have correct content by @jaredwray in [https://github.com/jaredwray/docula/pull/334](https://github.com/jaredwray/docula/pull/334)
* feat: adding in build flag by @jaredwray in [https://github.com/jaredwray/docula/pull/335](https://github.com/jaredwray/docula/pull/335)
* feat: better logging on the cli by @jaredwray in [https://github.com/jaredwray/docula/pull/336](https://github.com/jaredwray/docula/pull/336)
* feat: adding in partial templates by @jaredwray in [https://github.com/jaredwray/docula/pull/337](https://github.com/jaredwray/docula/pull/337)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v0.50.0...v0.90.0](https://github.com/jaredwray/docula/compare/v0.50.0...v0.90.0)
### v0.50.0
URL: https://docula.org/changelog/v0-50-0
Date: March 3, 2026
Tag: Release
## What's Changed
* feat: Add new theme support by @chrisllontop in [https://github.com/jaredwray/docula/pull/319](https://github.com/jaredwray/docula/pull/319)
* feat: adding ux fixes for modern by @jaredwray in [https://github.com/jaredwray/docula/pull/320](https://github.com/jaredwray/docula/pull/320)
* feat: remove the home page if not needed by @jaredwray in [https://github.com/jaredwray/docula/pull/321](https://github.com/jaredwray/docula/pull/321)
* feat: creating homePage options by @jaredwray in [https://github.com/jaredwray/docula/pull/322](https://github.com/jaredwray/docula/pull/322)
* feat: adding home buttons by @jaredwray in [https://github.com/jaredwray/docula/pull/323](https://github.com/jaredwray/docula/pull/323)
* feat: adding llms support by @jaredwray in [https://github.com/jaredwray/docula/pull/324](https://github.com/jaredwray/docula/pull/324)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v0.41.1...v0.50.0](https://github.com/jaredwray/docula/compare/v0.41.1...v0.50.0)
### v0.41.1
URL: https://docula.org/changelog/v0-41-1
Date: February 23, 2026
Tag: Release
## What's Changed
* fix: remove he.decode() calls that break HTML entities in code blocks by @jaredwray in [https://github.com/jaredwray/docula/pull/317](https://github.com/jaredwray/docula/pull/317)
* fix: publishing to npmjs with dist folder by @jaredwray in [https://github.com/jaredwray/docula/pull/318](https://github.com/jaredwray/docula/pull/318)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v0.41.0...v0.41.1](https://github.com/jaredwray/docula/compare/v0.41.0...v0.41.1)
### v0.41.0
URL: https://docula.org/changelog/v0-41-0
Date: February 20, 2026
Tag: Release
## What's Changed
* feat: add OpenAPI support with API documentation page by @chrisllontop in [https://github.com/jaredwray/docula/pull/303](https://github.com/jaredwray/docula/pull/303)
* chore: moving to nodejs 24 by @jaredwray in [https://github.com/jaredwray/docula/pull/312](https://github.com/jaredwray/docula/pull/312)
* chore: upgrading ecto to 4.8.2 by @jaredwray in [https://github.com/jaredwray/docula/pull/313](https://github.com/jaredwray/docula/pull/313)
* chore: upgrading vitest and other modules to latest by @jaredwray in [https://github.com/jaredwray/docula/pull/314](https://github.com/jaredwray/docula/pull/314)
* chore: upgrading cheerio and dotenv to latest by @jaredwray in [https://github.com/jaredwray/docula/pull/315](https://github.com/jaredwray/docula/pull/315)
* chore: upgrading @cacheable/net to 2.0.5 by @jaredwray in [https://github.com/jaredwray/docula/pull/316](https://github.com/jaredwray/docula/pull/316)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v0.40.0...v0.41.0](https://github.com/jaredwray/docula/compare/v0.40.0...v0.41.0)
### v0.40.0
URL: https://docula.org/changelog/v0-40-0
Date: January 19, 2026
Tag: Release
## What's Changed
* Use GitHub-style blockquote alerts in README by @jaredwray in [https://github.com/jaredwray/docula/pull/304](https://github.com/jaredwray/docula/pull/304)
* Skip auto-generated TOC when document already has one by @jaredwray in [https://github.com/jaredwray/docula/pull/305](https://github.com/jaredwray/docula/pull/305)
* Add TypeScript config file support (docula.config.ts) by @jaredwray in [https://github.com/jaredwray/docula/pull/306](https://github.com/jaredwray/docula/pull/306)
* feat: Add public folder copying to dist during build by @jaredwray in [https://github.com/jaredwray/docula/pull/307](https://github.com/jaredwray/docula/pull/307)
* feat: Add announcement.md support to home page by @jaredwray in [https://github.com/jaredwray/docula/pull/308](https://github.com/jaredwray/docula/pull/308)
* Add AGENTS.md for AI coding assistants by @jaredwray in [https://github.com/jaredwray/docula/pull/309](https://github.com/jaredwray/docula/pull/309)
* chore: upgrading feed to 5.2.0 by @jaredwray in [https://github.com/jaredwray/docula/pull/310](https://github.com/jaredwray/docula/pull/310)
* feat: adding in CLAUDE.md to reference AGENTS.md by @jaredwray in [https://github.com/jaredwray/docula/pull/311](https://github.com/jaredwray/docula/pull/311)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v0.31.2...v0.40.0](https://github.com/jaredwray/docula/compare/v0.31.2...v0.40.0)
### v0.31.2
URL: https://docula.org/changelog/v0-31-2
Date: December 19, 2025
Tag: Release
## What's Changed
* chore: adding in minimumReleaseAge by @jaredwray in [https://github.com/jaredwray/docula/pull/298](https://github.com/jaredwray/docula/pull/298)
* chore: upgrading vitest and biome to latest by @jaredwray in [https://github.com/jaredwray/docula/pull/299](https://github.com/jaredwray/docula/pull/299)
* chore: upgrading writr to 5.0.1 by @jaredwray in [https://github.com/jaredwray/docula/pull/300](https://github.com/jaredwray/docula/pull/300)
* chore: upgrading ecto to 4.7.1 by @jaredwray in [https://github.com/jaredwray/docula/pull/301](https://github.com/jaredwray/docula/pull/301)
* chore: upgrading @cacheable/net to 2.0.4 by @jaredwray in [https://github.com/jaredwray/docula/pull/302](https://github.com/jaredwray/docula/pull/302)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v0.31.1...v0.31.2](https://github.com/jaredwray/docula/compare/v0.31.1...v0.31.2)
### v0.31.1
URL: https://docula.org/changelog/v0-31-1
Date: November 18, 2025
Tag: Release
## What's Changed
* chore: upgrading vitest to 4.0.10 by @jaredwray in [https://github.com/jaredwray/docula/pull/292](https://github.com/jaredwray/docula/pull/292)
* chore: upgrading @biomejs/biome to 2.3.6 by @jaredwray in [https://github.com/jaredwray/docula/pull/293](https://github.com/jaredwray/docula/pull/293)
* chore: upgrading tsup to 8.5.1 by @jaredwray in [https://github.com/jaredwray/docula/pull/294](https://github.com/jaredwray/docula/pull/294)
* chore: upgrading ecto to 4.7.0 by @jaredwray in [https://github.com/jaredwray/docula/pull/295](https://github.com/jaredwray/docula/pull/295)
* chore: upgrading @cacheable/net to 2.0.3 by @jaredwray in [https://github.com/jaredwray/docula/pull/296](https://github.com/jaredwray/docula/pull/296)
* fix: type errors on builder tests by @jaredwray in [https://github.com/jaredwray/docula/pull/297](https://github.com/jaredwray/docula/pull/297)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v0.31.0...v0.31.1](https://github.com/jaredwray/docula/compare/v0.31.0...v0.31.1)
### v0.31.0
URL: https://docula.org/changelog/v0-31-0
Date: October 18, 2025
Tag: Release
## What's Changed
* chore: upgrading docula to 5.9.3 by @jaredwray in [https://github.com/jaredwray/docula/pull/281](https://github.com/jaredwray/docula/pull/281)
* chore: removing webpack as no longer needed by @jaredwray in [https://github.com/jaredwray/docula/pull/282](https://github.com/jaredwray/docula/pull/282)
* chore: upgrading @biomejs/biome to 2.2.6 by @jaredwray in [https://github.com/jaredwray/docula/pull/283](https://github.com/jaredwray/docula/pull/283)
* chore: upgrading dotenv to 17.2.3 by @jaredwray in [https://github.com/jaredwray/docula/pull/284](https://github.com/jaredwray/docula/pull/284)
* chore: upgrading ecto to 4.6.0 by @jaredwray in [https://github.com/jaredwray/docula/pull/285](https://github.com/jaredwray/docula/pull/285)
* chore: upgrading writr to 4.5.1 by @jaredwray in [https://github.com/jaredwray/docula/pull/286](https://github.com/jaredwray/docula/pull/286)
* feat: moving to @cacheable/net instead of axios by @jaredwray in [https://github.com/jaredwray/docula/pull/287](https://github.com/jaredwray/docula/pull/287)
* feat: removing helpers in favor of Writr by @jaredwray in [https://github.com/jaredwray/docula/pull/288](https://github.com/jaredwray/docula/pull/288)
* feat: adding in example sites by @jaredwray in [https://github.com/jaredwray/docula/pull/289](https://github.com/jaredwray/docula/pull/289)
* feat: supporting md files and removing mdx rendering by default @jaredwray in [https://github.com/jaredwray/docula/pull/290](https://github.com/jaredwray/docula/pull/290)
* feat: adding in mdx support when file is .mdx by @jaredwray in [https://github.com/jaredwray/docula/pull/291](https://github.com/jaredwray/docula/pull/291)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v0.30.0...v0.31.0](https://github.com/jaredwray/docula/compare/v0.30.0...v0.31.0)
### v0.30.0
URL: https://docula.org/changelog/v0-30-0
Date: September 19, 2025
Tag: Release
## What's Changed
* chore: upgrading biome to 2.2.4 by @jaredwray in [https://github.com/jaredwray/docula/pull/272](https://github.com/jaredwray/docula/pull/272)
* chore: upgrading tsx to 4.20.5 by @jaredwray in [https://github.com/jaredwray/docula/pull/273](https://github.com/jaredwray/docula/pull/273)
* chore: upgrading axios to 1.12.2 by @jaredwray in [https://github.com/jaredwray/docula/pull/274](https://github.com/jaredwray/docula/pull/274)
* chore: upgrading writr to 4.5.0 by @jaredwray in [https://github.com/jaredwray/docula/pull/275](https://github.com/jaredwray/docula/pull/275)
* chore: upgrading ecto to 4.4.2 by @jaredwray in [https://github.com/jaredwray/docula/pull/276](https://github.com/jaredwray/docula/pull/276)
* chore: upgrading dotenv to 17.2.2 by @jaredwray in [https://github.com/jaredwray/docula/pull/277](https://github.com/jaredwray/docula/pull/277)
* fix: adding in test coverage by @jaredwray in [https://github.com/jaredwray/docula/pull/278](https://github.com/jaredwray/docula/pull/278)
* chore: upgrade ecto to latest by @jaredwray in [https://github.com/jaredwray/docula/pull/279](https://github.com/jaredwray/docula/pull/279)
* fix: major fix to docs and ecto not rendering by @jaredwray in [https://github.com/jaredwray/docula/pull/280](https://github.com/jaredwray/docula/pull/280)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v0.20.0...v0.30.0](https://github.com/jaredwray/docula/compare/v0.20.0...v0.30.0)
### v0.20.0
URL: https://docula.org/changelog/v0-20-0
Date: August 18, 2025
Tag: Release
## What's Changed
* fix: add landing stylesheet by @jaredwray in [https://github.com/jaredwray/docula/pull/264](https://github.com/jaredwray/docula/pull/264)
* chore: upgrading typescript, tsx, and webpack to latest by @jaredwray in [https://github.com/jaredwray/docula/pull/265](https://github.com/jaredwray/docula/pull/265)
* fix: fixing the code coverage issue by @jaredwray in [https://github.com/jaredwray/docula/pull/266](https://github.com/jaredwray/docula/pull/266)
* chore: upgrading axios to 1.11.0 by @jaredwray in [https://github.com/jaredwray/docula/pull/267](https://github.com/jaredwray/docula/pull/267)
* chore: upgrading writr to 4.4.6 by @jaredwray in [https://github.com/jaredwray/docula/pull/268](https://github.com/jaredwray/docula/pull/268)
* chore: upgrading cheerio to 1.1.2 by @jaredwray in [https://github.com/jaredwray/docula/pull/269](https://github.com/jaredwray/docula/pull/269)
* chore: upgrading dotenv to 17.2.2 by @jaredwray in [https://github.com/jaredwray/docula/pull/270](https://github.com/jaredwray/docula/pull/270)
* fix: migrating to biome from xo by @jaredwray in [https://github.com/jaredwray/docula/pull/271](https://github.com/jaredwray/docula/pull/271)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v0.13.1...v0.20.0](https://github.com/jaredwray/docula/compare/v0.13.1...v0.20.0)
### v0.13.1
URL: https://docula.org/changelog/v0-13-1
Date: July 18, 2025
Tag: Release
## What's Changed
* chore: upgrading xo to 1.2.1 by @jaredwray in [https://github.com/jaredwray/docula/pull/258](https://github.com/jaredwray/docula/pull/258)
* chore: upgrading writr to 4.4.5 by @jaredwray in [https://github.com/jaredwray/docula/pull/259](https://github.com/jaredwray/docula/pull/259)
* chore: upgrading webpack to 5.100.2 by @jaredwray in [https://github.com/jaredwray/docula/pull/260](https://github.com/jaredwray/docula/pull/260)
* chore: upgrading ecto to 4.4.0 by @jaredwray in [https://github.com/jaredwray/docula/pull/261](https://github.com/jaredwray/docula/pull/261)
* chore: upgrading dotenv to 17.2.0 by @jaredwray in [https://github.com/jaredwray/docula/pull/262](https://github.com/jaredwray/docula/pull/262)
* chore: upgrading init with new files by @jaredwray in [https://github.com/jaredwray/docula/pull/263](https://github.com/jaredwray/docula/pull/263)
**Full Changelog**: [https://github.com/jaredwray/docula/compare/v0.13.0...v0.13.1](https://github.com/jaredwray/docula/compare/v0.13.0...v0.13.1)
### String Date Entry
URL: https://docula.org/changelog/2024-11-01-string-date
Date: Q1 2025
Tag: Added

## Overview
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
## New Features
- **Template Engine Overhaul** — Refactored the Handlebars template resolver to support nested partials and dynamic layout inheritance. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
- **Markdown Extensions** — Added support for custom directives, including callouts, tabs, and collapsible sections. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
- **Changelog Pagination** — Introduced paginated changelog views with configurable entries per page, improving load times for projects with extensive release histories.
- **Search Integration** — Built-in full-text search powered by a pre-built index generated at build time. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit.
## Bug Fixes
- Fixed an issue where relative image paths in nested documentation directories resolved incorrectly during builds.
- Resolved a race condition in the file watcher that caused duplicate rebuilds when multiple files changed simultaneously.
- Corrected date parsing for changelog entries using non-standard date formats such as `"Q1 2025"` or `"Summer 2024"`.
## Breaking Changes
- The `outputDir` option has been renamed to `output` for consistency with other configuration fields. Update your `docula.config.ts` accordingly.
- Minimum Node.js version is now 20. Support for Node.js 18 has been dropped.
## Migration Guide
To upgrade from the previous version, update your configuration file:
```typescript
// Before
const options = { outputDir: './dist' };
// After
const options = { output: './dist' };
```
Run `pnpm install` to update dependencies, then `pnpm build` to verify your site builds correctly.
## Performance
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Build times improved by approximately 40% for sites with over 100 documentation pages.
## Contributors
Thanks to all contributors who made this release possible. At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident.