# Docs Writer

> Guide for writing and improving documentation for SkiaSharp.Extended. Use this skill when creating, updating, or reviewing documentation pages, writing code examples for docs, generating screenshots for documentation, or improving existing docs.

- Skill: `mono/docs-writer` (Agent Skill)
- Install (CLI): `npx skillmds@latest add mono/docs-writer`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mono/docs-writer/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: mono (https://skillmd.com/u/mono)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mono/docs-writer

---


# Documentation Writer

This skill provides guidance for writing effective documentation for SkiaSharp.Extended.

## Documentation Principles

### Goals
- Help **new developers discover** features
- Help **experienced developers find** advanced features and customization
- Be **helpful, consistent, and informative** - not verbose
- This is a **community docs page** - impress and help users

### Style Guidelines
- **Friendly feature names** in TOC and titles (e.g., "Blur Hash" not "SKBlurHash")
- **Conceptual first** - explain why/when, then how
- **Conversational tone** - write as if explaining to a colleague
- **Concise code examples** - show primary overloads, not all variants
- **Research origins** - credit creators, link to official resources
- **Strategic visuals** - screenshots that add clarity, not decoration
- **Second person** - use "you can..." not "users can..."

### What Makes Good Docs
- Explain the **problem it solves** before showing how to use it
- Show **before/after comparisons** where applicable
- Include **real-world usage patterns** (API responses, MAUI bindings)
- Provide **customization options** with visual comparisons when helpful
- Link to **authoritative sources** for external technologies

### API Documentation
- **Link to generated API docs** using xref syntax: `[API Reference](xref:SkiaSharp.Extended.SKBlurHash)`
- **Include summary tables** only when they reduce redirects and add clarity
- **Don't reproduce** the full API docs in conceptual pages

### Images
- Keep existing images; use descriptive names for new ones (e.g., `components-comparison.png`)
- Store in `docs/images/extended/<feature>/` or `docs/images/ui/controls/<control>/`
- Use PNGs for UI screenshots, can use GIFs for animations

## Page Structure

Each documentation page follows this pattern:

```markdown
# Feature Name

Brief intro - what it is, the problem it solves (1-2 sentences)

[Hero image or comparison - e.g., before/after, original vs processed]

## Quick Start
- Encode/create: one code example
- Decode/use: one code example

## How It Works
- Brief explanation of underlying concepts
- Credit original creators if external technology
- Visual showing key concept if helpful

## Customization
- Key parameters and options with explanations
- Tables for parameters when helpful (reduces need to check API docs)
- Visual comparisons showing effect of different parameter values

## Usage Patterns
- Real-world integration examples (API responses, data models)
- MAUI binding/converter examples where applicable
- Brief XAML usage example

## Learn More
- Link to official site (if external technology like BlurHash, Lottie)
- Link to GitHub/source repository
- Link to origin story or detailed explanations
- Link to API reference using xref
```

### Example: External Technology Attribution
For features based on external technologies (BlurHash, Lottie, etc.):

```markdown
## Learn More

- [BlurHash.sh](https://blurha.sh/) — Official demo and explanation
- [BlurHash GitHub](https://github.com/woltapp/blurhash) — Original algorithm by Dag Ågren at Wolt
- [How Wolt created BlurHash](https://careers.wolt.com/en/blog/tech/...) — The origin story
- [API Reference](xref:SkiaSharp.Extended.SKBlurHash) — Full method documentation
```

### Example: Parameter Table
When parameters need explanation:

```markdown
| Components | String Length | Best For |
| :--------: | :-----------: | :------- |
| 2x2 | ~12 chars | Simple gradients |
| 4x3 | ~28 chars | Most images (recommended) |
| 6x6 | ~76 chars | Complex images with fine detail |
```

## Screenshot Generation

### Base Library Features
Generate screenshots using a temporary console app in `/tmp/`:

```bash
mkdir -p /tmp/docs-screenshots
cd /tmp/docs-screenshots
```

Create a minimal .csproj:
```xml
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="/path/to/source/SkiaSharp.Extended/SkiaSharp.Extended.csproj" />
  </ItemGroup>
</Project>
```

Write Program.cs to generate comparison images, then run:
```bash
dotnet run
```

### Screenshot Best Practices
- Generate side-by-side comparisons (e.g., different parameter values)
- Add labels to images using SKPaint/SKFont
- Use white background for consistency
- Cell size around 200x200 pixels works well
- Save directly to `docs/images/extended/<feature>/`

### Example: Comparison Image Generator
```csharp
using SkiaSharp;

var configs = new[] { (2, 2), (4, 3), (6, 6) };
var cellWidth = 200;
var padding = 10;

using var surface = SKSurface.Create(new SKImageInfo(totalWidth, totalHeight));
var canvas = surface.Canvas;
canvas.Clear(SKColors.White);

// Draw each variant side-by-side with labels
for (int i = 0; i < configs.Length; i++)
{
    // Generate image for this config
    // Draw to canvas at position
    // Add label below
}

using var image = surface.Snapshot();
using var data = image.Encode(SKEncodedImageFormat.Png, 100);
File.WriteAllBytes("comparison.png", data.ToArray());
```

### MAUI Controls
Discuss approach case-by-case - may require running on actual platforms. Existing GIFs in the repo can be kept.

## MAUI Integration Examples

**Always test MAUI code in a real project before including in docs.**

### Test Project Setup
```bash
mkdir -p /tmp/maui-test
cd /tmp/maui-test
dotnet new maui -n TestApp
cd TestApp
dotnet add package SkiaSharp.Views.Maui.Controls
dotnet add reference /path/to/source/SkiaSharp.Extended/SkiaSharp.Extended.csproj
dotnet build -f net10.0-maccatalyst  # or net10.0-android
```

### SKBitmap to ImageSource
Use the implicit conversion to `SKBitmapImageSource` (cross-platform, not Windows-specific):

```csharp
using SkiaSharp;
using SkiaSharp.Views.Maui.Controls;

SKBitmap bitmap = /* ... */;
ImageSource source = (SKBitmapImageSource)bitmap;
```

**Do NOT use** `ToWriteableBitmap()` - that's Windows-only.

### Value Converter Pattern
Include configurable properties for flexibility:

```csharp
using System.Globalization;
using SkiaSharp;
using SkiaSharp.Extended;
using SkiaSharp.Views.Maui.Controls;

public class BlurHashConverter : IValueConverter
{
    public int Width { get; set; } = 32;
    public int Height { get; set; } = 32;

    public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
    {
        if (value is string hash && !string.IsNullOrEmpty(hash))
        {
            var bitmap = SKBlurHash.DeserializeBitmap(hash, Width, Height);
            return (SKBitmapImageSource)bitmap;
        }
        return null;
    }

    public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
        => throw new NotImplementedException();
}
```

### XAML Usage
Always show how to use the converter in XAML:

```xml
<ContentPage.Resources>
    <local:BlurHashConverter x:Key="BlurHashConverter" Width="32" Height="32" />
</ContentPage.Resources>

<Image Source="{Binding BlurHash, Converter={StaticResource BlurHashConverter}}" />
```

## Building and Previewing Docs

```bash
cd docs
docfx build                    # Build docs
docfx serve _site --port 8080  # Serve locally
docfx --serve                  # Build and serve in one command
```

Verify pages render correctly:
```bash
curl -s http://localhost:8080/docs/blurhash.html | grep -o '<h1[^>]*>.*</h1>'
```

## Code Block Language Tags

Use consistent language tags for syntax highlighting:
- **`xml`** for XAML/XML content (not `xaml` - docfx highlights `xml` better)
- **`csharp`** for C# code
- **`bash`** for shell commands
- **`yaml`** for YAML files

## TOC Structure

For small documentation sites, use a **flat TOC** with section headings:

```yaml
items:
- name: Overview
  href: ../index.md

- name: SkiaSharp.Extended      # Heading only (no href = visual separator)
- name: Blur Hash
  href: blurhash.md
- name: Geometry Helpers
  href: geometry.md
- name: Path Interpolation
  href: path-interpolation.md

- name: SkiaSharp.Extended.UI.Maui  # Heading only
- name: Confetti Effects
  href: confetti.md
- name: Lottie Animations
  href: lottie.md

- name: Resources               # Catch-all for non-essential items
- name: Migration Guides
  items:
  - name: SVG Migration
    href: svg-migration.md
```

### TOC Guidelines
- **Headings without href** become visual section separators
- Use **friendly feature names** (not type names)
- Put migration guides and other non-essential content under a "Resources" heading
- Nested items only when there are true sub-pages (like Migration Guides)

## File Naming

When renaming doc files for friendlier URLs:
- `skblurhash.md` → `blurhash.md`
- `skgeometry.md` → `geometry.md` (if renaming)
- Update TOC href references accordingly

## Research Checklist

When documenting external technologies:
1. Who invented/created it?
2. Is there an official website or demo?
3. Is there a GitHub repository?
4. Is there an origin story or blog post?
5. What problem does it solve?
6. Are there alternatives? (mention if relevant)

## Testing Doc Code Snippets

**Always test code snippets before including in docs.**

### Create a Test Project
For each doc page, create a minimal test project in `/tmp/`:

```bash
mkdir -p /tmp/docs-code-test
cd /tmp/docs-code-test
```

Create .csproj:
```xml
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="/path/to/source/SkiaSharp.Extended/SkiaSharp.Extended.csproj" />
  </ItemGroup>
</Project>
```

### Test All Code Snippets
Create Program.cs that exercises all code from the doc page:

```csharp
// Test all code snippets from [Feature] docs
using SkiaSharp;
using SkiaSharp.Extended;

Console.WriteLine("Testing [Feature] doc code snippets...\n");

// === Quick Start: Encode ===
Console.WriteLine("1. Quick Start - Encode:");
// Copy code from docs here
// Verify it compiles and runs

// === Quick Start: Decode ===
Console.WriteLine("2. Quick Start - Decode:");
// Copy code from docs here

Console.WriteLine("\n✅ All code snippets compile and run correctly!");
```

Run the test:
```bash
dotnet run
```

### For MAUI Code
Test in a separate MAUI project (see MAUI Integration Examples section).

## Quality Checklist

Before finalizing a doc page:
- [ ] Friendly title (not type name)
- [ ] Brief intro explaining the value proposition
- [ ] Hero image or comparison
- [ ] Quick start with working code
- [ ] Customization options explained
- [ ] MAUI integration example (if applicable)
- [ ] Learn More links (official resources + API reference)
- [ ] **All code snippets tested in /tmp/ project**
- [ ] Build docs and verify no warnings
- [ ] Check rendered page in browser

## CI and Deployment

### Workflow Requirements
The docs workflow (`builds-docs.yml`) requires:
- MAUI workloads installed with explicit nuget.org source:
  ```yaml
  dotnet workload install maui --source https://api.nuget.org/v3/index.json
  ```

### PR Best Practices
- **Never merge with failing CI** - always wait for green checks
- Workflow failures related to workload installation often need the nuget.org source fix
- Check job logs to understand the actual failure before dismissing as transient

