@veluai/velu
v0.2.52
Published
A documentation-site generator with live preview. Scaffold a docs project and run it locally with two commands — author your pages in Markdown + components, configure the site with a single `velu.json`.
Readme
Velu
A documentation-site generator with live preview. Scaffold a docs project
and run it locally with two commands — author your pages in Markdown +
components, configure the site with a single velu.json.
npm install -g @veluai/velu
velu init my-docs
velu dev my-docsThen open http://localhost:8358. Editing any .mdx page or velu.json
reloads the browser automatically.
Requires Node.js 18+. Prefer not to install globally? Use
npx @veluai/velu init my-docsandnpx @veluai/velu dev my-docs.
Commands
| Command | What it does |
| --- | --- |
| velu init <dir> | Scaffold a new docs project into <dir> (creates velu.json, a favicon, and a set of starter .mdx pages). Add --template help-center to start from a help center instead. |
| velu migrate mintlify [dir] | Migrate Mintlify docs into a new directory; supports --out, --dry-run, --strict, and --json. |
| velu dev [dir] | Start the live-preview dev server for the project in <dir> (defaults to the current directory). |
Set a custom port with the PORT env var:
PORT=5180 velu dev my-docsMigrate from Mintlify
velu migrate mintlify ./mintlify-docs --out ./velu-docs --dry-run
velu migrate mintlify ./mintlify-docs --out ./velu-docsThe source stays untouched. Configuration, MDX, snippets, custom CSS/JavaScript, assets, and supported npm scripts are migrated, with JSON and Markdown reports for anything requiring review. See the migration guide for coverage, exit codes, and runtime limitations.
Set "theme": "vepa" in velu.json for the Vepa preset. Migration
maps Mintlify’s sequoia setting to vepa automatically. See Vepa compatibility
for the pinned Mintlify reference, verified geometry, and remaining parity limits.
Project layout
velu init produces a project shaped like this:
my-docs/
├─ velu.json # site config: name, colors, font, favicon, navigation
├─ favicon.svg
├─ index.mdx # pages, organized however your navigation references them
├─ quickstart.mdx
└─ …velu.json
velu.json drives the whole site — branding and navigation:
{
"$schema": "https://veluai.com/velu.schema.json",
"name": "My Docs",
"colors": { "primary": "#dc143c" },
"favicon": "/favicon.svg",
"font": { "family": "Inter" },
"navigation": {
"tabs": [
{
"tab": "Guides",
"groups": [
{ "group": "Getting started", "pages": ["index", "quickstart"] }
]
}
]
}
}colors—primaryis required;lightanddarkdefault toprimary.navigation— Mintlify-compatible:products → versions → languages → tabs → anchors → groups → pages. Switchable axes (products, versions, languages) become URL path prefixes; the default value of each axis is unprefixed. Languages are stored as ISO 639-1 codes and shown with their native name.
Page labels come from each page's frontmatter title.
Group landing pages and directory listings
Give a group a root page to make it the group's landing page. Set
directory to list the group's pages and sub-groups automatically below that
page's content, which is how a help center gets its topic and article indexes:
{
"navigation": {
"directory": "card",
"groups": [
{
"group": "Account",
"root": "account/index",
"pages": ["account/billing", "account/plans"]
}
]
}
}"card"lists entries as cards,"accordion"lists them in bordered panels, and"none"(the default) shows no listing.- Set
directoryon the navigation root or on any product, version, language, tab or group. It applies to everything nested below, and a nested node can override it. - Only a group with a
rootpage gets a listing. Each entry shows the page's frontmattertitle,descriptionandicon; a nested group shows its article count and links to its ownrootpage. - Pages a reader cannot access are left out of the listing.
velu init my-help-center --template help-center scaffolds a working example.
Custom CSS and JavaScript
Every .css and .js file in the project folder (at any depth) is included on
every page — nothing to configure. CSS is linked after the theme so your rules
win; JS runs once per page load, after the page has hydrated. Dot-folders,
node_modules/, public/ and the build output are skipped.
MDX also supports Tailwind utility classes on HTML elements
(className="w-full rounded-xl", dark:hidden, …) — they are scanned from the
project and generated into the theme stylesheet. A utility class you put on an
element beats the theme's own styles for it, so text-base on an <h2> really
is body size.
Landing pages (mode: custom)
A page with mode: custom in its frontmatter keeps only the top bar. When
every top-level element of the page is a layout block (<div>, <section>,
<header>, <footer>), the page is a blank canvas: full width, no padding, and
your own classes own the layout. A page with loose headings or paragraphs gets
a centered column instead.
Two helpers for landing pages:
- Any element with
data-search-triggeropens search when clicked. Adddata-search-term="billing"to open it with that query filled in. <Card href="/account" cta="4 articles">shows the label as the card's link text and keeps the whole card clickable.- Any element with
data-assistant-triggeropens Ask AI (data-assistant-question="..."starts it with a question). These elements are hidden wherever Ask AI is unavailable: the local preview, and sites whose plan turns it off. <Columns cols={3}>lays its children out three to a row and wraps the rest onto new rows; on a phone each one takes a full row.
The help center template's home page (velu init <name> --template help-center)
uses all of this.
Selectors follow Mintlify's, so Mintlify custom CSS ports over:
- Ids on the layout —
#navbar,#sidebar,#sidebar-content,#content,#content-area,#table-of-contents,#pagination,#footer,#search-bar-entry,#search-input,#assistant-entry,#topbar-cta-button,#page-context-menu,#chat-assistant-sheet,#feedback-*,#request-example,#response-example,#changelog-filters,#localization-select-*, … - Element selectors — components render as the same tags Mintlify uses, so
card { },callout { },code-block { },steps { },toc-item { },sidebar-group { },mdx-content { }… work as-is. Roots that must stay native HTML (<a>,<button>,<details>…) carrydata-componentinstead:[data-component="accordion"],[data-component="nav-tabs-item"]. - State —
html[data-theme="dark"],html[data-current-path="/quickstart"], and[data-active]on the active sidebar link, header tab, TOC item and dropdown item.
/* style.css */
#navbar { background: #fffff2; }
card { border-radius: 0; }
html[data-theme="dark"] callout { border-color: #444; }// analytics.js
window.dataLayer = window.dataLayer || [];License
Proprietary. © Velu.
