Gradle Plugin

On this page

Gradle Plugin

Java and Spring Boot developers don't need CommandBox or a system-wide BoxLang install to add a bx-sites site to their own project - the io.boxlang.bxsites Gradle plugin downloads everything it needs (the BoxLang runtime and bx-sites itself) into a local cache the first time it runs. The only prerequisite is a JDK 21.

Status: pre-1.0, not yet published to the Gradle Plugin Portal - see gradle-plugin/ in the bx-sites repo for the source and current build/test instructions. This page documents what it does once published; the mechanics below are already real and verified, just not yet available as a one-line plugins { } dependency.

Quick start

plugins {
    id("io.boxlang.bxsites") version "<version>"
}
./gradlew bxSitesNew    # scaffolds docs/ + bxsites.yaml
./gradlew bxSitesBuild   # renders docs/**.md into site/
./gradlew bxSitesServe   # build + serve locally with live reload

A default setup needs nothing else configured - the plugin infers the content directory (docs/, falling back to src/ - except in a project with the Java plugin applied, where src/ is your actual Java source root and is never used as bx-sites content) and the output directory (always <projectRoot>/site/) automatically. Your site's own look, theme, nav, and every other setting is controlled entirely by bxsites.yaml/.toml/.json at the project root, exactly as documented in Configuration - the plugin never duplicates that schema, it only wires up how and when bx-sites runs from your build.

Tasks

TaskWhat it does
bxSitesNewScaffolds a new bx-sites project. Not wired into any lifecycle - run it once, explicitly.
bxSitesBuildRenders the site. Real up-to-date checking: reruns only when your content, config, or the pinned versions actually change.
bxSitesServeBuilds and serves the site locally with live reload. Runs in the foreground until stopped.
bxSitesCleanRemoves the built site/ directory.
bxSitesSearchIndexRebuilds site/search-index.json without a full site build.
bxSitesLintLints the docs/ Markdown source. Wired into check by default (see hookIntoCheck below).
bxSitesDeployBuilds the site and deploys it to the configured target.
bxSitesPublishBuilds the site and publishes it to bxSites Cloud.
bxSitesPackageBuilds the site and zips it to site.zip.
bxSitesStatsReports page/word counts and other stats for the built site.
bxSitesDoctorRuns bx-sites' own project health diagnostics.

bxSitesBuild never runs automatically as part of assemble unless you opt in (see hookIntoAssemble below) - a docs build is a distinct, often-slower concern from compiling your actual code.

Configuration

bxSites {
    projectRoot.set(layout.projectDirectory)
    boxlangMiniserverVersion.set("1.18.0-snapshot")   // pinned BoxLang runtime version
    bxSitesVersion.set("1.0.0-snapshot")               // pinned bx-sites version
    boxlangHomeDir.set(layout.buildDirectory.dir("bxsites/boxlang-home"))
    hookIntoAssemble.set(false)                        // opt-in: run bxSitesBuild as part of assemble
    hookIntoCheck.set(true)                            // wires bxSitesLint into `check` by default
}

Every property has a sensible default. The output directory isn't settable here at all - bx-sites itself hardcodes it to <projectRoot>/site/, so the plugin derives it rather than exposing a setting that wouldn't actually be honored.

Spring Boot doc generation

