Introduction to LRX
LRX is a modern documentation framework built for speed and simplicity. It takes your Markdown content, processes it through a flexible pipeline, and generates a fully-featured documentation site with search, navigation, and syntax highlighting out of the box.
Whether you're documenting a library, an API, or an internal knowledge base, LRX provides the tools you need without the overhead you don't.
If you're coming from another documentation tool, check out our migration guide for a smooth transition.
Why LRX?
Most documentation tools force you to choose between simplicity and power. LRX bridges that gap with a convention-over-configuration approach that scales from a single README to thousands of pages.
- Zero config start -- drop in your Markdown files and run
lrx build - Blazing fast -- incremental builds in under 100ms for most projects
- Full-text search -- built-in client-side search, no external service required
- Flexible theming -- override any component with your own templates
How It Works
At its core, LRX follows a three-stage pipeline:
- Parse -- Markdown files are parsed into an AST with frontmatter extraction
- Transform -- Plugins process the AST (syntax highlighting, link resolution, table of contents)
- Render -- Templates convert the processed AST into static HTML pages
This pipeline is fully extensible. Each stage exposes hooks that let you modify behavior without forking the core.
LRX requires Node.js 18 or later. Make sure you have it installed before proceeding.
Installation
Install LRX globally via npm, or add it as a dev dependency to your project:
# Global installation
npm install -g lrx
# Or as a dev dependency
npm install --save-dev lrx
Verify the installation by checking the version:
lrx --version
# lrx v3.2.1
If you're using an older version of LRX (v2.x), note that the configuration format has changed. See the Config File section for migration steps.
Quick Start
The fastest way to get started is with the init command. It scaffolds a new documentation project with sensible defaults:
lrx init my-docs
cd my-docs
lrx dev
This creates the following structure:
my-docs/
├── docs/
│ ├── index.md
│ └── getting-started.md
├── lrx.config.js
└── package.json
Open http://localhost:3000 in your browser and you'll see your documentation site with live reloading enabled. Every time you save a Markdown file, the page refreshes automatically.
Pages
Every Markdown file in your docs/ directory becomes a page. The file path determines the URL:
| File Path | URL | Nav Title |
|---|---|---|
docs/index.md |
/ |
Home |
docs/guide/setup.md |
/guide/setup |
Setup |
docs/api/hooks.md |
/api/hooks |
Hooks |
docs/changelog.md |
/changelog |
Changelog |
Frontmatter
Each page can include YAML frontmatter to control its metadata:
---
title: My Custom Title
description: A brief description for SEO
order: 3
category: Guides
---
The order field controls the position in the sidebar navigation. Pages without an order are sorted alphabetically after ordered pages.
Routing
LRX uses file-system routing. The directory structure inside docs/ maps directly to URL paths. Nested directories create nested routes with automatic breadcrumb generation.
// lrx.config.js
export default {
routes: {
base: '/docs',
trailingSlash: false,
rewrites: {
'/old-path': '/new-path'
}
}
}
Custom rewrites let you redirect legacy URLs without breaking existing links. LRX generates a _redirects file compatible with most hosting platforms.
Data Fetching
Pages can pull in external data at build time using the data frontmatter key or the fetchData hook:
// hooks/fetch-api-data.js
export default {
name: 'fetch-api-data',
hook: 'beforeRender',
async handler(context) {
const response = await fetch('https://api.example.com/data');
context.data.apiData = await response.json();
}
}
Data is available in templates via the data object. This is useful for dynamically populating API reference pages from OpenAPI specs or pulling in release notes from GitHub.
Templates
LRX ships with a default template that produces the documentation layout you see here. You can override any part of it by creating matching files in your project's templates/ directory:
templates/
├── layout.html # Main page wrapper
├── sidebar.html # Left navigation
├── article.html # Content area
├── toc.html # On-this-page sidebar
└── components/
├── callout.html
├── code-block.html
└── table.html
Templates use a minimal Mustache-like syntax with {{variable}} for interpolation and {{#each items}} for iteration. No external template engine is required.
Config File
The lrx.config.js file at your project root controls all build behavior. Here's a complete example with all available options:
// lrx.config.js
export default {
title: 'My Project Docs',
description: 'Documentation for My Project',
base: '/',
outDir: 'dist',
theme: {
colors: {
primary: '#3B82F6',
background: '#FFFFFF'
},
font: 'Inter'
},
search: {
enabled: true,
placeholder: 'Search docs...',
hotkey: '/'
},
sidebar: {
collapsible: true,
defaultOpen: 2
},
plugins: [
'lrx-plugin-mermaid',
['lrx-plugin-analytics', { id: 'G-XXXXX' }]
]
}
Environment
LRX supports environment-specific configuration through .env files. Variables prefixed with LRX_ are available in your config and templates:
# .env.production
LRX_BASE_URL=https://docs.example.com
LRX_ANALYTICS_ID=G-XXXXX
Access environment variables in your config using process.env.LRX_BASE_URL. LRX loads .env, .env.local, and .env.[mode] files in order, with later files taking precedence.
Plugins
Plugins extend LRX functionality without modifying core code. Each plugin is a function that receives the LRX build context and can hook into any stage of the pipeline:
// lrx-plugin-example.js
export default function myPlugin(options = {}) {
return {
name: 'my-plugin',
configResolved(config) {
// Modify resolved config
},
transform(content, id) {
// Transform markdown content
return content;
},
buildEnd(context) {
// Run after build completes
}
}
}
Plugins run in the order they appear in your config. If a plugin depends on another's output, make sure it's listed after its dependency.
CLI Commands
LRX provides a focused set of CLI commands for common workflows:
| Command | Description | Common Flags |
|---|---|---|
lrx dev |
Start development server with live reload | --port 3000 |
lrx build |
Build static site to outDir |
--mode production |
lrx preview |
Preview built site locally | --port 4000 |
lrx init |
Scaffold a new documentation project | --template minimal |
Run lrx --help or lrx [command] --help for full usage information.
Hooks
Hooks let you tap into specific moments of the LRX build lifecycle. They're the primary extension mechanism for plugins:
const hooks = {
'config:resolved': (config) => {},
'pages:collected': (pages) => {},
'page:beforeTransform': (page) => {},
'page:afterTransform': (page) => {},
'page:beforeRender': (page, data) => {},
'build:start': (context) => {},
'build:end': (context) => {}
}
Hooks are async-compatible. Return a Promise and LRX will await it before proceeding to the next stage. Multiple plugins can hook into the same lifecycle event.
Utilities
LRX exposes a set of utility functions for common documentation tasks. Import them from the lrx/utils package:
import { slugify, readFrontmatter, resolveLinks, buildTOC } from 'lrx/utils';
// Generate URL-safe slugs from headings
slugify('Hello World!'); // 'hello-world'
// Extract frontmatter from markdown
const { data, content } = readFrontmatter(markdown);
// Resolve relative links between pages
const resolved = resolveLinks(content, currentPage, allPages);
// Build table of contents from headings
const toc = buildTOC(content, { maxDepth: 3 });
Build Process
Running lrx build executes the full build pipeline:
- Collect -- Scan
docs/directory for all Markdown files - Parse -- Extract frontmatter and convert Markdown to AST
- Transform -- Run all transform plugins (syntax highlighting, link resolution)
- Render -- Apply templates to generate HTML pages
- Emit -- Write files to
outDirwith assets and search index
lrx build --mode production --outDir dist
# Output:
# ✓ Collected 47 pages
# ✓ Transformed in 230ms
# ✓ Rendered in 180ms
# ✓ Search index: 12.4kb
# ✓ Total: 410ms
Production builds automatically minify HTML and CSS, generate a sitemap, and create a search index. Use --no-minify to skip minification for debugging.
Hosting
LRX generates plain static files that can be hosted anywhere. Here are configurations for popular platforms:
Netlify
# netlify.toml
[build]
command = "lrx build"
publish = "dist"
Vercel
{
"buildCommand": "lrx build",
"outputDirectory": "dist"
}
GitHub Pages
# .github/workflows/docs.yml
name: Deploy Docs
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npx lrx build
- uses: peaceiris/actions-gh-pages@v3
with:
publish_dir: ./dist
After building, your dist/ directory contains everything needed to serve the site. No server-side runtime is required.
Use lrx preview locally to verify the production build before deploying. It starts a static file server that mirrors production behavior.