# Document generation








katachi can generate Markdown documentation from an `architecture { }` definition.

## Basics

Configure it in `build.gradle.kts`.

```kts title="architecture-test/build.gradle.kts" {2-3}
katachi {
    // ⭐️ The fully qualified name of the property holding your `architecture { }`
    architecture = "com.example.projectArchitecture"
}
```

Once that is set, running the `katachiDocs` Gradle task generates the documentation.

```shell
./gradlew katachiDocs
```

### Example output

Take the following definition as an example.

```kt
architecture {
    title = "myapp"

    "domain".group {
        title = "Domain layer"
        summary = "App-specific behavior and the values it acts on"

        "UseCase" {
            title = "Use case"
            summary = "A single app-specific behavior that happens on a screen"
            example("GetItemListUseCase", "The list of items")
            example("SignInUseCase", "Signing in")
            layout { "core/domain" / mainSourceSet / kotlin / "com/example/core/domain/useCase" / "*UseCase".ktFile() }
            "has only an invoke method".konsist { /* ... */ }
        }

        "RepositoryInterface" {
            title = "Repository"
            summary = "The boundary where data is fetched and saved"
            layout { "core/domain" / mainSourceSet / kotlin / "com/example/core/domain/repository" / "*Repository".ktFile() }
        }
    }
}
```

