APM

>Agent Skill

@microsoft/doc-writer

skilldevelopment

Guidelines for producing accurate and maintainable documentation for the Aspire documentation site. Use when writing or updating user guides, integration docs, tutorials, or any content on aspire.dev.

documentation
apm::install
$apm install @microsoft/doc-writer
apm::skill.md
---
name: doc-writer
description: Guidelines for producing accurate and maintainable documentation for the Aspire documentation site. Use when writing or updating user guides, integration docs, tutorials, or any content on aspire.dev.
---

# Documentation Writer Skill

This skill provides guidelines for AI coding agents to help maintainers produce accurate and easy-to-maintain documentation for the Aspire project. The aspire.dev repository is the official documentation site for Aspire, and this skill helps ensure consistent, high-quality documentation.

## Documentation Overview

### Site Structure

**Location**: `src/frontend/src/content/docs/`  
**Audience**: Developers using Aspire for cloud-native application development  
**Format**: Astro with MDX files  
**Build System**: Astro (static site generator with Starlight theme)

### Documentation Categories

```
src/frontend/src/content/docs/
├── index.mdx                    # Landing page
├── get-started/                 # Getting started guides
│   ├── prerequisites.mdx
│   ├── install-cli.mdx
│   ├── first-app.mdx
│   └── ...
├── app-host/                    # AppHost documentation
├── architecture/                # Architecture concepts
├── dashboard/                   # Aspire Dashboard docs
├── deployment/                  # Deployment guides
├── diagnostics/                 # Diagnostics and telemetry
├── extensibility/               # Extensibility guides
├── fundamentals/                # Core concepts
├── integrations/                # Integration documentation
│   ├── ai/                      # AI integrations
│   ├── caching/                 # Caching integrations
│   ├── cloud/                   # Cloud integrations
│   ├── compute/                 # Compute integrations
│   ├── databases/               # Database integrations
│   ├── frameworks/              # Framework integrations
│   ├── messaging/               # Messaging integrations
│   ├── observability/           # Observability integrations
│   ├── reverse-proxies/         # Reverse proxy integrations
│   └── security/                # Security integrations
├── reference/                   # API reference
├── testing/                     # Testing guides
└── whats-new/                   # Release notes
```

## Astro and MDX Conventions

### Frontmatter

Every documentation file requires frontmatter:

```yaml
---
title: Page Title
description: A brief summary of the page content (required for SEO)
---
```

Optional frontmatter fields:
- `next: false` - Disable "Next page" link for terminal pages
- Custom metadata as needed by Starlight theme

### Required Imports

Import Starlight components at the top of your MDX file:

```tsx
import { Aside, CardGrid, LinkCard, Steps, Tabs, TabItem, Icon, FileTree } from '@astrojs/starlight/components';
```

Additional commonly used imports:

```tsx
import { Kbd } from 'starlight-kbd/components'
import LearnMore from '@components/LearnMore.astro';
import PivotSelector from '@components/PivotSelector.astro';
import Pivot from '@components/Pivot.astro';
import ThemeImage from '@components/ThemeImage.astro';
import InstallPackage from '@components/InstallPackage.astro';
import InstallDotNetPackage from '@components/InstallDotNetPackage.astro';
import AsciinemaPlayer from '@components/AsciinemaPlayer.astro';
import Badge from '@astrojs/starlight/components/Badge.astro';
import Image from 'astro:assets';
```

### Component Usage

#### Aside (Callouts)

Use for tips, notes, cautions, and warnings:

```mdx
<Aside type="tip" title="Pro Tip">
This is a helpful tip for users.
</Aside>

<Aside type="note">
Important information users should be aware of.
</Aside>

<Aside type="caution">
Proceed with care - this may have unexpected consequences.
</Aside>

<Aside type="danger">
Critical warning - this could cause data loss or security issues.
</Aside>
```

#### Steps

Use for sequential instructions:

```mdx
<Steps>

1. First step with explanation

    ```bash title="Run this command"
    aspire new aspire-starter
    ```

2. Second step

3. Third step

</Steps>
```

#### Tabs/TabItem

Use for language or platform-specific content:

```mdx
<Tabs>
<TabItem label="CLI">

```bash
aspire run
```

</TabItem>
<TabItem label="Visual Studio">

Press F5 to start debugging.

</TabItem>
</Tabs>
```

