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

# Template Variables

Define and use template variables to create dynamic, personalized documentation content.

## Overview

Template variables let you personalize documentation content for each reader. Define variables in your `docs.json`, reference them in MDX pages with `{{variable_name}}` syntax, and readers can switch values using the variable selector in the rendered site.

Variables are resolved at render time using a layered priority system, so authenticated users, URL parameters, and local selections all work seamlessly together.

## Variable Types

HolyDocs supports four variable types:

| Type | Description | Example Use |
|---|---|---|
| `string` | Free-text input with a default value | API base URL, project name |
| `select` | Dropdown with predefined options | Language, SDK, region |
| `secret` | Masked input (never persisted server-side) | API keys, tokens |
| `computed` | Derived from other variables via expression | Full endpoint URL |

## Defining Variables

Add a `variables` array to your `docs.json`:

```json
{
  "variables": [
    {
      "name": "sdk",
      "type": "select",
      "label": "SDK",
      "description": "Your preferred SDK language",
      "defaultValue": "javascript",
      "options": ["javascript", "python", "go", "ruby"]
    },
    {
      "name": "api_base",
      "type": "string",
      "label": "API Base URL",
      "defaultValue": "https://api.example.com"
    },
    {
      "name": "api_key",
      "type": "secret",
      "label": "API Key",
      "description": "Your personal API key (stored locally, never sent to our servers)"
    },
    {
      "name": "endpoint",
      "type": "computed",
      "label": "Users Endpoint",
      "expression": "{{api_base}}/v1/users"
    }
  ]
}
```

### Variable Properties

| Property | Type | Required | Description |
|---|---|---|---|
| `name` | string | Yes | Unique identifier used in `{{name}}` syntax |
| `type` | `string` \| `select` \| `secret` \| `computed` | Yes | Variable type |
| `label` | string | No | Display label in the variable switcher UI |
| `description` | string | No | Help text shown below the input |
| `defaultValue` | string | No | Initial value before user interaction |
| `options` | string[] | Only for `select` | Available choices for the dropdown |
| `expression` | string | Only for `computed` | Expression that can reference other variables |

## Using Variables in MDX

Reference any defined variable with double-brace syntax:

````mdx
## Authentication

All API requests require a Bearer token. Pass your API key in the
`Authorization` header:

{{curly_open}}{{curly_open}}curly syntax note: use double braces{{curly_close}}{{curly_close}}

```bash
curl -H "Authorization: Bearer {{api_key}}" \
  {{api_base}}/v1/users
```

The {{sdk}} SDK provides a helper for this:
````

When rendered, `{{api_key}}` and `{{api_base}}` are replaced with the reader's selected values in real time.

Variables work inside code blocks, inline code, headings, and regular text. They are resolved before the MDX pipeline processes the page, so they work anywhere in your content.

## Variable Switcher UI

When variables are defined, a floating variable panel appears on the rendered doc site. Readers can:

- Select values from dropdowns (for `select` variables)
- Type custom values (for `string` variables)
- Enter secrets that are stored only in their browser (for `secret` variables)
- See computed values update automatically

Selections persist in the reader's browser via `localStorage`, so they carry across page navigations and return visits.

## Computed Variables

Computed variables derive their value from other variables using expressions. This avoids duplication and keeps content consistent:

```json
{
  "name": "install_command",
  "type": "computed",
  "expression": "npm install @{{org_name}}/{{package_name}}"
}
```

Computed expressions can reference any other variable (including other computed variables). HolyDocs resolves them in dependency order.

Circular references between computed variables will result in a build error. For example, if variable `a` references `b` and `b` references `a`, the build will fail with a clear error message.

## Resolution Priority

Variables are resolved using a layered system. Higher layers override lower ones:

**Authenticated user context (highest)**

If the reader is authenticated, user properties like `name`, `email`, and `groups` are available as variables automatically. These take the highest priority.
  **URL query parameters**

Pass variable values via URL: `?sdk=python&api_base=https://staging.example.com`. Useful for sharing pre-configured links.
  **User local selections**

Values the reader has set in the variable switcher, stored in `localStorage`.
  **Project defaults (lowest)**

The `defaultValue` from your `docs.json` variable definitions.

## Environment Overrides

Override variable defaults per environment. This is useful when staging and production use different API endpoints:

```json
{
  "variables": [
    {
      "name": "api_base",
      "type": "string",
      "defaultValue": "https://api.example.com"
    }
  ],
  "environments": [
    {
      "name": "staging",
      "branchPattern": "staging/*",
      "variableOverrides": {
        "api_base": "https://staging-api.example.com"
      }
    }
  ]
}
```

## Authenticated User Variables

When authentication is enabled on your doc site, user properties are available as variables without defining them in `docs.json`:

| Variable | Description |
|---|---|
| `{{user.name}}` | Authenticated user's display name |
| `{{user.email}}` | Authenticated user's email address |
| `{{user.groups}}` | Comma-separated list of the user's access groups |

```mdx
Welcome back, {{user.name}}! Your account email is {{user.email}}.
```

## Conditional Content with Variables

Combine variables with the built-in `Tabs` component to show different content based on context:

````mdx
<Tabs>
  <Tab title="JavaScript">
    ```javascript
    import { Client } from '@example/sdk';
    const client = new Client('{{api_key}}');
    const users = await client.users.list();
    ```
  </Tab>
  <Tab title="Python">
    ```python
    from example_sdk import Client
    client = Client("{{api_key}}")
    users = client.users.list()
    ```
  </Tab>
</Tabs>
````

## Sharing Pre-Configured Links

Append variable values as query parameters to share documentation with specific values pre-filled:

```
https://docs.yourcompany.com/quickstart?sdk=python&api_base=https://eu.api.example.com
```

This is especially useful for onboarding flows where you want to link users directly to docs with their specific configuration.

## Best Practices

**Use descriptive variable names**

Prefer `api_base_url` over `url` and `organization_name` over `name`. Clear names make your MDX content self-documenting.
  **Always set defaultValue for non-secret variables**

Without defaults, unresolved variables render as empty strings. Set sensible defaults so the docs read well even before a reader interacts with the variable switcher.
  **Keep secrets client-side only**

Secret variables are stored exclusively in the reader's browser. They are never sent to HolyDocs servers or included in build output.
  **Use computed variables to reduce duplication**

If the same derived value appears in multiple places (like a full API endpoint), define it as a computed variable rather than repeating the expression.