bxSitesOpenApiDoc wires a springdoc-generated OpenAPI/Swagger spec into your site as an interactive widget, using bx-sites' own native ::: openapi ::: content block - no OpenAPI parsing happens on our side at all. It's not wired into any lifecycle by default (bind it yourself once your project's springdoc plugin has produced a spec file, e.g. tasks.named("bxSitesBuild") { dependsOn("bxSitesOpenApiDoc") }):

bxSites {
    springBoot {
        openApi {
            enabled.set(true)
            specFile.set(layout.buildDirectory.file("openapi/openapi.json"))
            pageTitle.set("Bookshelf API")     // default: "API Reference"
            pagePath.set("api/openapi.md")     // relative to the content dir; this is the default
            autoPatchConfig.set(false)         // set true to auto-add openapi: true to bxsites.yaml/.toml instead of failing
        }
    }
}

Requires your own springdoc Gradle plugin already applied and configured to generate the spec file this points at - bxSitesOpenApiDoc only consumes that file, copying it into the content dir's assets/openapi/ and writing a thin wrapper page. It also expects bxsites.yaml's openapi: true to already be set (see Configuration) - fails with an actionable error if it isn't, unless autoPatchConfig is on (YAML/TOML configs only; JSON is never auto-patched, since safely inserting a key into arbitrary JSON without a real parser is too risky). Known limitation: Swagger UI renders entirely client-side, so per-endpoint text never reaches bx-sites' own search index - only the wrapper page's title/frontmatter is indexed.

bxSitesJavadocDoc emits one Markdown page per public top-level Java type, using the JDK's own Javadoc doclet SPI in-process (no javadoc subprocess). Also opt-in, not wired into any lifecycle by default:

bxSites {
    springBoot {
        javadoc {
            enabled.set(true)
            sourceFiles.from(sourceSets.getByName("main").allJava)
            pagePathPrefix.set("api/javadoc")   // this is the default
            tags.set(listOf("api", "javadoc"))  // this is the default
        }
    }
}

Deliberately scoped down for v1, not a complete Javadoc-to-Markdown converter - this is the heaviest of the three Spring Boot generators and a full doclet-spec-compliant implementation is a much larger effort than this milestone budgeted for. What it covers: public/protected constructors and methods of public top-level types (nested and package-private types, and fields, are skipped entirely), each member's own doc comment (not inherited ones), and @param/@return/@throws/ @deprecated tags. What it deliberately doesn't do yet: inline HTML in doc comments is stripped rather than converted to Markdown (a best-effort text extraction, not a full HTML-to-Markdown converter); {@link}/ {@see} render as inline code with no cross-page hyperlink resolution; no index/nav page is generated - wiring pages into your site's own navigation is left to you. Runs against source files directly, so records' compiler-generated accessors/toString/equals/hashCode show up too, matching the standard javadoc tool's own behavior.

bxSitesControllerScanDoc reflection-scans compiled classes for Spring MVC controllers and emits one page per controller listing its mapped endpoints - the fallback generator, for projects without OpenAPI generation on:

bxSites {
    springBoot {
        controllerScan {
            // enabled defaults to true unless springBoot.openApi.enabled is true
            classesDir.set(layout.buildDirectory.dir("classes/java/main"))
            runtimeClasspath.from(configurations.getByName("runtimeClasspath"))
            pagePathPrefix.set("api/controllers")     // this is the default
            tags.set(listOf("api", "controllers"))    // this is the default
        }
    }
}

Runs the scan in a forked JVM against your project's own runtime classpath (Spring included) - never in this plugin's own JVM, which stays Spring-agnostic. Deliberately scoped down: only classes directly annotated @Controller/@RestController are recognized (a custom stereotype annotation built on @Controller isn't); only directly annotated @RequestMapping/@GetMapping/@PostMapping/@PutMapping/ @DeleteMapping/@PatchMapping methods are recognized; nested classes are skipped; and since reflection has no access to source-level doc comments, generated pages list endpoints (method, path, handler signature) with no per-endpoint description text.

BoxLang doc generation

bxSitesDocBoxDoc generates a BoxLang/CFML API reference from DocBox, for a JVM project whose sources include .bx/.cfc classes. Unlike the three Spring Boot generators above it's a thin wrapper around the bx-sites docbox verb rather than an in-JVM generator - the implementation lives on the BoxLang side, and one implementation both build tools drive can't drift the way two would. Opt in, and it's wired into no lifecycle by default:

bxSites {
    boxlang {
        docbox {
            enabled.set(true)
            mappings.put("models", "models")
            projectTitle.set("Bookshelf API")   // default: the site's own name + " API"
            excludes.set("tests|build")
            pagePathPrefix.set("api/docbox")    // this is the default
            tags.set(listOf("api", "docbox"))   // this is the default
        }
    }
}

Only options you actually set are passed through, so anything left out still falls through to bxsites.yaml - the config file stays the single source of truth and this block only overrides it. See DocBox API Reference for what the pages look like, and note that the bx-docbox module has to be installed in the provisioned BoxLang runtime.

There is deliberately no ColdBox task. A ColdBox application is built and run through CommandBox, never Gradle, so bxSites coldbox stays a bx-sites CLI concern.

What's not built yet

  • bxSitesServe's live output streaming - currently buffers output with a 30-minute timeout, both wrong for a task meant to run indefinitely.

See the Maven Plugin guide for the equivalent on the Maven side - both wrap the same underlying logic, so verb coverage and behavior stay identical between the two build tools.

Edit this page Download Markdown Last updated Sep 11, 2026, 7:11:15 PM