#### Pivot/PivotSelector

Use for programming language selection that persists across page:

```mdx
<PivotSelector
    title="Select your programming language"
    key="lang"
    options={[
        { id: "csharp", title: "C#" },
        { id: "python", title: "Python" },
    ]}
/>

<Pivot id="csharp">
C# specific content here.
</Pivot>

<Pivot id="python">
Python specific content here.
</Pivot>
```

#### CardGrid and LinkCard

Use for navigation and feature highlights:

```mdx
<CardGrid>
<LinkCard
    title="Getting Started"
    description="Build your first Aspire app"
    href="/get-started/first-app/"
/>
<LinkCard
    title="Integrations"
    description="Explore available integrations"
    href="/integrations/"
/>
</CardGrid>
```

### Code Blocks

Always include a descriptive title:

```mdx
```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var api = builder.AddProject<Projects.Api>("api");

// After adding all resources, run the app...
builder.Build().Run();
```
```

For JSON configuration:

```mdx
```json title="JSON — appsettings.json"
{
  "ConnectionStrings": {
    "mydb": "Host=localhost;Database=mydb"
  }
}
```
```

### Package Installation Components

For hosting packages:

```mdx
<InstallPackage package="Aspire.Hosting.Redis" />
```

For client/library packages:

```mdx
<InstallDotNetPackage package="Aspire.StackExchange.Redis" />
```

## Integration Documentation

### File Location

Place integration docs in the appropriate category folder under `src/frontend/src/content/docs/integrations/`:

| Category | Folder | Examples |
|----------|--------|----------|
| AI/ML | `ai/` | Ollama, Azure OpenAI |
| Caching | `caching/` | Redis, Garnet, Valkey |
| Cloud | `cloud/` | Azure, AWS services |
| Compute | `compute/` | Docker, Kubernetes |
| Databases | `databases/` | PostgreSQL, SQL Server, MongoDB |
| Frameworks | `frameworks/` | Python, Rust, Orleans |
| Messaging | `messaging/` | RabbitMQ, Kafka |
| Observability | `observability/` | OpenTelemetry, Prometheus |
| Reverse Proxies | `reverse-proxies/` | YARP |
| Security | `security/` | Keycloak |

### Integration Documentation Structure

#### For Hosting-Only Integrations

```mdx
---
title: [Technology] integration
description: Learn how to use the [Technology] integration with Aspire.
---

import { Aside } from '@astrojs/starlight/components';
import InstallPackage from '@components/InstallPackage.astro';
import Image from 'astro:assets';

import techIcon from "@assets/icons/technology.svg";

<Image src={techIcon} alt="Technology logo" width={100} height={100} style="float: left; margin-right: 1rem;" data-zoom-off />

Brief description of the technology and what the integration enables.

## Hosting integration

<InstallPackage package="Aspire.Hosting.Technology" />

### Add [Technology] resource

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

var tech = builder.AddTechnology("tech");

// After adding all resources, run the app...
builder.Build().Run();
```

### Configuration options

Describe available configuration methods and options.

## See also

