Getting Started
Install the module, scaffold a project, and build your first site.
On this page
Getting Started
Install
BX Sites depends on bx-markdown
for Markdown rendering, bx-esapi
for HTML-encoding, bx-yaml for
reading bxsites.yaml, and bx-image
for the responsive-image pipeline (see Responsive Images) -
all four are installed automatically as box.json dependencies, so
installing bx-sites itself is the only command needed, either via
BoxLang's own OS binary installer:
install-bx-module bx-sites
or via CommandBox:
box install bx-sites
Either one reads box.json's boxlang.executable
and drops a bxSites script on your PATH (in ~/.boxlang/bin), so every
command below works either as a short standalone command:
bxSites <verb> [options]
or, everywhere BoxLang is available but that PATH shim isn't (a CI
runner, a module registered by hand rather than installed) - both forms
run the exact same thing:
boxlang bxSites <verb> [options]
The rest of this guide uses the short form.
Scaffold a project
bxSites new my-docs
cd my-docs
This creates:
my-docs/
├── docs/
│ ├── assets/
│ └── index.md
└── bxsites.yaml
Pass --theme=material or --theme=tailwind to scaffold with a different
default theme, and --name="My Project Docs" to set the site name up
front - otherwise new derives it from the target directory name.
Config file format
bxsites.yaml is the default and preferred format - it's what new
scaffolds unless told otherwise, and every example in this guide and in
Configuration shows it first. bxsites.json is fully
supported too, for a project that prefers it: pass --format=json to
scaffold one instead, or just hand-write/rename one yourself - ConfigLoader
resolves whichever of bxsites.yaml/.yml/.json is actually present, in
that order, with no other config needed to switch. See
Configuration for the full key reference in both
formats.
Already have content in GitBook? bxSites migrate --source=/path/to/export
converts a GitBook export straight into docs/ - see
Migrating from GitBook - and you can
skip ahead to Build.
Add pages
Every .md file under docs/ becomes a page. Folder nesting becomes nav
nesting automatically:
docs/ is what new scaffolds and what every example here uses, but a
project that isn't really "docs" in spirit - a marketing site, a
portfolio - can use src/ instead, with zero other changes: every verb
(build, serve, check, lint, page:new, ...) looks for docs/
first and falls back to src/ when that's what actually exists. Build
output always lands in site/ either way - the two never collide, since
site/ is never itself a valid source-folder name.
docs/
├── index.md -> /
├── guides/
│ ├── index.md -> /guides/
│ └── deployment.md -> /guides/deployment/
(A large site can override this inferred order/grouping entirely with an
explicit nav - see nav.)
Linking between pages
Link to another page the normal mkdocs way - a file-relative path to its
.md source, exactly as if the two files were sitting next to each other
on disk (because they are):
See [Deployment](guides/deployment.md) or, from that same guide,
[back to Getting Started](../getting-started.md#add-pages).
BX Sites rewrites every such link to its built pretty-URL at build time
(guides/deployment.md -> /guides/deployment/index.html, anchors and
query strings preserved), resolved against the linking page's own
folder - ../ and sibling references work exactly like they would
resolving any other relative path. This is also why the link keeps
working if you read the file directly on GitHub instead of the built
site: it's a real, valid relative path to a real file either way. Absolute
URLs, mailto:, and links already starting with / are left untouched.
Downloading a page as Markdown
Every built page also gets its own original .md source published
alongside it - docs/guides/deployment.md ends up copied to
site/guides/deployment.md, right next to
site/guides/deployment/index.html - with a "Download Markdown" link on
the page itself, next to "Edit this page". No config needed, always on.
This is the same motivation as llms.txt -
a person (or an LLM) can fetch a page's raw Markdown directly instead of
scraping rendered HTML - and since the whole docs/ tree is mirrored 1:1,
a page's own relative links keep working read this way too.
Each page can start with a small frontmatter block:
---
title: Deployment
order: 2
hidden: false
description: How to deploy a built BX Sites site.
tags: [guides, deployment]
icon: 🚀
summary: Everything you need to publish a built site.
ogImage: assets/deployment-card.png
toc: true
---
# Deployment
Your content here.
title- overrides the nav/page title (otherwise derived from the filename)order- controls sibling ordering in the nav (lower sorts first; omitted pages sort last, alphabetically)hidden-trueexcludes the page from the nav (and from search) without excluding it from the builddescription- this page's social-card/meta description (seeogImage); falls back to the site-widedescriptionin the site config when omittedtags- an array of tags for this page, rendered as clickable badges under the title and collected into a site-wide/tags/index page (only built at all once at least one page has tags); also boosts search relevance for matching queriesicon- shown next to the page title and its nav entry - a plain emoji, or a named icon from a bundled library (rocket,lucide:rocket,tabler:rocket, or a project's owncustom:my-icon) - see Themes: Iconssummary- a one-line lead-in shown under the title (distinct fromdescription, which is meta-tag-only and never rendered on the page itself)ogImage- overrides this one page's social-card image - seeogImagetoc-falsehides this page's own "On this page" table of contents, even with 2+ headings (the usual trigger for it to render) - handy for a landing/hero page that doesn't want a floating TOC competing with its own content; defaults totrue
Frontmatter values can be inline lists (tags: [a, b, c]), YAML-style block
lists (tags: followed by indented - item lines), or >/| block
scalars for a multi-line value - it's a small hand-rolled parser though, not
full YAML, so nested objects/maps aren't supported.
Build
bxSites build
Renders every page in docs/ into a static site in site/, ready to host
anywhere that serves static files.
Serve locally
bxSites serve
Builds the project, serves site/ at http://127.0.0.1:8080/, and
rebuilds automatically whenever you save a change under docs/, your
bxsites.yaml/.json site config, or a project-level theme/ override -
your browser reloads on its own. Pass --port=3000 or --host=0.0.0.0 to
change how it binds.
Clean
bxSites clean
Removes site/ and any build cache, without touching your docs/ source.