<Tabs>
    <TabItem label="Directory structure">
        <FileTree>
        - build/katachi/docs/
          - README.md
          - domain/
            - README.md
            - UseCase.md
            - RepositoryInterface.md
        </FileTree>
    </TabItem>

    <TabItem label="README.md">
        ```md collapse
        # myapp documentation

        ## Document map

        ### [Domain layer](./domain/README.md)

        App-specific behavior and the values it acts on

        - [Use case](./domain/UseCase.md)
        - [Repository](./domain/RepositoryInterface.md)

        ## Domain layer

        App-specific behavior and the values it acts on

        - [Use case](./domain/UseCase.md) ... A single app-specific behavior that happens on a screen
        - [Repository](./domain/RepositoryInterface.md) ... The boundary where data is fetched and saved
        ```
    </TabItem>
    <TabItem label="domain/README.md">
        ````md collapse
        [myapp](../README.md)

        # Domain layer

        App-specific behavior and the values it acts on

        | Role | Summary |
        |---|---|
        | [Use case](./UseCase.md) | A single app-specific behavior that happens on a screen |
        | [Repository](./RepositoryInterface.md) | The boundary where data is fetched and saved |

        ## Placement in this group

        ```
        core/domain/src/main/kotlin/com/example/core/domain/
          useCase/*UseCase.kt        Use case
          repository/*Repository.kt  Repository
        ```
        ````
    </TabItem>
    <TabItem label="domain/UseCase.md">
        ```md collapse
        [myapp](../README.md) / [Domain layer](README.md)

        # Use case

        A single app-specific behavior that happens on a screen

        ## Placement

        | Path | When to use |
        |---|---|
        | `core/domain/src/main/kotlin/com/example/core/domain/useCase/*UseCase.kt` |  |

        ## Constraints

        - has only an invoke method

        ## Examples

        - `GetItemListUseCase` ... The list of items
        - `SignInUseCase` ... Signing in
        ```
    </TabItem>
    <TabItem label="domain/RepositoryInterface.md">
        ```md collapse
        [myapp](../README.md) / [Domain layer](README.md)

        # Repository

        The boundary where data is fetched and saved

        ## Placement

        | Path | When to use |
        |---|---|
        | `core/domain/src/main/kotlin/com/example/core/domain/repository/*Repository.kt` |  |
        ```
    </TabItem>
</Tabs>

The samples in katachi's GitHub repository keep actually generated documentation in `sample/<name>/docs/`. See them for concrete examples as well.

<LinkCard title="katachi samples" href="https://github.com/TBSten/katachi/tree/main/sample" />

## Output directory

By default the documentation is generated under `build/katachi/docs/`.

The destination can be changed by setting `katachi.processors.docs.outputDir` in `build.gradle.kts`.

```kts {6}
katachi {
    architecture = "com.example.projectArchitecture"

    processors {
        docs {
            outputDir = rootProject.layout.projectDirectory.dir("docs/architecture")
        }
    }
}
```

## Generated files

These are the files generated from an `architecture { }` definition.

### Without groups

<FileTree>
- \<output directory>/
  - README.md
  - \<Role>.md
</FileTree>

### With groups

<FileTree>
- \<output directory>/
  - README.md
  - \<Role>.md
  - \<group>/
    - README.md
    - \<Role>.md
    - \<nested group>/
      - README.md
      - \<Role>.md
</FileTree>

Groups can nest, and a nested group is generated below the directory of its parent group.

File and directory names are decided by the **identifier** (`UseCase` in `"UseCase" { }`, `domain` in `"domain".group { }`), not by `title`. Changing `title` does not change the file name.

## Properties used to generate the documentation

The documentation is generated from the properties you set on Roles and groups.

### Role

| Property | What it becomes in the generated documentation | Pages it is used on |
|---|---|---|
| [`title`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-role-scope/title.html) | The heading of the Role's page. Defaults to the Role's identifier | `<Role>.md`, and the link text in the index and listings |
| [`summary`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-role-scope/summary.html) | The single line that goes in the listing table | `<Role>.md`, the parent's `README.md` |
| [`description`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-role-scope/description.html) | The body of the Role's page. The Markdown you write goes in as is, newlines included. katachi adds no structure of its own, so **the headings inside are yours to choose** | `<Role>.md` |
| [`example(name, description)`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-role-scope/example.html) | A concrete example. Call it once per example; they appear **in the order you called them** | `## Examples` in `<Role>.md` |
| [`documented`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-role-scope/documented.html) | Set to `false` to keep it out of the documentation. It only stops being documented -- **it still takes part in `assert()` and the other checks** | --- |

<CodeComparison>
    <CodeComparison.Panel label="Role definition">
        ```kt
        "UseCase" {
            title = "UseCase"
            summary = "A single app-specific behavior that happens on a screen"
            description = """
                A UseCase is a class representing one app-specific behavior.
            """.trimIndent()

            example("GetItemListUseCase", "Fetches the list of items")
            example("SignInUseCase", "Signs in")

            layout {
                "src/main/kotlin/com/example/useCase" /
                    "*UseCase".ktFile()
            }

            "has only an invoke method".konsist { /* ... */ }
        }
        ```
    </CodeComparison.Panel>
    <CodeComparison.Panel label="Generated Markdown">
        ```md title="UseCase.md"
        [Architecture](README.md)                    ← breadcrumb

        # UseCase                                      ← title

        A single app-specific behavior that happens on a screen  ← summary

        A UseCase is a class representing one app-specific behavior.  ← description

        ## Placement                                    ← layout { }

        | Path | When to use |
        |---|---|
        | `src/main/kotlin/com/example/useCase/*UseCase.kt` |  |

        ## Constraints                                        ← the name of konsist { }

        - has only an invoke method

        ## Examples                                          ← example()

        - `GetItemListUseCase` ... Fetches the list of items
        - `SignInUseCase` ... Signs in
        ```
    </CodeComparison.Panel>
</CodeComparison>

### group

A group takes the same four properties a Role does. **Only `example()` is missing.**

| Property | What it becomes in the generated documentation | Pages it is used on |
|---|---|---|
| [`title`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-group-scope/title.html) | The heading of the group's README. Defaults to the group's identifier | `README.md`, `<group>/README.md` |
| [`summary`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-group-scope/summary.html) | The single line in the parent's document map and in the group's section | `README.md`, `<group>/README.md` |
| [`description`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-group-scope/description.html) | The body of the group's README | `<group>/README.md` |
| [`documented`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-group-scope/documented.html) | Set to `false` to keep the whole group out of the documentation. It still takes part in the checks | --- |

<details>
    <summary>Careful: documented = false takes the group's contents out with it</summary>

    A group with `documented = false` **takes its Roles and nested groups out of the documentation along with it,** whatever those Roles write for themselves.

    ```kt
    "build".group {
        documented = false
        "VersionCatalog" { }   // leaves the documentation together with the group
    }
    ```

    The value itself is not copied onto the Roles and groups inside (each keeps what it wrote). A processor of your own that reads this value should walk up `Role.groupPath` and look at the parent groups' values too.

</details>

<CodeComparison>
    <CodeComparison.Panel label="group definition">
        ```kt
        "domain".group {
            title = "Domain layer"
            summary = "App-specific behavior and the values it acts on"
            description = """
                The layer that depends on neither the screens nor the storage.
            """.trimIndent()

            "UseCase" {
                title = "Use case"
                summary = "A single app-specific behavior that happens on a screen"
                layout { "src/main/kotlin/com/example/domain/useCase" / "*UseCase".ktFile() }
            }

            "RepositoryInterface" {
                title = "Repository"
                summary = "The boundary where data is fetched and saved"
                layout { "src/main/kotlin/com/example/domain/repository" / "*Repository".ktFile() }
            }
        }
        ```
    </CodeComparison.Panel>
    <CodeComparison.Panel label="Generated Markdown">
        ````md title="domain/README.md"
        [Architecture](../README.md)                  ← breadcrumb

        # Domain layer                                  ← title

        App-specific behavior and the values it acts on  ← summary

        The layer that depends on neither the screens nor the storage.  ← description

        | Role | Summary |                                 ← title and summary of the Roles inside
        |---|---|
        | [Use case](./UseCase.md) | A single app-specific behavior that happens on a screen |
        | [Repository](./RepositoryInterface.md) | The boundary where data is fetched and saved |

        ## Placement in this group                           ← layout { } of the Roles inside

        ```
        src/main/kotlin/com/example/domain/
          useCase/*UseCase.kt        Use case
          repository/*Repository.kt  Repository
        ```
        ````
    </CodeComparison.Panel>
</CodeComparison>

### Top page

The heading and description of the top page (the `README.md` right under the output directory) are set by writing `title` and `description` directly inside `architecture { }`.

| Property | What it becomes in the generated documentation | Pages it is used on |
|---|---|---|
| [`title`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-architecture-scope/title.html) | The heading of the top page | `README.md`, the breadcrumb of every page |
| [`description`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-architecture-scope/description.html) | The body right under the heading | `README.md` |

<CodeComparison>
    <CodeComparison.Panel label="architecture definition">
        ```kt
        val projectArchitecture = architecture {
            title = "myapp"
            description = """
                The file layout of myapp.

                myapp is designed on top of **MVVM * Clean Architecture**.
            """.trimIndent()

            "domain".group {
                title = "Domain layer"
                summary = "App-specific behavior and the values it acts on"
                "UseCase" { /* ... */ }
            }
        }
        ```
    </CodeComparison.Panel>
    <CodeComparison.Panel label="Generated Markdown">
        ```md title="README.md"
        # myapp documentation

        The file layout of myapp.

        myapp is designed on top of **MVVM * Clean Architecture**.

        ## Document map

        ### [Domain layer](./domain/README.md)

        App-specific behavior and the values it acts on
        ...
        ```
    </CodeComparison.Panel>
</CodeComparison>

### Custom sections

To add your own sections to the documentation on top of the ones provided by default, such as the title, define a section with [`documentSection()`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/document-section.html).

Declare a section with `documentSection("heading")`, and create a property to write it through with `by`.

```kt
val TestPolicy = documentSection("Test policy")
var MetadataScope.testPolicy by TestPolicy
```

<details>
    <summary>Nesting sections</summary>

    Sections can be nested. Declare the child on its parent section, as in `TestPolicy.documentSection("Unit tests")`.
    **The heading level follows from the depth.** The top level is `##`, and each level down adds one `#`.
    Even if the parent has no body, its heading still appears when a child has one.

    <CodeComparison>
        <CodeComparison.Panel label="Section definition">
            ```kt
            val TestPolicy = documentSection("Test policy")
            var MetadataScope.testPolicy by TestPolicy

            val UnitTest = TestPolicy.documentSection("Unit tests")
            var MetadataScope.unitTest by UnitTest

            val projectArchitecture = architecture {
                "UseCase" {
                    title = "Use case"
                    summary = "A single app-specific behavior that happens on a screen"
                    example("SignInUseCase", "Signing in")
                    layout { "src/main/kotlin/com/example/useCase" / "*UseCase".ktFile() }

                    unitTest = "Replace the repository with a fake and check the return value."
                }
            }
            ```
        </CodeComparison.Panel>
        <CodeComparison.Panel label="Generated Markdown">
            ```md title="UseCase.md"
            [Architecture](README.md)

            # Use case

            A single app-specific behavior that happens on a screen

            ## Placement

            | Path | When to use |
            |---|---|
            | `src/main/kotlin/com/example/useCase/*UseCase.kt` |  |

            ## Examples

            - `SignInUseCase` ... Signing in

            ## Test policy                                 ← no body, but shown because a child has one

            ### Unit tests                                 ← one level down, so ###

            Replace the repository with a fake and check the return value.
            ```
        </CodeComparison.Panel>
    </CodeComparison>

    Custom sections come **after the built-in sections (`## Placement` / `## Constraints` / `## Examples`)**, in the order they are written in the definition.

</details>

## Summary

- Documentation is created by setting properties such as title, summary, description, and example in the architecture definition.

## Next steps

- [Generating code from a template](/katachi/guides/generate-code-from-template/) ... Learn how to generate code, rather than documentation, from the same definition.
- [ArchitectureProcessor and customizing it](/katachi/guides/processor/) ... Document generation is one ArchitectureProcessor too. Learn how to produce other outputs of your own.