Structured authoring with DITA

Before docs-as-code with Markdown, there was structured authoring, and it’s still the right tool when one source has to publish to many products, audiences and formats. Here’s a small DITA example of how I think about reuse.

i

Writing sample. I wrote this for my portfolio. “Meridian” is a fictional company, and none of this comes from an employer’s content.

Why DITA

DITA (Darwin Information Typing Architecture) is an XML standard for topic-based authoring. Instead of long documents, you write small, typed topics and assemble them with maps:

Topic type Answers Example
Concept What is it, and why does it matter? What is an API key?
Task How do I do it? Rotating an API key
Reference What are the exact details? API key permissions

Typing matters because it enforces structure. A task topic can’t wander into a three-paragraph explanation, because the schema expects prerequisites, steps and a result.

A task topic

This topic explains how to rotate an API key. It pulls the product name from a key and reuses a shared warning with a conref, so neither is ever copied by hand.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN" "task.dtd">
<task id="rotate-api-key">
  <title>Rotating an API key</title>
  <shortdesc>Replace an API key without downtime by creating a new key,
    updating your integration, and then revoking the old key.</shortdesc>
  <taskbody>
    <prereq>You need the <uicontrol>Developer admin</uicontrol> role in
      <keyword keyref="product-name"/>.</prereq>
    <steps>
      <step>
        <cmd>Go to <menucascade><uicontrol>Settings</uicontrol>
          <uicontrol>API keys</uicontrol></menucascade>.</cmd>
      </step>
      <step>
        <cmd>Click <uicontrol>Create key</uicontrol> and copy the new key.</cmd>
        <info conref="shared/warnings.dita#warnings/key-shown-once"/>
      </step>
      <step>
        <cmd>Update your integration to use the new key, and deploy it.</cmd>
      </step>
      <step audience="enterprise">
        <cmd>Ask a second admin to approve the rotation.</cmd>
        <info>Enterprise accounts require dual approval for key changes.</info>
      </step>
      <step>
        <cmd>Next to the old key, click <uicontrol>Revoke</uicontrol>.</cmd>
      </step>
    </steps>
    <result>Requests signed with the old key now fail with
      <codeph>401 invalid_api_key</codeph>.</result>
  </taskbody>
</task>

The reused pieces

The warning lives once, in a shared file. Every topic that needs it points to it with conref, so fixing it once fixes it everywhere:

<!-- shared/warnings.dita -->
<topic id="warnings">
  <title>Shared warnings</title>
  <body>
    <note id="key-shown-once" type="caution">The full key is shown only
      once. Store it in your secrets manager before you close this page.</note>
  </body>
</topic>

The map assembles topics into a deliverable and defines keys, so a rebrand is a one-line change:

<!-- developer-guide.ditamap -->
<map>
  <title>Meridian developer guide</title>
  <keydef keys="product-name">
    <topicmeta><keywords><keyword>Meridian</keyword></keywords></topicmeta>
  </keydef>
  <topicref href="concepts/api-keys.dita"/>
  <topicref href="tasks/rotate-api-key.dita"/>
  <topicref href="reference/api-key-permissions.dita"/>
</map>

One source, many outputs

A DITAVAL filter decides which audience-specific content is published. This one produces the standard edition by excluding the enterprise-only approval step:

<!-- standard.ditaval -->
<val>
  <prop att="audience" val="enterprise" action="exclude"/>
</val>

The same source then publishes to HTML, PDF or a help system through the DITA Open Toolkit or Oxygen XML. That means no copy-paste and no forked content.

How this shapes my Markdown work too

Most of my recent work is docs-as-code in Markdown, but the DITA habits carry over:

  • One topic, one job. I keep concept, task and reference content separate, even without a schema to enforce it.
  • Write once, reuse everywhere. At Kissflow I built a modular Git and Markdown architecture around reusable content blocks. It was the same idea as conrefs, with lighter tooling.
  • Structure you can check. Templates, linters and Cursor rules do for Markdown what the DTD does for DITA: they make the right structure the default.

© 2026 Akaash Amalraj · Built with Astro, written by a human, reviewed by a style guide. · llms.txt

esc