docula.config.ts (TypeScript) or docula.config.mjs (JavaScript) file to customize the build process with lifecycle hooks.llms.txt and llms-full.txt for LLM-friendly indexing of docs, API reference, and changelog content.See Docula in action with these open source projects that use it for their documentation:
These examples showcase different approaches to using Docula, from simple single-page sites to more complex documentation with multiple pages and custom configurations.
npx docula init
This will create a folder called site with the following structure:
site
├───site.css
├───logo.png
├───favicon.ico
├───README.md
├───docula.config.mjs
Note: for typescript do 'docula init --typescript'
Simply replace the logo, favicon, and css file with your own. The readme is your root project readme and you just need to at build time move it over to the site folder. If you have it at the root of the project and this is a folder inside just delete the README.md file in the site folder and docula will copy it over for you automatically.
npx docula
This will build your site and place it in the dist folder. You can then host it anywhere you like.
Docula supports TypeScript configuration files (docula.config.ts) in addition to JavaScript (docula.config.mjs). TypeScript configs provide type safety and better IDE support.
To create a new project with a TypeScript config file:
npx docula init --typescript
This creates a docula.config.ts file with full type support:
import type { DoculaOptions } from 'docula';
export const options: Partial<DoculaOptions> = {
templatePath: './template',
outputPath: './dist',
sitePath: './site',
githubPath: 'your-username/your-repo',
siteTitle: 'My Project',
siteDescription: 'Project description',
siteUrl: 'https://your-site.com',
};
You can add typed lifecycle hooks to your config:
import type { DoculaOptions } from 'docula';
export const options: Partial<DoculaOptions> = {
siteTitle: 'My Project',
// ... other options
};
export const onPrepare = async (config: DoculaOptions): Promise<void> => {
// Runs before the build process
console.log(`Building ${config.siteTitle}...`);
};
When both config files exist, Docula loads them in this order (first found wins):
docula.config.ts (TypeScript - takes priority)docula.config.mjs (JavaScript)| Option | Type | Default | Description |
|---|---|---|---|
templatePath |
string |
'./template' |
Path to custom template directory |
outputPath |
string |
'./dist' |
Output directory for built site |
sitePath |
string |
'./site' |
Directory containing site content |
githubPath |
string |
- | GitHub repository path (e.g., 'user/repo') |
siteTitle |
string |
'docula' |
Website title |
siteDescription |
string |
- | Website description |
siteUrl |
string |
- | Website URL |
port |
number |
3000 |
Port for local development server |
singlePage |
boolean |
true |
Single page or multi-page site |
homePage |
boolean |
true |
When false, Docula uses the first docs page as /index.html instead of rendering home.hbs |
sections |
DoculaSection[] |
- | Documentation sections |
openApiUrl |
string |
- | OpenAPI spec URL for API documentation (auto-detected if api/swagger.json exists) |
enableReleaseChangelog |
boolean |
true |
Convert GitHub releases to changelog entries |
enableLlmsTxt |
boolean |
true |
Generate llms.txt and llms-full.txt in the build output |
If you want to use your own template you can do so by adding a docula.config.ts file to the root of your project. This file will be used to configure the build process.
or at the command line:
npx docula --template path/to/template
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
The readme.md file will be the root page and the rest will be added to the table of contents. 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 the markdown file. Here is an example:
title: Getting Started
order: 2
If you want your docs to be the root home page (/) instead of rendering the template home page, set homePage: false:
export const options = {
homePage: false,
};
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.
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:
Docula can generate an API Reference page from an OpenAPI (Swagger) specification. The page is rendered using Docutopia and is available at /api.
If your site directory contains an api/swagger.json file, Docula will automatically detect it and generate the API Reference page — no configuration needed:
site
├───api
│ └───swagger.json
├───docs
├───logo.svg
├───favicon.ico
└───docula.config.mjs
You can also set the openApiUrl option in your config to point to any OpenAPI spec, either a local path or a remote URL:
export const options = {
openApiUrl: '/api/swagger.json',
// or a remote URL:
// openApiUrl: 'https://petstore.swagger.io/v2/swagger.json',
};
When openApiUrl is set explicitly, it takes priority over auto-detection.
The file must be a valid OpenAPI 3.x or Swagger 2.0 JSON specification. A minimal example:
{
"openapi": "3.0.0",
"info": {
"title": "My API",
"version": "1.0.0"
},
"paths": {}
}
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./llms.txt includes:
/llms-full.txt/llms-full.txt includes:
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.
To disable generation:
export const options = {
enableLlmsTxt: false,
};
You can override generated output by providing custom files in your site directory:
site/llms.txtsite/llms-full.txtIf present, Docula copies these files to output as-is.
dist/llms.txt and dist/llms-full.txt).sitemap.xml.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.
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:
**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.
The announcement uses your theme's CSS variables and displays with:
--sidebar-background--color-secondary--color-primaryYou can customize the appearance by overriding the .announcement class in your variables.css:
.announcement {
background-color: #fff3cd;
border-left-color: #ffc107;
}
Simply delete the announcement.md file when you no longer need the announcement. The home page will automatically return to its normal layout.
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.
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
Each changelog entry is a markdown file with front matter:
---
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
| 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. |
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/When changelog entries are found, Docula generates:
/changelog/ — shows all entries sorted by date (newest first) with titles, dates, tags, and content/changelog/{slug}/ — a dedicated page for each entry with a back link to the listingChangelog URLs are also automatically added to the generated sitemap.xml.
Tags receive a CSS class based on their value (e.g., a tag of "Bug Fix" gets the class changelog-tag-bug-fix). You can style tags and other changelog elements by overriding these classes in your variables.css:
.changelog-entry {
border-bottom: 1px solid var(--border);
padding: 1.5rem 0;
}
.changelog-tag {
font-size: 0.75rem;
padding: 0.2rem 0.5rem;
border-radius: 4px;
}
.changelog-tag-release {
background-color: #d4edda;
color: #155724;
}
.changelog-tag-bug-fix {
background-color: #f8d7da;
color: #721c24;
}
Docula uses Writr's GitHub-flavored Markdown plugins, including GitHub-style blockquote alerts. Use the alert syntax directly in Markdown:
> [!NOTE]
> Info: Remember to configure your GitHub token for private repos.
> [!WARNING]
> Warn: This action cannot be undone.
> [!CAUTION]
> Alert: Rotate your secrets immediately.
These render with the remark-github-blockquote-alert classes (like .markdown-alert and .markdown-alert-note). If you want GitHub-like styling, copy the plugin's CSS into your site/variables.css or template stylesheet (for example, from remark-github-blockquote-alert/alert.css), or add your own overrides:
.markdown-alert {
border-left: 4px solid var(--border);
border-radius: 8px;
margin: 1rem 0;
padding: 0.75rem 1rem;
background: var(--background);
}
.markdown-alert-note {
border-left-color: #4c8ef7;
}
.markdown-alert-warning {
border-left-color: #f2b90c;
}
.markdown-alert-caution {
border-left-color: #e5534b;
}
If you want to use the Github token to access the Github API you can do so by setting the GITHUB_TOKEN environment variable. This is useful if you want to access private repositories or if you want to access the Github API without hitting the rate limit. This is optional and you can still use docula without it but could hit rate limits and will not be able to access private repositories.
Docula provides powerful helper utilities through its integration with Writr. 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:
See the Working with Markdown using Writr section below for comprehensive examples and usage patterns.
Docula exports Writr for powerful markdown operations including loading files, rendering, and managing frontmatter. Writr provides a simple API for working with markdown content.
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');
Front matter is metadata at the top of markdown files in YAML format. Writr makes it easy to read and modify:
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');
// 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';
// 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');
Code of Conduct and Contributing guidelines.
MIT © Jared Wray
Full Changelog: https://github.com/jaredwray/docula/compare/v0.41.1...v0.50.0
Full Changelog: https://github.com/jaredwray/docula/compare/v0.41.0...v0.41.1
Full Changelog: https://github.com/jaredwray/docula/compare/v0.31.2...v0.40.0