cd <your project>
curl -Lo dtcw4 https://doctoolchain.org/dtcw4
chmod +x dtcw4
docToolchain Manual
1. What Is docToolchain?
1.1. Introduction
docToolchain is a documentation generation tool that uses the Docs as Code approach as a basis for its architecture, plus some additional automation provided by the arc42 template.
1.2. Docs as Code
‘Docs as code’ refers to a philosophy that you should write documentation using the same tools as you use to write code. If you need to write technical docs for your software project, why not use the same tools and processes as you use for your source code? There are so many benefits:
-
You don’t have to learn a complicated docs management system.
-
Developers feel more at home in the docs because they look and feel like code.
-
You can manage docs using standard version control like GitHub.
1.3. arc42
arc42 has been a part of docToolchain since the earliest version. But what is arc42?
Dr. Gernot Starke and Peter Hruschka created the arc42 template as a standard for software architecture documentation. They used their experience of software architectures both in the template structure and the explanations that appear in each chapter to guide you when you’re writing your documentation.
arc42 is available in well-known formats including MS Word, textile, and Confluence. All of these formats are automatically generated from a single golden master which is formatted in AsciiDoc.
1.4. How docToolchain Brings Everything Together
To follow a docs as code approach, you need a build script that automates steps like exporting diagrams and rendering Markdown (or AsciiDoc in the case of docToolchain) to the target format.
Creating this type of build script is not easy (and even harder to maintain). There are also lots of questions to answer: “How do I create .docx?” and “Why doesn’t lib x work with lib y?”
docToolchain is the result of one developer’s journey through the docs as code universe. The goal of docToolchain is to automate the creation of technical docs through an easy-to-use build script that only needs to be configured not modified, and that is nurtured and cared for by a diverse open source community.
1.5. What You Get with docToolchain
1.5.1. A Ready-Made Document Management System
By using a version control system like Git, you get a perfect document management system for free. Git allows you to version your docs, branch them, and also leaves an audit trail. You can even check who wrote which part of the docs. Isn’t that great?
And because your docs are simple plain text, it’s easy to do a diff and see exactly what has changed. Bonus: storing your docs in the same repo as your code means they’re always in sync!
1.5.2. Built-In Collaboration and Review
As a distributed version control system, Git comes with doc collaboration and review processes built in. People can fork the docs and send pull requests for the changes they make. You review the changes. Done!
1.5.3. Image References and Code Snippets
Instead of pasting images into a binary document format, docToolchain lets you reference images. This ensures that your imagery is always up-to-date every time you rebuild your documents.
You can also reference code snippets directly from your source code. You’ll save so much time because your docs and code will always be in sync and completely up to date!
1.5.4. Compound and Stakeholder-Tailored Docs
As if image refs and code snippets weren’t enough, docToolchain also lets you split docs into several sub-documents plus a master for greater cohesion. And you’re not restricted to one master. You can create master docs for different stakeholders that only contain the chapters they need.
1.5.5. And So Much More…
If you can dream it, you can script it! Want to include a list of open issues from Jira? You can! Want to include a changelog from Git? Go for it! Want to use inline text-based diagrams? Knock yourself out!
1.6. Install docToolchain
1.6.1. Prerequisites
-
Java 17, 21 or 25 — check with
java -version(./dtcw4 local install javainstalls Java 25 for you) -
git — needed to clone docToolchain during installation
-
Bash —
dtcw4is a Bash script (on Windows, use WSL2)
1.6.2. Quick Start
1. Get the Wrapper Script
Download dtcw4 into your project directory:
On Windows, use WSL2. dtcw4 is a Bash script.
|
2. Install docToolchain
# Install Java if needed
./dtcw4 local install java
# Install docToolchain v4
./dtcw4 local install doctoolchain
This clones the main-4.x branch and builds the runtime JARs once (~2 min).
After that, no build tool is involved at runtime.
3. Download a Template (optional)
First, create a config file if you don’t have one yet:
touch docToolchainConfig.groovy
./dtcw4 local downloadTemplate
This interactively installs the arc42 architecture template and updates your config file.
4. Generate Output
./dtcw4 local generateHTML
./dtcw4 local generatePDF
./dtcw4 local generateSite
Output is written to the build/ directory:
build/
├── html5/ # generateHTML output
├── pdf/ # generatePDF output
└── microsite/
└── output/ # generateSite output
5. List All Tasks
./dtcw4 tasks
1.6.3. How It Works
Only dtcw4 lives in your project directory. It handles:
-
Installation: Clones docToolchain from GitHub and builds the runtime JARs once.
-
Task execution: Delegates to the installed
dtcwin~/.doctoolchain/docToolchain-4.0.0/, which runs tasks directly via the JVM — no Gradle, no daemon.
Runtime JARs are stored in ~/.doctoolchain/docToolchain-4.0.0/lib/.
Task execution uses direct JVM invocation (~2-3s startup).
1.6.4. Running in Docker
docToolchain provides a container image from Docker Hub:
./dtcw4 docker generateHTML
The wrapper script detects the container engine and pulls the image automatically.
Custom Docker Image
./dtcw4 docker image <image_name> generateHTML
Environment Variables for Docker
Create a file dtcw_docker.env in your project directory:
PROJECT=MY_PROJECT
TEAM=MY_TEAM
1.6.5. Updating
./dtcw4 local install doctoolchain --update
This pulls the latest main-4.x and rebuilds the runtime JARs.
1.6.6. Environment Variables
| Variable | Default | Description |
|---|---|---|
|
|
docToolchain version to use |
|
|
Git branch to install from |
|
auto-detected |
Set to |
|
|
Path to configuration file |
|
(none) |
URL to an external microsite theme zip |
1.7. Features
docToolchain v4 is a docs-as-code tool that generates professional documentation from AsciiDoc sources.
1.7.1. Fast Startup
Tasks run via direct JVM invocation — no Gradle daemon, no build system overhead. Typical startup time is 2-3 seconds.
1.7.2. No Ruby Required
v4 uses AsciidoctorJ (the Java port of AsciiDoctor) exclusively.
No Ruby gems, no external asciidoctor CLI needed.
1.7.3. Multiple Output Formats
Generate HTML, PDF, or a full microsite from the same AsciiDoc sources. See the Tasks section for all available output formats.
1.7.4. Multiple Markup Formats
The microsite renders more than AsciiDoc: Markdown and plain HTML work out of the
box, and reStructuredText (.rst) is supported via a one-line converter entry.
See Multi-Markup for the
full list and how to enable .rst.
1.7.5. Diagram Support
Built-in support for text-based diagrams via asciidoctor-diagram: PlantUML, ditaa, Mermaid, and more.
1.7.6. Math & Formulas (STEM)
docToolchain renders mathematical and scientific formulas (AsciiDoc STEM content). STEM is enabled out of the box — no configuration needed.
Use it inline or as a block, in either the latexmath or the asciimath notation:
A square root inline: stem:[sqrt(4) = 2].
[latexmath]
++++
\sum_{i=1}^{n} i = \frac{n(n+1)}{2}
++++
[asciimath]
++++
sum_(i=1)^n i = (n(n+1))/2
++++
The default notation for an unqualified \$…\$ / [stem] is latexmath.
Override it per document with :stem: asciimath, or pin a single expression with
the explicit [asciimath] / [latexmath] block forms shown above.
Formulas render in all main output formats:
-
HTML — rendered in the browser via MathJax.
-
PDF — rendered natively by asciidoctor-pdf.
| In the microsite, MathJax is loaded the same way as in standalone HTML. For fully offline / self-contained sites you can bundle MathJax locally instead of loading it from a CDN — see the tracking issue. |
1.7.7. Confluence Publishing
Publish your documentation directly to Confluence, keeping docs-as-code and Confluence in sync. Only changed pages are updated — no spam for page watchers.
1.7.8. Cross-Platform
All tasks work on Linux, macOS, and Windows.
The exportPPT task uses Apache POI — no Windows-only dependencies.
1.7.10. CI/CD Ready
Set DTC_HEADLESS=true for non-interactive mode.
Works with GitHub Actions, GitLab CI, Jenkins, and any CI system with Java 17, 21 or 25.
1.8. Extending docToolchain: Custom Tasks and Monkey-Patching
docToolchain ships every task as a self-contained Groovy script. You can use the same mechanism in your own project — to add a task or to change one that docToolchain already provides. Neither needs a fork, a build step, or an edit to a registry.
This is a v4 feature (the Gradle-free runtime driven by dtcw/dtcw4).
The older v3 customTasks config entry belongs to the Gradle build and does not
apply here.
|
1.8.1. How task resolution works
When you run ./dtcw <task>, the wrapper looks for the task script in two
places, the project first, the installation second:
-
scripts/<task>.groovyin your project (the project scripts directory) -
<task>.groovyin the installed docToolchain (~/.doctoolchain/docToolchain-<version>/scripts/)
A file counts as a task only if it carries the marker // @task within its
first five lines — exactly the rule used by the built-in tasks. This is how a
project script can be discovered without you registering it anywhere.
The project scripts directory defaults to scripts/ under your project root.
Override it with the environment variable DTC_PROJECT_SCRIPTS_DIR.
In the docker environment the project is mounted at a fixed location
inside the container, so DTC_PROJECT_SCRIPTS_DIR must be a path relative to
the project root. An absolute value cannot be reached inside the container, so
project tasks would not be found there (resolution falls back to the installed
task).
|
1.8.2. Adding a custom task
Create a skeleton with createTask and edit it:
./dtcw createTask exportNotion
This writes scripts/exportNotion.groovy with the // @task marker already in
place. Add your logic, then run it:
./dtcw exportNotion
It also shows up in the task list, under its own heading:
./dtcw tasks
You can of course create the file by hand instead — the only requirement is the
// @task marker near the top.
Reusing docToolchain’s helpers
A custom task can reuse the bundled helpers (for example DtcConfig to read
docToolchainConfig.groovy). They live in the installation, not your project,
and dtcw tells your script where via the dtc.scriptsHome system property:
def docDir = System.getProperty('docDir', '.')
def configFile = System.getProperty('mainConfigFile', 'docToolchainConfig.groovy')
def scriptsHome = System.getProperty('dtc.scriptsHome')
def gcl = new GroovyClassLoader(this.class.classLoader)
def DtcConfig = gcl.parseClass(new File(scriptsHome, 'lib/DtcConfig.groovy'))
def config = DtcConfig.load(docDir, configFile).getRaw()
println "inputPath is ${config.inputPath}"
The skeleton created by createTask already contains this pattern.
1.8.3. Monkey-patching an installed task
To change what a shipped task does, copy it into your project and edit the copy:
./dtcw copyTask generateHTML
This copies the installed generateHTML.groovy to scripts/generateHTML.groovy
in your project. Because the project copy has the same name as an installed
task, it overrides it: from now on ./dtcw generateHTML runs your copy.
docToolchain makes the override visible so you never patch by accident:
-
./dtcw generateHTMLprints a note to stderr that the installed task is being overridden by your project file. -
./dtcw taskslistsgenerateHTMLasoverridden by scripts/generateHTML.groovy.
The copy keeps working even though it now lives in your project: its bundled
helpers and resources still resolve from the installation via dtc.scriptsHome.
To return to the shipped behaviour, simply delete your copy.
| A monkey-patched task is pinned to the version you copied. After upgrading docToolchain, re-copy the task if you want to pick up upstream changes. |
1.8.4. Security note
Project tasks are Groovy code that runs with your privileges — the same trust
level that docToolchainConfig.groovy already has, since it too is executable
Groovy. Opening someone else’s project and running dtcw runs their scripts.
Treat a project’s scripts/ directory with the same care as its config.
2. docToolchain Tasks
3. generateHTML
3.1. About This Task
Generates HTML5 from your AsciiDoc sources using AsciidoctorJ.
Output is written to build/html5/.
./dtcw4 local generateHTML
3.2. Configuration
Specify which files to render in your docToolchainConfig.groovy:
inputFiles = [
[file: 'manual.adoc', formats: ['html','pdf']],
]
3.3. Single-File HTML
To produce a single self-contained HTML file, set :data-uri: in your AsciiDoc source.
Be aware that the file can become very large.
3.4. Text-Based Diagrams
docToolchain includes the asciidoctor-diagram extension for PlantUML, ditaa, and other diagram types.
.example diagram
[plantuml, "{plantUMLDir}demoPlantUML", png]
----
class BlockProcessor
class DiagramBlock
BlockProcessor <|-- DiagramBlock
----
Use {plantUMLDir} in the image name to ensure diagrams work for both HTML and PDF output.
|
| Use a unique image name for each diagram to avoid overwriting. |
3.5. Controlling Diagram Size
Use the width attribute (pixels) or scale attribute (ratio):
[plantuml, target="{plantUMLDir}myDiagram", format=png, width=250]
[plantuml, target="{plantUMLDir}myDiagram", format=png, scale=0.75]
If Graphviz is not installed, add !pragma layout smetana as the first line of your PlantUML diagram to use the built-in Java layout engine.
|
3.6. Further Reading
4. generatePDF
4.1. About This Task
Generates PDF from your AsciiDoc sources using AsciidoctorJ PDF.
Output is written to build/pdf/.
The result looks like a typeset book, not a print-to-PDF web page.
./dtcw4 local generatePDF
4.2. Configuration
Specify which files to render in your docToolchainConfig.groovy:
inputFiles = [
[file: 'manual.adoc', formats: ['html','pdf']],
]
Add the files you want rendered with the pdf format.
4.3. Custom PDF Theme
To customize colors, fonts, headers, and footers, create a custom-theme.yml file.
-
Run
./dtcw4 local copyThemes pdfThemeto copy the bundledpdfTheme(including the exampletemplate_config/pdfTheme/custom-theme.yml) into your project. -
Reference it from your AsciiDoc file:
:pdf-themesdir: {docdir}/../pdfTheme
:pdf-theme: custom
4.4. Further Reading
5. generateSite
5.1. About This Task
When your documentation grows beyond a single document, a microsite bundles everything into a navigable website with landing page, blog, and search.
The generateSite task renders a static site from your AsciiDoc sources using docToolchain’s built-in site generator.
(Up to v3 this was jBake; v4 replaced it with a self-contained generator while keeping the same jbake--prefixed page metadata.)
./dtcw4 local generateSite
Output is written to build/microsite/output/.
5.2. Pages
The microsite is page-oriented: each AsciiDoc file becomes a page.
Add page metadata to include a page in the site (the jbake- prefix is kept for backwards compatibility):
:jbake-menu: arc42
:jbake-title: Solution Strategy
:jbake-order: 4
:jbake-type: page_toc
:jbake-status: published
:toc:
== Solution Strategy
- jbake-menu
-
The top-level menu code. Defaults to the top-level folder name (without order prefix).
- jbake-title
-
Title shown in the navigation. Defaults to the first headline.
- jbake-order
-
Sort order in the sidebar. Defaults to the numeric prefix of the filename or folder.
- jbake-type
-
Controls the template. Use
page_tocfor a page with sidebar table of contents, orpagefor full-width. - jbake-status
-
Either
draftorpublished. Files prefixed with_default todraft.
Start pages with a == level headline.
|
5.3. Configuration
Configuration follows a convention-over-configuration approach. Defaults work out of the box — configure only what you want to change.
5.3.1. Menu
Navigation Structure
-
A top-level menu with entries across the top of the page.
-
A section sidebar for each top-level menu entry.
The structure is derived from your folder layout:
src/docs/
├── 10_foo
│ ├── 10_first.adoc
│ └── 20_second.adoc
└── 20_bar
├── 10_lorem.adoc
└── 20_ipsum
├── 10_topic-A.adoc
└── 20_topic-B.adoc
Top-level folders determine menu codes (foo, bar).
Sub-folders create navigation tree nodes.
Numeric prefixes control sort order.
Configuring the Top-Level Menu
Map menu codes to display titles in your docToolchainConfig.groovy:
menu = [code1: 'Some Title 1', code2: 'Other Title 2', code3: '-']
Use '-' to hide a menu entry.
When no mapping is defined, the code itself is used as the title.
The order in the map determines the display order.
5.3.2. Links
In the right column, links are controlled by values in docToolchainConfig.groovy:
-
"Improve this doc": shown when
gitRepoUrlis set. -
"Create an issue": shown when
issueUrlis set.
5.4. Templates and Style
The bundled templates use Bootstrap 5 as their CSS framework. Templates and styles are bundled with docToolchain.
5.4.1. Branding (Fonts, Colors, Logo)
You can re-brand the microsite without copying the whole theme.
Set any of these keys in the microsite block of docToolchainConfig.groovy.
Every value is optional — leave it empty to keep the theme default.
microsite.with {
// your logo, relative to the site's asset root (assets/images)
logo = 'images/my-logo.png'
// colors — any CSS color value
colorPrimary = '#1f8a5b' // accent / brand color
colorPrimaryDark = '#155138' // darker shade used in gradients
colorLink = '#176c49' // body link color
colorInk = '#17181c' // main text color
colorBackground = '#f4f3ee' // page background
colorCard = '#fbfaf6' // card / panel background
// fonts — a CSS font-family value
fontHeading = "'Roboto', sans-serif"
fontBody = "'Open Sans', sans-serif"
fontMono = "'JetBrains Mono', monospace"
// optional: load custom web fonts (e.g. a Google Fonts stylesheet)
fontCssUrl = 'https://fonts.googleapis.com/css2?family=Roboto&family=Open+Sans&display=swap'
}
The colors override the theme’s CSS custom properties and apply to both the pages and the landing page.
For deeper changes, copy the full theme with copyThemes jBakeTheme and edit the CSS directly.
5.5. Landing Page
The microsite needs a landing page as its start page.
Run copyLandingPage to scaffold an editable copy into your project, then configure it in docToolchainConfig.groovy:
microsite.with {
landingPage = 'landingpage.gsp' // file in your theme's doc/ folder
}
The landing page is plain HTML5 styled with Bootstrap — the header and footer are added automatically.
If microsite.landingPage is not set, the site is generated without an index.html landing page.
index.gsp in src/site/templates is the internal master template, not your landing page. Put your landing-page content in src/site/doc/<landingPage> instead.
|
5.6. Blog
The microsite includes a blog.
Create posts in src/docs/blog/<year>/<post-name>.adoc:
:jbake-title: My Post Title
:jbake-date: 2025-01-15
:jbake-type: post
:jbake-tags: blog, asciidoc
:jbake-status: published
= {jbake-title}
{jbake-date}
Your content here.
5.7. Search
The microsite includes a search input field that can be linked to an external search engine.
5.8. CI/CD
Set DTC_HEADLESS=true in automated builds to skip interactive prompts (e.g., theme installation).
6. publishToConfluence
6.1. About This Task
This task takes a generated HTML file, splits it by headline, and pushes it to your instance of Confluence. This lets you use the docs-as-code approach even if your organisation insists on using Confluence as its main document repository.
|
Since 01.01.2024, Atlassian has been turning off API V1 for Confluence Cloud wherever a V2 equivalent exists. docToolchain versions from 3.1 on support API V2. If you are using an older version of docToolchain, you’ll need to upgrade to a newer version.
To enable API V2, set |
|
Currently, docToolchain only has full support for the old Confluence editor. The new editor is not fully supported yet. You can use the new editor, but you may experience some unexpected layout issues/ changes. To make use of the new editor you need to set |
6.2. Special Features
6.2.1. Easy Code Block Conversion
[source]-blocks are converted to code-macro blocks in Confluence.
Confluence supports a very limited list of languages supported for code block syntax highlighting. When specifying an unknown language, it would even display an error. Therefore, some transformation is applied.
-
If no language is given in the source block, it is explicitly set to plain text (because the default would be Java that might not always apply).
-
Some known and common AsciiDoc source languages are mapped to Confluence code block languages.
source target note json
yml
produces an acceptable highlighting
shell
bash
only a specific shell is supported
yaml
yml
different name of language
-
If the language of the source block is not supported by Confluence, it is set to plain text as fallback to avoid the error.
| Get a list of valid languages (and learn how to add others) here. |
6.2.2. Minimal Impact on Non-Techie Confluence Users
Only pages and images that changed between task runs are published, and only those changes are notified to page watchers, cutting down on 'spam'.
6.2.3. Keywords Automatically Attached as Labels
:keywords: are attached as labels to every Confluence page generated using the publishToConfluence task.
See Atlassian’s own guidelines on labels.
Several keywords are allowed, and they must be separated by commas. For example: :keywords: label_1, label-2, label3, ….
Labels (keywords) must not contain a space character. Use either '_' or '-'.
6.3. Configuration
You configure the publishToConfluence task in the file docToolchainConfig.groovy. It is located in the root of your project folder. We try to make the configuration self-explanatory, but below is some more information about each config option.
input
is an array of files to upload to Confluence with the ability to configure a different parent page for each file.
6.4. Attributes
-
file: absolute or relative path to the asciidoc generated html file to be exported -
url: absolute URL to an asciidoc generated html file to be exported -
ancestorName(optional): the name of the parent page in Confluence as string; this attribute has priority over ancestorId, but if page with given name doesn’t exist, ancestorId will be used as a fallback -
ancestorId(optional): the id of the parent page in Confluence as string; leave this empty if a new parent shall be created in the space
The following four keys can also be used in the global section below
-
spaceKey: page specific variable for the key of the confluence space to write to case sensitive! If the case is not correct, it can be that new page will be created but can’t be updated in the next run. -
subpagesForSections(optional): The number of nested sub-pages to create. Default is '1'. '0' means creating all on one page. The following migration for removed configuration can be used.-
allInOnePage = trueis the same assubpagesForSections = 0 -
allInOnePage = false && createSubpages = falseis the same assubpagesForSections = 1 -
allInOnePage = false && createSubpages = trueis the same assubpagesForSections = 2
-
-
pagePrefix(optional): page specific variable, the pagePrefix will be a prefix for the page title and it’s sub-pages use this if you only have access to one confluence space but need to store several pages with the same title - a different pagePrefix will make them unique -
pageSuffix(optional): same usage as prefix but appended to the title and it’s subpages
only 'file' or 'url' is allowed. If both are given, 'url' is ignored
ancestorId
The page ID of the parent page where you want your docs to be published. Go to this page, click Edit and the required ID will show up in the URL. Specify the ID as a string within the config file.
api
Endpoint of the confluenceAPI (REST) to be used and looks like https://[yourServer]/[context], while [context] is optional.
If you use Confluence Cloud, you can omit the context.
If you use Confluence Server, you may need to set a context, depending on your Confluence configuration.
rateLimit (since 3.2.0), The rate limit for Confluence requests. Default is 10 requests per second.
useV1Api
This feature is available for docToolchain >= 3.1 only
If you set this to false, ensure the api config is set to https://[yourCloudDomain]. (Mind no context given here)
|
If you are using Confluence Cloud, you can set this to false to use the new API V2. If you are using Confluence Server, you can set this to true to use the old API V1. If you are using Confluence Cloud and set this to true, you will get an error message, as Atlassian has been turning off API V1 since 01.01.2024.
enforceNewEditor
Atlassian is currently rolling out a new editor for Confluence. If you want to use the new editor, you can set this to true. If you are using the old editor, you can set this to false. If you are using the new editor, you may experience some unexpected layout issues/ changes, since the new editor has yet no feature parity and therefore may be incompatible.
disableToC
This boolean configuration determines whether the table of contents (ToC) is disabled on the page once uploaded to Confluence. false by default, so the ToC is active.
pagePrefix/pageSuffix
Confluence can’t handle two pages with the same name - even with different casing (lowercase, UPPERCASE, a mix).
This script matches pages regardless of case and refuses to replace a page whose name differs from an existing page only by casing.
Ideally, you should create a new Confluence space for each piece of larger documentation.
If you are restricted and can’t create new spaces, you can use pagePrefix/pageSuffix to define a prefix/suffix for the doc so that it doesn’t conflict with other page names.
pageVersionComment
Set an optional comment for the new page version in Confluence.
credentials
For security reasons it is highly recommended to store your credentials in a separate file outside the Git repository, such as in your Home folder.
To authenticate with username and API token, use: credentials = "user:${new File("/users/me/apitoken").text}" or credentials = "user:${new File("/users/me/apitoken").text}"`.bytes.encodeBase64().toString()` to …….. You can create an API-token in your profile.
|
Atlassian is deprecating unscoped (classic) API tokens.
If you receive a
|
To authenticate with username and password, use: credentials = ……
You can also set your username, password of apitoken as an environment variable. You then do the following: 1. Open the file that contains the environment variables: a. On a Mac, go to your Home folder and open the file .zprofile. 2. ….
apikey
In situations where you have to use full user authorisation because of internal Confluence permission handling, you’ll need to add the API-token in addition to the credentials.
The API-token cannot be added to the credentials because it’s used for user and password exchange.
Therefore, the API-token can be added as parameter apikey, which makes the addition of the token a separate header field with key: keyId and value of apikey.
An example (including storing of the real value outside this configuration) is: apikey = "${new File("/home/me/apitoken").text}".
bearerToken
You can pass a Confluence
Personal Access Token as the bearerToken. It is an alternative to
credentials. Do not confuse it with apiKey.
extraPageContent
If you need to prefix your pages with a warning stating that 'this is generated content', this is where you do it.
enableAttachments
If value is set to true, any links to local file references will be uploaded as attachments. The current implementation only supports a single folder, the name of which will be used as a prefix to validate whether your file should be uploaded.
If you enable this feature, and use a folder which starts with 'attachment', an adaption of this prefix is required.
pageLimit
Limits the number of pages retrieved from the server to check if a page with this name already exists.
jiraServerId Only required if you are using Jira on-premise. If you are using Jira cloud you do not need to set this value. Stores the Jira server ID that your Confluence instance is connected to. If a value is set, all anchors pointing to a Jira ticket will be replaced by the Confluence Jira macro. How-To find your Jira server ID please check the Atlassian documentation.
All files to attach will need to be linked inside the document:
link:attachment/myfolder/myfile.json[My API definition]
attachmentPrefix
Stores the expected foldername of your output directory. Default is attachment.
proxy
If you need to provide proxy to access Confluence, you can set a map with the keys host (e.g. 'my.proxy.com'), port (e.g. '1234') and schema (e.g. 'http') of your proxy.
useOpenapiMacro
If this option is present and equal to confluence-open-api or swagger-open-api then any source block marked with class openapi will be wrapped in the Elitesoft Swagger Editor macro (see Elitesoft Swagger Editor). The key depends on the version of the macro.
For backward compatibility, if this option is present and equal to true, then again the Elitesoft Swagger Editor macro will be used.
If this option is present and equal to "open-api" then any source block marked with class openapi will be wrapped in Open API Documentation for Confluence macro: (see Open API Documentation for Confluence). A download source (yaml) button is shown by default.
Using the plugin can be handled on different ways.
-
copy/paste the content of the YAML file to the plugin without linking to the origin source by using the url to the YAML file
[source.openapi,yaml]
----
\include::https://my-domain.com/path-to-yaml[]
----
-
copy/paste the content of the YAML file to the plugin without linking to the origin source by using a YAML file in your project structure:
[source.openapi,yaml]
----
\include::my-yaml-file.yaml[]
----
-
create a link between the plugin and the YAML file without copying the content into the plugin. The advantage following this way is that even in case the API specification is changed without re-generating the documentation, the new version of the configuration is used in Confluence.
[source.openapi,yaml,role="url:https://my-domain.com/path-to-yaml"]
----
\include::https://my-domain.com/path-to-yaml[]
----
6.5. CSS Styling
Some AsciiDoctor features depend on specific CSS style definitions. Unless these styles are defined, some formatting that is present in the HTML version will not be represented when published to Confluence. To configure Confluence to include additional style definitions:
-
Log in to Confluence as a space admin.
-
Go to the desired space.
-
Select Space tools > Look and Feel > Stylesheet.
-
Click Edit then enter the desired style definitions.
-
Click Save.
The default style definitions can be found in the AsciiDoc project as asciidoctor-default.css. You will most likely NOT want to include the entire thing, as some of the definitions are likely to disrupt Confluence’s layout.
The following style definitions are Confluence-compatible, and will enable the use of the built-in roles (big/small, underline/overline/line-through, COLOR/COLOR-background for the sixteen HTML color names):
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
7. exportPPT
7.1. About This Task
Exports PowerPoint slides (.pptx) as PNG images and extracts speaker notes as AsciiDoc.
./dtcw4 local exportPPT
In v4, this task uses Apache POI for rendering and works on all platforms (Linux, macOS, Windows). The v3 version was Windows-only (VBScript).
Only .pptx files are supported. Legacy .ppt format is not supported.
|
7.1.1. Generated Output
For each <name>.pptx found under your input path, the task writes:
-
slide images to
src/docs/images/ppt/<name>/slide_NNN.png(one PNG per slide), -
speaker notes to
src/docs/ppt/<name>/slide_NNN_notes.adoc(only for slides that have notes), -
a ready-to-include AsciiDoc file at
src/docs/ppt/<name>/<name>.adoc.
The generated <name>.adoc contains one section per slide, each with the slide title as a === heading, the slide image, and an include of the slide’s notes:
=== <slide title>
image::ppt/<name>/slide_001.png[<slide title>]
include::slide_001_notes.adoc[]
Include the generated <name>.adoc from your own document to embed the slides and notes.
7.2. Further Reading
8. exportExcel
8.1. About This Task
Exports Excel spreadsheets (.xlsx) to CSV and AsciiDoc tables using Apache POI.
Each worksheet is exported as both .csv and .adoc.
Formulas are evaluated and exported statically.
./dtcw4 local exportExcel
Output is written to <inputPath>/excel/[filename]/[worksheet].(adoc|csv) (by default src/docs/excel/…).
The src folder is used (not build) to preserve change history in version control.
8.2. Including Exported Data
As AsciiDoc table (preserves alignment, col-span, row-span, colors):
include::excel/Sample.xlsx/Numerical.adoc[]
As CSV:
[options="header",format="csv"] |=== include::excel/Sample.xlsx/Numerical.csv[] |===
8.3. Further Reading
-
asciidoctorj-office-extension — an alternative approach
9. downloadTemplate
9.1. About This Task
9.2. Setup and Configuration
downloadTemplate requires an existing docToolchainConfig.groovy in your project root (or the path set via DTC_CONFIG_FILE).
If the file doesn’t exist yet, create an empty one: touch docToolchainConfig.groovy.
|
9.3. Headless Mode
For unattended use (e.g., with CI/CD pipelines or LLM agents), the downloadTemplate task supports headless mode where no user input is required.
9.3.1. Using the DTC_HEADLESS Environment Variable
When DTC_HEADLESS=true is set, the task will use sensible defaults:
-
Template:
arc42 -
Language:
EN -
Help variant:
plain(without help text)
export DTC_HEADLESS=true
./dtcw4 local downloadTemplate
10. createTask
10.1. About This Task
createTask scaffolds a new project-local custom task. It writes a ready-to-edit
Groovy script — with the // @task marker already in place — into your project’s
scripts directory, so dtcw discovers and runs it without any further wiring.
./dtcw createTask exportNotion
This creates scripts/exportNotion.groovy. Run it with ./dtcw exportNotion and
see it listed via ./dtcw tasks.
10.2. Setup and Configuration
-
The task name must start with a letter and contain only letters, digits, hyphens or underscores. If omitted, the name defaults to
customTask. -
The target directory defaults to
scripts/; override it with theDTC_PROJECT_SCRIPTS_DIRenvironment variable. -
createTasknever overwrites an existing file — pick a new name or edit the existing script directly.
The generated skeleton shows how to read docToolchainConfig.groovy and reuse
docToolchain’s bundled helpers via the dtc.scriptsHome system property.
10.3. Further Reading and Resources
-
copyTask — copy an installed task to modify it
11. copyTask
11.1. About This Task
copyTask copies an installed task script into your project so you can modify it
— monkey-patching. The project copy has the same name as the installed task and
therefore overrides it: dtcw runs your copy instead of the shipped one.
./dtcw copyTask generateHTML
This copies the installed generateHTML.groovy to scripts/generateHTML.groovy
in your project. Edit it, then run ./dtcw generateHTML as usual.
11.2. Setup and Configuration
-
Pass the name of an existing installed task. Run
./dtcw tasksto see the available names. -
The copy is placed in
scripts/by default; override withDTC_PROJECT_SCRIPTS_DIR. -
copyTaskrefuses to overwrite an existing project copy.
11.3. How the Override Behaves
-
./dtcw generateHTMLprints a note to stderr that the installed task is being overridden by your project file. -
./dtcw tasksflags the task asoverridden by scripts/generateHTML.groovy. -
The copy still loads its bundled helpers and resources from the installation via
dtc.scriptsHome, so it keeps working unchanged. -
Delete the copy to fall back to the shipped task.
| A copied task is pinned to the version you copied. After upgrading docToolchain, re-copy it if you want upstream changes. |
11.4. Further Reading and Resources
-
createTask — scaffold a brand-new custom task
11.6. Solutions to Common Problems
If you are stuck, also check Stack Overflow or raise an issue on GitHub.
11.6.1. References
Q: How can I reference source code from my documentation?
Answer
Within your documents folder (default src/docs), use relative includes:
include::filename.adoc[]
For files outside the documents folder, use:
include::/home/runner/work/docToolchain/docToolchainfilename.adoc[]
To make this work in editor previews, add:
ifndef::projectRootDir[:projectRootDir: ../../../]
11.6.2. Images
Q: Why are images not shown in the preview of my editor?
Answer
Your editor does not know the imagesdir attribute.
Add this line to each file:
ifndef::imagesdir[:imagesdir: ../images]
Q: Which image format should I use?
Answer
PNG is the preferred format — all output formats support it well.
Other formats:
- SVG
-
Great for high-resolution diagrams but may not render correctly in DOCX output.
- JPG
-
Good for photos, not for diagrams (compression artifacts).
- GIF
-
Not supported by the PDF renderer.
Q: Why are my images rotated in the output?
Answer
Mobile devices store orientation in image metadata rather than rotating the image.
Fix with ImageMagick: convert -auto-orient photo.jpg photo.jpg
Or re-save the image in any editor.
11.6.3. Runtime
Q: I get Could not initialize class java.awt.GraphicsEnvironment in WSL
Answer
This is a known WSL issue related to PlantUML and font rendering.
Solutions (try in order):
-
Shut down WSL:
wsl --shutdownfrom PowerShell, then retry -
Reinstall your Java runtime
-
Use PowerShell instead of WSL
-
Use a Kroki server for diagram rendering instead of PlantUML
Make sure WSL is up-to-date: wsl --update
Q: How do I configure a proxy?
Answer
Pass proxy settings as system properties:
./dtcw4 local generateSite -Dhttp.proxyHost=proxy.example.com -Dhttp.proxyPort=3128
Q: Can I tune the JVM startup for faster v4 builds?
Answer
docToolchain v4 runs every task in a fresh, short-lived JVM (no Gradle daemon).
To make that startup cheap, the dtcw wrapper launches the v4 JVM with these
flags by default: -XX:TieredStopAtLevel=1 -XX:+UseSerialGC.
A run that lasts only seconds never recoups the cost of the C2 JIT compiler
optimising hot methods it abandons moments later. Capping the JIT at level 1
(C1) removes that wasted compilation, and SerialGC skips parallel-GC thread
setup. On a typical site this roughly halves the wall-clock time.
The flags are a default, not a hard-coded value. Override them with the
DTC_JAVA_STARTUP_OPTS environment variable:
# Disable the defaults entirely:
DTC_JAVA_STARTUP_OPTS= ./dtcw4 local generateSite
# Replace them with your own choice:
DTC_JAVA_STARTUP_OPTS="-XX:+UseParallelGC" ./dtcw4 local generateSite
For a very large documentation set whose render runs for minutes, the C2
JIT does eventually pay off. There, disabling the defaults
(DTC_JAVA_STARTUP_OPTS=) can be faster — measure both and keep the winner.
|
11.7. Useful Resources
11.7.1. Underlying Technologies
Markup
AsciiDoc
Our preferred markup language for technical docs.
-
"Asciidoctor Deep Dive Video" by Alexander Schwartz
Markdown
jBake also supports Markdown via flexmark-java.
Templates
arc42
-
arc42 — architecture documentation template
Docs as Code
Docs as Code
Static Site Generator
jBake
-
jBake — drove
generateSitein v3; v4 uses a built-in generator (MicrositeBaker) -
Docsy — the standard theme in v3; v4 ships Bootstrap 5 GSP templates
-
Bootstrap 5 — CSS framework
11.7.2. Books
| Title | Author | Language |
|---|---|---|
Anne Gentle |
English |
|
Gernot Starke, Stefan Zörner, Michael Simons, Ralf D. Müller |
English |
|
Gernot Starke, Peter Hruschka |
English |
11.8. Configuration
docToolchain uses a single Groovy configuration file for all settings.
11.8.1. Configuration File
By default, docToolchain looks for docToolchainConfig.groovy in your project root.
Overriding the Config File
Use the DTC_CONFIG_FILE environment variable:
export DTC_CONFIG_FILE=path/to/config.groovy
The config file must exist before running any task.
If it is missing, DtcConfig.load() will fail.
Run ./dtcw4 local downloadTemplate to create a default one, or create an empty docToolchainConfig.groovy manually.
|
11.8.2. Core Settings
outputPath = 'build'
inputPath = 'src/docs'
inputFiles = [
[file: 'manual.adoc', formats: ['html','pdf']],
]
imageDirs = ['images/.']
outputPath-
Base directory for all generated output.
inputPath-
Directory containing your AsciiDoc sources.
inputFiles-
List of files to process, with desired output formats (
html,pdf). imageDirs-
Directories to scan for images (relative to
inputPath).
11.8.3. Microsite Settings
microsite.with {
contextPath = '/'
title = 'My Documentation'
host = 'https://example.com'
landingPage = 'landingpage.gsp'
menu = [
about: 'About',
manual: 'User Docs',
tasks: 'Tasks',
]
}
menu-
Maps menu codes (from folder names or
:jbake-menu:attributes) to display titles. Use'-'to hide a menu entry.
11.8.4. Confluence Settings
confluence = [
api: 'https://your-wiki.atlassian.net/wiki',
spaceKey: 'MY_SPACE',
credentials: "user:${new File('/path/to/apitoken').text}",
input: [
[file: 'build/html5/manual.html', ancestorId: '123456'],
],
]
See the publishToConfluence task for all options.
11.8.5. Dynamic Configuration
Since the config file is executable Groovy, you can use dynamic values:
// From system property: ./dtcw4 local generateHTML -DmyProp=value
example = System.properties.myProp
// From environment variable
example = System.getenv("MY_VAR")
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.