> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ensemble.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Your First Documentation

> Set up API documentation using Conductor's docs system

**Estimated Time:** 10-15 minutes
**Prerequisites:** Working Conductor project

## What You'll Learn

By the end of this guide, you'll understand how to:

* 📖 Create a `docs/` directory with auto-discovered markdown pages
* ✍️ Write markdown documentation with frontmatter
* 🎨 Customize themes and navigation via ensemble config
* 🔐 Control documentation access with triggers
* 🔄 Use Handlebars templating for dynamic content

## Understanding Documentation in Conductor

The `docs/` directory is a **first-class component directory** in Conductor, just like `agents/` and `ensembles/`. It provides:

* **Auto-discovered markdown pages** - Just add `.md` files
* **Built-in docs-serve ensemble** - Handles HTTP routing automatically
* **Multiple UI frameworks** (Stoplight, Redoc, Swagger, Scalar, RapiDoc)
* **Auto-generated navigation** from file structure

```
your-project/
├── docs/                    # First-class docs directory
│   ├── getting-started.md   # Custom page
│   └── authentication.md    # Another page
├── ensembles/               # Workflows (docs-serve is built-in)
├── agents/                  # Your agents
└── conductor.config.ts
```

<Note>
  The `docs-serve` ensemble is included in Conductor's system templates. It automatically handles routing docs to `/docs/*` paths.
</Note>

## Step 1: Create the docs/ Directory

### Initialize Your Docs

Create the docs directory with your first markdown file:

```bash theme={null}
mkdir -p docs
```

Create `docs/getting-started.md`:

```markdown theme={null}
---
title: Getting Started
description: Quick start guide for the API
order: 1
icon: 🚀
---

# Getting Started

Welcome to our API! This guide will help you make your first call.

## Base URL

```

