Imported from ortus-boxlang/bx-sites (
AGENTS.md). Install upstream withnpx skills add ortus-boxlang/bx-sites. Copyright stays with the author.
Project Guidelines
Purpose
This repository contains the bx-sites BoxLang module, its static-site
generator, and the documentation site that dogfoods it. Keep changes focused
on the module's public CLI, build output, tests, documentation, and packaging
contracts.
Architecture
ModuleConfig.bxowns module metadata, runtime activation, CLI argument parsing, and verb dispatch.models/build/contains the build pipeline and content processors.models/cli/contains one dispatcher class per CLI verb.models/config/contains configuration and source-directory resolution.models/deploy/contains deployment contracts and target implementations;models/publish/contains the bxSites Cloud publisher.resources/assets/andresources/themes/are packaged runtime resources.docs/is this repository's site source,tests/specs/contains TestBox specs, andtests/support/contains test doubles and fixtures.- Keep implementation BoxLang-first. Add Java libraries or compiled classes only when they are genuinely required as packaged runtime input.
Project folders
- A project's content root is resolved by
SourceDirResolver.bxsites.yaml's ownsourcekey wins outright when set -docs,src, any custom folder name, or.(the whole repo is the content, no subfolder). Whensourceis unset,docs/thensrc/are auto-detected; when neither exists ANDsourceis unset, resolving throwsBxSites.SourceNotConfiguredinstead of silently falling back to the project root - see docs/guides/content-source.md. - A project's
.theme/(an authored override) and.themes/<name>/(aninstall:theme-installed theme) both live inside that resolved content root, not at the project root. site/is always generated build output. Never treat it as a source folder; builds remove and recreate it.- Deployment configuration belongs under
deployments/, notdeploy/, to avoid colliding with thedeployCLI verb. bxsites.yamlis the preferred project configuration format. JSON remains supported throughbxsites.jsonand--format=json;docs/nav.jsonis always JSON because it is parsed separately as a navigation override.
Local Toolchain Setup
On a fresh machine/sandbox with no BoxLang install, bootstrap the toolchain like this (idempotent - safe to re-run):
# 1. Installs BoxLang + a bundled Lucee-based CommandBox (v6.x) to
# /usr/local/boxlang, and bx-cli's own launcher scripts to /root/.boxlang/bin.
/bin/bash -c "$(curl -fsSL https://install.boxlang.io)"
# 2. install-boxlang/install-bx-module need these two vars in the SAME shell
# invocation that calls them - the installer appends them to ~/.bashrc, but
# most non-interactive shells (including how Bash tool calls run here) hit
# Ubuntu's default `[ -z "$PS1" ] && return` guard near the top of
# ~/.bashrc, so `source ~/.bashrc` alone silently no-ops and leaves them
# unset. Export them directly instead, every time, rather than sourcing.
export BOXLANG_INSTALL_HOME="/usr/local/boxlang"
export PATH="/root/.boxlang/bin:/usr/local/bin:$PATH"
# 3. Install the real, BoxLang-native CommandBox (bx-cli, v7.x) - NOT the
# Lucee-based v6.x one the quick installer bundles as a fallback at
# /usr/local/boxlang/bin/box. Both land on PATH as `box`; bx-cli's own
# launcher at /root/.boxlang/bin/box must come FIRST (see the export
# above) or the wrong `box` wins silently. `box version` should report
# "CommandBox 7.x" (bx-cli), not "CommandBox 6.x" (Lucee) - verify this
# before trusting any following `box`/`install-bx-module` output.
install-bx-module bx-cli
# 4. Project-local dependencies (testbox, coldbox modules, etc. - box.json's
# own devDependencies), plus the global BoxLang modules CI installs via
# setup-boxlang's own `modules:` list (not part of box.json, since these
# are runtime deps of the module itself, not the test tooling).
cd /path/to/bx-sites
box install --verbose --nosave
install-bx-module bx-esapi,bx-yaml,bx-toml,bx-markdown,bx-image,bx-docbox
# 5. BoxLang looks for modules under $BOXLANG_HOME/modules (default
# ~/.boxlang/modules) by name, matching @bxsites references throughout
# this codebase - symlink this checkout in under that name (see
# tests.yml's own "Test Module" step, which does the same in CI).
export BOXLANG_HOME="/root/.boxlang"
mkdir -p "${BOXLANG_HOME}/modules"
ln -sfn "$(pwd)" "${BOXLANG_HOME}/modules/bx-sites"
chmod +x testbox/run
./testbox/run --stream
Every later shell (a fresh Bash tool call, a new terminal) needs the three
exports from steps 2 and 5 re-set - none of it persists via ~/.bashrc in
a non-interactive shell, per the gotcha above.
If a source file's edits don't seem to take effect on the next test run, clear BoxLang's own compiled-class cache and retry before assuming the change is wrong - it's usually just stale bytecode from a prior run in the same session:
rm -rf "${BOXLANG_HOME}/classes/$(pwd | tr '/' '_')"
Build And Test
- Install dependencies with
box install --verbose --nosavewhen reproducing CI locally. - Use the native BoxLang TestBox runner at
./testbox/run; its streaming flag is--stream(not--streaming). - Run all normal specs with
./testbox/run --streamor use./testbox/run --reporter=ANTJunit --verbosefor CI-style output. - Select bundles with
--bundles=<dot-notated-bundle>; use--filter-bundles=<pattern>only to filter discovered bundles. For example:./testbox/run --bundles=tests.specs.cli.NewSpec --stream. - Use
--show-failed-only --hide-skippedto keep focused streaming output concise, and--slow-threshold-ms=<n>or--top-slowest=<n>to investigate slow specs. - The full dogfood documentation build is opt-in. Normal tests skip
DogfoodDocsSpecwithout building the docs; run it explicitly with:BXSITES_RUN_DOGFOOD_TESTS=true ./testbox/run --bundles=tests.specs.DogfoodDocsSpec --stream. - TestBox's runner does not reliably return a failing process exit code. When
consuming its results in automation, inspect the generated JUnit XML for
nonzero
failuresorerrors, as.github/workflows/tests.ymldoes. - Package the module with
boxlang Build.bx --version=<version> --buildId=<id> --branch=<branch>. Preserve token replacement, source exclusions, the primary artifact, the with-dependencies artifact, and checksum generation. Generated files belong underbuild/. - For a real local site build, use
boxlang bxSites build. The repository'sbuildMultiTheme.shis local preview tooling only; it builds the ten themes with separate Git worktrees and requiresboxlang,yq, and a Git checkout. - Changes to the real build path should be checked with a real build, not only
the TestBox fakes. CI also verifies that a successful-looking build produced
non-empty
site/output because CLI errors can be swallowed during dispatch.
Documentation And Locales
- Keep
docs/i18n/{de,es,it}/synchronized with the English documentation tree. Any documentation change underdocs/needs the equivalent translated update in each locale mirror unless the task explicitly scopes the change to English. - New examples should use YAML by default and should match the behavior of a
freshly scaffolded
bxSites newproject. - Preserve the distinction between authored source under
docs/orsrc/and generated output undersite/.
BoxLang Conventions
- Avoid private helper names that collide with built-in functions, and qualify helper calls when name resolution could be ambiguous.
- An arrow closure has its own
argumentsscope. Capture outer arguments in a local variable before using them insidefilter,map,some, or similar callbacks. - Do not mix positional and named arguments in one call. Use one style for the complete call.
- BoxLang string literals use doubled delimiters rather than backslash escapes.
Interpolation with
#...#works in both quote styles; construct literal hash delimiters withchar( 35 )when a string would otherwise contain a pair. dateFormat()masks are case-sensitive:MMis month andmmis minutes.directoryList(path, true, "path")can include directories; filter them when a file-only result is required.- Use the module mapping (
bxsites) for runtime class lookup, not the ForgeBox slug (bx-sites). - CLI primary values should use
--flag=value; a bare first positional can be interpreted as a project-root override byModuleConfig.bx.
GitHub Actions
.github/workflows/tests.ymlinstalls BoxLang dependencies, links this checkout intoBOXLANG_HOME/modules, runs the TestBox suite, and uploads JUnit results..github/workflows/pages.ymlbuilds the ten built-in themes in a matrix, verifies eachsite/before publishing, and assembles the theme gallery. The workflow detects whethermainexists before splitting ownership of the published root and/next/content betweenmainanddevelopment.- Keep workflow changes aligned with the module's actual packaging and build behavior; do not rely on a green CLI exit code alone for site builds.
Available Skills
The repository ships task-specific agent skills in .agents/skills. Before
implementing, reviewing, or debugging work covered by one of these areas, read
the relevant SKILL.md and follow its guidance. Prefer the most specific skill
available when more than one applies.
BoxLang Core
boxlang-core-dev-async-tasks: BoxFuture, AsyncService, executors, schedulers, and async lifecycle callbacks.boxlang-core-dev-bif-development: Custom BoxLang built-in functions and module registration.boxlang-core-dev-component-development: Custom BoxLang components and tag registration.boxlang-core-dev-interceptors: Interceptors, observer events, pools, and registration.boxlang-core-dev-logging: LoggingService, BoxLangLogger, and structured logging configuration.boxlang-core-dev-module-development: ModuleConfig lifecycle, metadata, BIFs, interceptors, and packaging.boxlang-core-dev-runtime-architecture: BoxLang runtime, scopes, types, parsing, contexts, and class loading.boxlang-scheduled-tasks: Scheduler DSL, cron/frequency constraints, lifecycle callbacks, and scheduled HTTP work.boxlang-security: BoxLang security settings, validation, file uploads, secrets, and OWASP concerns.boxlang-templating:.bxmtemplates, mixed HTML/BoxLang, and template components.boxlang-web-development: BoxLang web applications, HTTP handling, REST, sessions, CSRF, and servers.boxlang-zip: ZIP creation and extraction with thebx:zipcomponent.
BoxLang Modules And Integrations
bx-docbox: DocBox API documentation generation and output strategies.bx-esapi: OWASP ESAPI encoding, decoding, and HTML sanitization.bx-ftp: FTP, FTPS, SFTP, SSH keys, and connection pools.bx-image: Image creation and manipulation with bx-image.bx-mail: Mail components, multipart messages, SMTP, signing, and encryption.bx-pdf: PDF documents, sections, headers, footers, saving, and encryption.bx-rss: RSS/Atom feed reading and creation.bx-web-support: Mock web servers, requests, and web-context tests.bx-yaml: YAML serialization, deserialization, files, and BoxLang classes.
CommandBox
commandbox-config-settings: Global CommandBox settings and environment overrides.commandbox-deploying: CommandBox production deployment, Docker, CI, and hosting.commandbox-developing: Custom commands, namespaces, WireBox, modules, and interceptors.commandbox-embedded-server: Embedded server configuration, SSL, bindings, aliases, and profiles.commandbox-package-management:box.json, ForgeBox packages, dependencies, locks, and publishing.commandbox-setup: Installing and configuring CommandBox and Java runtimes.commandbox-task-runners: Task runners, targets, lifecycle hooks, jobs, watchers, and shell integration.commandbox-testing: CommandBox and TestBox integration, runners, reporters, and coverage.commandbox-usage: CommandBox commands, namespaces, settings, recipes, aliases, and shell usage.
Testing
boxlang-testing: BoxLang TestBox tests, BDD, xUnit, MockBox, fixtures, async tests, and CLI execution.testbox-assertions:$assertmethods, custom assertions, type, collection, exception, and numeric checks.testbox-bdd: BDD suites, lifecycle hooks, labels, focused/skipped specs, and data binding.testbox-cbmockdata: Realistic mock data, nested objects, arrays, and custom suppliers.testbox-expectations: Fluentexpect()matchers, collection modes, negation, and custom matchers.testing-fixtures: Shared fixtures, factories, test data builders, and fixture lifecycle.testbox-listeners: Test run listener callbacks and lifecycle reporting.testbox-mockbox: MockBox mocks, stubs, spies, verification, properties, and query simulation.testbox-reporters: TestBox reporter selection, options, and custom reporters.testbox-runners: TestBox CLI, BoxLang, web, programmatic, streaming, watcher, and filtering options.testbox-unit-xunit: xUnit test classes, lifecycle methods,$assert, and AAA structure.testing-coverage: Coverage configuration, reporting, CI integration, and interpretation.testing-fixtures: Shared fixtures, factories, test data builders, and fixture lifecycle.
Engineering And Supporting Tools
code-documenter: Developer documentation, API references, runbooks, and documentation consistency.code-reviewer: Reviews focused on correctness, security, maintainability, performance, and test risk.gitbook-docs-expert: GitBook frontmatter, hints, content references, embeds, tabs, and navigation.github-action-authoring: Composite GitHub Actions, runner support, PATH issues, and CI jobs.java-expert: Java services, libraries, concurrency, performance, dependencies, and hardening.junit-expert: JUnit 5 lifecycle, parameterized tests, assertions, extensions, and build integration.mockito-expert: Mockito mocks, stubs, spies, matchers, captors, and strict stubbing.ortus-java-coding-standards: Ortus formatting, naming, structure, and code-style conventions.security-expert: Secure system design, threat modeling, secrets, authentication, and authorization.
Change Discipline
- Prefer small, template-safe changes and preserve public APIs and generated output conventions.
- Update related metadata together when changing names, versions, slugs, or
build tokens:
ModuleConfig.bx,box.json,Build.bx,readme.md, andchangelog.mdas applicable. - Do not commit generated
build/,site/, test-result, or temporary files. - Keep this file focused on repository-wide rules. Put task-specific workflows in a scoped instruction file or skill instead.