- [Official Technology documentation](https://...)
- [Related Aspire documentation](/path/to/related/)
```

#### For Hosting + Client Integrations

Include both hosting and client sections:

```mdx
## Hosting integration

<InstallPackage package="Aspire.Hosting.Technology" />

### Add [Technology] resource

[Hosting examples...]

### Hosting integration health checks

[Health check information if applicable...]

## Client integration

<InstallDotNetPackage package="Aspire.Technology" />

### Add [Technology] client

```csharp title="C# — Program.cs"
builder.AddTechnologyClient("tech");
```

### Add keyed [Technology] client

```csharp title="C# — Program.cs"
builder.AddKeyedTechnologyClient("tech");
```

For more information, see [.NET dependency injection: Keyed services](https://learn.microsoft.com/dotnet/core/extensions/dependency-injection#keyed-services).

### Configuration

#### Connection strings

The connection name must match the resource name defined in the AppHost.

#### Configuration providers

```json title="JSON — appsettings.json"
{
  "Aspire": {
    "Technology": {
      "myconnection": {
        "Option1": "value"
      }
    }
  }
}
```

### Client integration health checks

[Health check information...]

### Observability and telemetry

[Logging and tracing information...]

## See also

- [Official documentation](https://...)
```

### Community Toolkit Integrations

For integrations from the [Aspire Community Toolkit](https://github.com/CommunityToolkit/Aspire), add the badge at the top:

```mdx
import Badge from '@astrojs/starlight/components/Badge.astro';

<Badge text="⭐ Community Toolkit" variant="tip" size="large" />
```

## Updating Navigation

After creating documentation, update the sidebar configuration:

### Location

Edit `src/frontend/config/sidebar/sidebar.topics.ts` (or the appropriate topic file)

### Adding Entries

Add entries to the appropriate section in alphabetical order:

```typescript
{ label: "Technology Name", slug: "integrations/category/technology" }
```

For collapsed sections with children:

```typescript
{
  label: "Technology Name",
  collapsed: true,
  items: [
    { label: "Overview", slug: "integrations/category/technology" },
    { label: "Advanced", slug: "integrations/category/technology-advanced" },
  ]
}
```

### Update Integration Links

After adding integration documentation, run the update-integrations prompt to ensure the integration is indexed:

```
.github/prompts/update-integrations.prompt.md
```

## Writing Style Guidelines

### Voice and Tone

- Use **second person** ("you") when addressing the reader
- Use **active voice** ("Create a resource" not "A resource is created")
- Use **imperative mood** for instructions ("Call the method" not "You should call the method")
- Be concise but complete
- Be professional but approachable

### Terminology

Use consistent terminology throughout:

| Preferred | Avoid |
|-----------|-------|
| Aspire | .NET Aspire (except in formal/legal contexts) |
| AppHost | App Host, app host |
| resource | component (for AppHost resources) |
| integration | connector, plugin |

### Inclusive Language

- Use inclusive, accessible language
- Avoid assumptions about the reader's background
- Use gender-neutral pronouns (they/them) or rewrite to avoid pronouns
- Avoid ableist language (e.g., "blind to", "crippled by")
- Use people-first language when discussing disabilities

### International Considerations

- Write dates as "January 15, 2025" not "1/15/25"
- Specify time zones when referencing specific times
- Use diverse, international examples
- Avoid idioms and culturally-specific references

## Icons and Images

### Icon Location

Place icons in `src/frontend/src/assets/icons/`

### Icon Usage

```mdx
import Image from 'astro:assets';
import techIcon from "@assets/icons/technology.svg";

<Image
    src={techIcon}
    alt="Technology logo"
    width={100}
    height={100}
    style="float: left; margin-right: 1rem;"
    data-zoom-off
/>
```

For light/dark theme variants:

```mdx
import ThemeImage from '@components/ThemeImage.astro';

<ThemeImage
    lightSrc={techIconLight}
    darkSrc={techIconDark}
    alt="Technology logo"
    width={100}
    height={100}
/>
```

### Terminal Recordings (Asciinema)

For CLI demonstrations, use asciinema recordings (`.cast` files) instead of static code blocks. These provide an interactive, playable terminal experience that better demonstrates command output and timing.

#### Existing Recordings

Recordings are stored in `src/frontend/public/casts/`. Check for existing recordings before creating new ones:

- `aspire-version.cast` - Shows `aspire --version` command
- `aspire-new.cast` - Shows project creation with `aspire new`
- `aspire-run.cast` - Shows running an Aspire app
- `aspire-help.cast` - Shows CLI help output
- `mcp-init.cast` - Shows MCP initialization

#### Using AsciinemaPlayer

```mdx
import AsciinemaPlayer from '@components/AsciinemaPlayer.astro';

<AsciinemaPlayer
  src="/casts/aspire-new.cast"
  poster="npt:0:01"
  rows={15}
  autoPlay={false}
/>
```

**Common props**:
- `src`: Path to the `.cast` file (relative to `public/`)
- `rows`: Terminal height in rows (default: 15)
- `poster`: Frame to show before playback (e.g., `"npt:0:01"` = 1 second in)
- `autoPlay`: Whether to auto-play (default: false)
- `loop`: Whether to loop playback (default: true)
- `speed`: Playback speed multiplier (default: 1.5)
- `idleTimeLimit`: Max idle time between commands (default: 1.5s)

#### Creating New Recordings with Hex1b CLI

Use the Hex1b CLI tool to create new terminal recordings and screenshots. Install it first if needed:

```bash
dotnet tool install -g Hex1b.Tool
```

Refer to the **hex1b skill** for the full command reference. Common workflow:

1. Start a terminal session:
   ```bash
   dotnet hex1b terminal start -- bash
   # Note the terminal ID from the output
   ```

2. Send commands and wait for output:
   ```bash
   dotnet hex1b keys <id> --text "aspire run"
   dotnet hex1b keys <id> --key Enter
   dotnet hex1b assert <id> --text-present "Ready" --timeout 30
   ```

3. Record a session:
   ```bash
   dotnet hex1b capture recording start <id> --output session.cast
   # ... interact with the terminal ...
   dotnet hex1b capture recording stop <id>
   ```

4. Capture output as SVG (for screenshots) or text:
   ```bash
   dotnet hex1b capture screenshot <id> --format svg --output screenshot.svg
   dotnet hex1b capture screenshot <id> --format text --output output.txt
   ```

5. Stop the terminal when done:
   ```bash
   dotnet hex1b terminal stop <id>
   ```

#### When to Use Recordings vs Code Blocks

| Content Type | Recommendation |
|--------------|----------------|
| CLI command with dynamic output | Asciinema recording |
| Simple one-liner command | Code block |
| Interactive terminal session | Asciinema recording |
| Configuration files | Code block |
| Long-running process (aspire run) | Asciinema recording |

## Testing Your Documentation

Before submitting documentation:

1. **Build locally**: Run the site locally to verify rendering
2. **Check links**: Ensure all internal and external links work
3. **Validate code**: Test all code examples compile and run using `aspire run`
4. **Review formatting**: Verify components render correctly
5. **Check navigation**: Confirm sidebar entries are correct

### Installing the Aspire CLI

Ensure you have the appropriate version of the Aspire CLI installed for testing. The version depends on what you're documenting:

#### GA/Stable Builds (Default)

For documenting released features:

```bash
# Linux/macOS
curl -sSL https://aspire.dev/install.sh | bash

# Windows (PowerShell)
irm https://aspire.dev/install.ps1 | iex
```

For complete installation instructions, see [Install Aspire CLI](/get-started/install-cli/).

#### Nightly/Dev Builds

For documenting features on the main branch that haven't been released yet:

```bash
# Linux/macOS
curl -sSL https://aspire.dev/install.sh | bash -s -- --quality dev

# Windows (PowerShell)
iex "& { $(irm https://aspire.dev/install.ps1) } -Quality 'dev'"
```

You can also access this via the download icon on aspire.dev and selecting "Dev" from the Channel selector.

#### PR Builds

For documenting features in specific pull requests before they merge:

1. Go to the PR in [dotnet/aspire](https://github.com/dotnet/aspire)
2. Find the build artifacts in the Checks/Actions section
3. Download and install the CLI from the PR artifacts

This is useful for getting an early start on documentation for upcoming features.

#### Staging Builds

For prerelease builds from the current release branch:

```bash
# Linux/macOS
curl -sSL https://aspire.dev/install.sh | bash -s -- --quality staging

# Windows (PowerShell)
iex "& { $(irm https://aspire.dev/install.ps1) } -Quality 'staging'"
```

### Running Locally

The documentation site can be run locally using the Aspire CLI:

```bash
aspire run
```

<Aside type="tip">
When testing code examples that add integration packages, use `aspire add <package-name>` rather than `dotnet add package`. The Aspire CLI automatically adds packages to the correct project.
</Aside>

Use the Aspire MCP tools to check the status of resources:

```
mcp_aspire_list_resources
```

Navigate to the `frontend` resource endpoint to view the documentation site.

## Cross-Referencing

### Link to Related Documentation

Use standard Markdown links with absolute paths from the docs root:

```markdown
For more information, see [Service Defaults](/fundamentals/service-defaults/).
```

### Reference NuGet Packages

Use the 📦 emoji with links:

```markdown
Install the [📦 Aspire.Hosting.Redis](https://nuget.org/packages/Aspire.Hosting.Redis) package.
```

### See Also Sections

End pages with a "See also" section linking to:
- Official technology documentation
- Related Aspire documentation
- NuGet package pages
- GitHub repositories (when applicable)

## Localization

The aspire.dev site supports multiple languages. When creating new content:

1. Create content in the default (English) location first
2. Localized versions are managed separately in their respective folders (e.g., `fr/`, `de/`, `ja/`)
3. Do not manually translate content - follow the project's localization workflow

## Common Patterns

### Prerequisites Notes

```mdx
<Aside type="note" title="Prerequisites">
Before continuing, ensure you have:
- [Installed the Aspire CLI](/get-started/install-cli/)
- [Completed the prerequisites](/get-started/prerequisites/)
</Aside>
```

### Version-Specific Information

```mdx
<Aside type="caution">
This feature requires Aspire version 9.0 or later.
</Aside>
```

### Feature Flags or Experimental Features

```mdx
<Aside type="danger" title="Experimental">
This feature is experimental and may change in future releases.
</Aside>
```

## Mermaid Diagrams

The site supports Mermaid diagrams for architecture visualization:

```mdx
```mermaid
architecture-beta
  service api(logos:dotnet)[API service]
  service frontend(aspire:blazor)[Blazor front end]

  frontend:L --> R:api
```
```

Use the `architecture-beta` diagram type for service architecture diagrams.

## Common Documentation Issues (From PR Feedback)

The following rules are derived from common feedback patterns in documentation PRs. Following these rules will help avoid common mistakes.

### General Writing Rules

1. **Remove unnecessary commas**: Don't write "Now, that you have..." - write "Now that you have..."
2. **Avoid casual language**: Don't include phrases like "treat yourself to a coffee" or other informal asides in documentation
3. **Remove unused imports**: Don't import components that aren't used in the document
4. **Verify all internal links**: Links must point to pages that actually exist. Common mistakes:
   - Linking to `/get-started/setup-and-tooling/` instead of `/get-started/prerequisites/`
   - Linking to `/reference/cli/` for CLI installation instead of `/get-started/install-cli/`
5. **Add redirects when restructuring**: When moving or renaming documentation pages, add redirect entries in `src/frontend/config/redirects.mjs`

### Code Example Rules

1. **Use standard indentation**: For fluent APIs on newlines, use standard 4-space indentation, NOT alignment with the method call above
   
   ✅ Correct:
   ```csharp
   builder.AddProject<Projects.Api>("api")
       .WithReference(redis)
       .WithExternalHttpEndpoints();
   ```
   
   ❌ Incorrect (aligned indentation):
   ```csharp
   builder.AddProject<Projects.Api>("api")
          .WithReference(redis)
          .WithExternalHttpEndpoints();
   ```

2. **Code block language identifiers**: Use only one language identifier, not duplicates like `csharp csharp`

3. **Verify code syntax**: Check for typos in code:
   - `main:app` not `main.app` (Python uvicorn module:app format)
   - Verify package/module names are correct

4. **Accurate technical descriptions**:
   - `process.env` is an **object**, not a method
   - `express` is NOT used to access environment variables (that's `process.env`)
   - Don't claim libraries do things they don't do

5. **Connection string environment variables**:
   - For C#/.NET: Use `ConnectionStrings:resourcename` (colon separator)
   - For Python/JavaScript: Use `ConnectionStrings__resourcename` (double underscore separator)
   - Use the standard `ConnectionStrings__<resourcename>` pattern, not custom variable names like `ELASTICSEARCH_ENDPOINT`

6. **Don't document deprecated APIs as primary examples**: If an API is deprecated, don't use it as the first or main example. Use current, recommended APIs.

7. **Avoid insecure defaults in examples**: Don't include `TrustServerCertificate=true` in connection strings without noting it's for development only

### Component Usage Rules

1. **Match Pivot components to their PivotSelector**: When using nested Pivot components, ensure they reference the correct parent PivotSelector with the `key` attribute

2. **Keep LinkCard descriptions concise**: Card descriptions should be short enough to not squeeze the UI. Prefer "Configure persistence..." over "Discover how to configure persistence..."

3. **Avoid redundant Asides**: Don't have two Asides saying similar things near each other

### Cross-Language Documentation

When documenting integrations that support multiple languages (C#, Python, JavaScript):

1. **Show complete, working examples** for each language
2. **Ensure variable names are defined** before they're used in code examples
3. **Verify the same resource name** is used consistently across language examples
4. **Don't remove code that defines variables** that are used later in the document