Production: [https://api.example.com](https://api.example.com)
Development: [http://localhost:8787](http://localhost:8787)

````

## Quick Start

### 1. Get Your API Key

Sign up and generate your API key from the dashboard.

### 2. Make Your First Request

```bash
curl -X GET https://api.example.com/v1/users \
  -H "Authorization: Bearer YOUR_API_KEY"
````

### 3. Handle the Response

```json theme={null}
{
  "success": true,
  "data": [
    { "id": 1, "name": "Alice" },
    { "id": 2, "name": "Bob" }
  ]
}
```

````

### Test It Works

Start your dev server:

```bash
ensemble conductor start
````

Visit the documentation:

```bash theme={null}
curl http://localhost:8787/docs

# Or open in browser:
open http://localhost:8787/docs
```

<Note>
  You should see your markdown pages rendered along with auto-generated API documentation!
</Note>

## Step 2: Add More Documentation Pages

### Create an Authentication Page

Create `docs/authentication.md`:

````markdown theme={null}
---
title: Authentication
description: How to authenticate with the API
order: 2
icon: 🔐
---

# Authentication

All API requests require authentication via Bearer token.

## Getting a Token

1. Sign up at our dashboard
2. Navigate to API Settings
3. Generate a new API key

## Using the Token

Include your token in the Authorization header:

```bash
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://api.example.com/v1/endpoint
````

## Token Expiration

Tokens expire after 30 days. Refresh them via the dashboard.

````

### Frontmatter Options

Each markdown file can have YAML frontmatter:

| Field | Type | Description |
|-------|------|-------------|
| `title` | string | Page title (shown in nav and header) |
| `description` | string | Page description (for SEO/preview) |
| `order` | number | Navigation order (lower = first) |
| `hidden` | boolean | Hide from navigation |
| `icon` | string | Icon for navigation (emoji or icon name) |
| `category` | string | Category for grouping |

## Step 3: Customize Documentation via Ensemble Config

The `docs-serve` ensemble handles routing and configuration. To customize your documentation, you can create a custom docs ensemble:

Create `ensembles/docs-custom.yaml`:

```yaml
name: docs-custom
description: Customized documentation

trigger:
  - type: http
    paths:
      - path: /docs
        methods: [GET]
      - path: /docs/:slug
        methods: [GET]
      - path: /docs/openapi.json
        methods: [GET]
    public: true

flow:
  - name: render
    agent: docs
    config:
      title: My API Documentation
      basePath: /docs
      ui: scalar
      theme:
        primaryColor: '#1a73e8'
        darkMode: true
      nav:
        showReserved:
          agents: true
          ensembles: true
          api: true

output:
  format: html
  rawBody: ${render.output}
````

### Theme Configuration

Configure the appearance via the ensemble's `flow[].config.theme`:

```yaml theme={null}
config:
  theme:
    primaryColor: '#1a73e8'  # Your brand color
    darkMode: true
```

### Choose a UI Framework

```yaml theme={null}
config:
  ui: stoplight  # Options: stoplight, redoc, swagger, scalar, rapidoc
```

| UI          | Best For                           |
| ----------- | ---------------------------------- |
| `stoplight` | Modern, interactive docs (default) |
| `redoc`     | Clean, mobile-friendly             |
| `swagger`   | Classic Swagger UI                 |
| `scalar`    | Beautiful, customizable            |
| `rapidoc`   | Fast, lightweight                  |

## Step 4: Control Access

### Public Documentation

The default `docs-serve` uses `public: true` on the trigger:

```yaml theme={null}
trigger:
  - type: http
    path: /docs
    methods: [GET]
    public: true  # Anyone can access
```

### Authenticated Documentation

For authenticated docs, create a custom ensemble:

```yaml theme={null}
name: docs-internal
description: Internal documentation (authenticated)

trigger:
  - type: http
    path: /docs/internal
    methods: [GET]
    public: false  # Requires authentication

flow:
  - agent: docs
    config:
      title: Internal API Documentation
      basePath: /docs/internal

output:
  format: html
  rawBody: ${render.output}
```

The `public: false` setting enforces authentication. Conductor validates Bearer tokens or API keys from request headers automatically.

## Step 5: Use Handlebars Templating

### Dynamic Content

Your markdown pages support Handlebars:

```markdown theme={null}
---
title: Welcome
---

# Welcome to {{projectName}}

Current version: **{{version}}**

{{#if showBetaFeatures}}
## Beta Features

Check out our new beta features!
{{/if}}

{{#each endpoints}}
- **{{this.name}}**: {{this.description}}
{{/each}}
```

### Variables

Variables come from your configuration context. These are passed through the docs agent's config.

## Step 6: Navigation Configuration

### Navigation Groups

Organize into sections via the ensemble config:

```yaml theme={null}
config:
  nav:
    groups:
      - title: Getting Started
        icon: 🚀
        items:
          - getting-started
          - quickstart
          - installation

      - title: Guides
        icon: 📖
        items:
          - guides/*

      - title: API Reference
        icon: 📚
        items:
          - api
          - agents
          - ensembles
        collapsed: true  # Collapsed by default
```

### Reserved Sections

Conductor auto-generates sections for your agents and ensembles:

```yaml theme={null}
config:
  nav:
    showReserved:
      agents: true       # Auto-generated agents list
      ensembles: true    # Auto-generated ensembles list
      api: true          # OpenAPI reference

    reservedPosition: bottom  # top | bottom

    reservedLabels:
      agents: "AI Agents"
      ensembles: "Workflows"
      api: "API Reference"
```

## Accessing Your Documentation

```bash theme={null}
# Interactive HTML documentation
GET /docs

# Specific pages
GET /docs/getting-started
GET /docs/authentication

# OpenAPI specification
GET /docs/openapi.yaml
GET /docs/openapi.json

# Auto-generated sections
GET /docs/agents
GET /docs/ensembles
GET /docs/api
```

## Directory Structure

A well-organized docs directory:

```
docs/
├── getting-started.md     # Entry point
├── authentication.md      # Auth guide
├── guides/
│   ├── quickstart.md
│   ├── advanced.md
│   └── best-practices.md
├── reference/
│   ├── errors.md
│   └── rate-limits.md
└── tutorials/
    └── first-integration.md
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Docs Not Showing">
    **Problem:** `/docs` returns 404

    **Solutions:**

    1. Verify `docs/` directory exists with at least one `.md` file
    2. Rebuild to trigger auto-discovery:
       ```bash theme={null}
       ensemble conductor start
       ```
    3. Check logs for errors:
       ```bash theme={null}
       ensemble wrangler tail
       ```
  </Accordion>

  <Accordion title="Pages Not Appearing">
    **Problem:** Markdown pages not showing in navigation

    **Solutions:**

    1. Check frontmatter syntax (must start with `---`)
    2. Verify file extension is `.md`
    3. Check `hidden: true` isn't set in frontmatter
    4. Rebuild the project
  </Accordion>

  <Accordion title="Authentication Issues">
    **Problem:** Can't access authenticated docs

    **Solutions:**

    1. Verify trigger has `public: false`
    2. Configure auth rules in `conductor.config.ts`
    3. Test with correct headers:
       ```bash theme={null}
       curl -H "Authorization: Bearer TOKEN" \
         http://localhost:8787/docs/internal
       ```
  </Accordion>

  <Accordion title="Styling Not Applied">
    **Problem:** Theme colors not showing

    **Solutions:**

    1. Verify `theme` section in ensemble config
    2. Check hex colors include `#` prefix
    3. Clear browser cache
  </Accordion>
</AccordionGroup>

## Best Practices

### Documentation

✅ **Do:**

* Keep pages focused and scannable
* Include code examples for every endpoint
* Use frontmatter for consistent metadata
* Version your documentation with your API

❌ **Don't:**

* Write walls of text without headings
* Skip authentication documentation
* Include internal endpoints in public docs
* Forget to update docs when API changes

### Security

✅ **Do:**

* Use separate ensembles for public and internal documentation
* Configure authentication via triggers
* Sanitize examples (remove real API keys)

❌ **Don't:**

* Expose admin endpoints publicly
* Include real tokens in examples

## Summary

You've learned how to:

* ✅ Create a `docs/` directory with markdown files
* ✅ Write markdown pages with frontmatter
* ✅ Customize themes and navigation via ensemble config
* ✅ Control access with trigger configuration
* ✅ Use Handlebars for dynamic content

<Tip>
  The `docs/` directory is a first-class component in Conductor - just add your markdown files and they're automatically discovered and served!
</Tip>

## Next Steps

<CardGroup cols={2}>
  <Card title="Documentation Reference" href="/conductor/building/documentation">
    Complete configuration options
  </Card>

  <Card title="Your First Agent" href="/conductor/getting-started/your-first-agent">
    Create AI-powered agents
  </Card>

  <Card title="Your First Ensemble" href="/conductor/getting-started/your-first-ensemble">
    Orchestrate multi-agent workflows
  </Card>

  <Card title="Security & Authentication" href="/conductor/building/security-authentication">
    Secure your APIs and documentation
  </Card>
</CardGroup>
