This is the documentation website for Spectre.Console (rich console UI library) and Spectre.CLI (command-line application framework). This guide will help you contribute documentation, add samples, and work with the site effectively.
- .NET 11.0 - Blazor Server application
- Pennington - Markdown-based content engine for .NET
- MonorailCss - Utility-first CSS framework
- Pennington.TreeSitter - Tree-sitter code-fragment extraction for live code samples
- .NET 10.0 SDK
- For creating animated samples (optional):
Navigate to the Spectre.Docs directory and run:
dotnet watchThe application will be available at https://localhost:5203 (or check console output for the exact port).
The project is configured with hot reload - changes to markdown files in Content/**/* will automatically refresh the site during development.
dotnet run -- build <outputfolder>The site uses a multi-service content architecture with three main sections:
Content/
├── console/ # Spectre.Console documentation
│ ├── how-to/
│ ├── tutorials/
│ ├── widgets/
│ ├── live/
│ ├── prompts/
│ ├── reference/
│ └── explanation/
├── cli/ # Spectre.CLI documentation
│ ├── how-to/
│ ├── tutorials/
│ ├── reference/
│ └── explanation/
├── blog/ # Blog posts and release notes
└── assets/ # Images, SVG animations, etc.
Each section has its own content service and front matter model, configured in Program.cs.
Create a .md file in the appropriate subdirectory (e.g., Content/console/how-to/my-guide.md):
---
title: "Your Page Title"
description: "SEO-friendly description of the page"
date: 2025-01-15
tags: ["tag1", "tag2"]
section: "Console"
uid: "console-unique-id"
order: 100
---
# Your Content Here
Start writing your documentation using standard markdown...Front Matter Fields:
title(required) - Page title shown in navigation and browserdescription(required) - Used for SEO and metadataorder(required) - Sidebar navigation order (lower = higher in list)uid- Unique identifier for cross-referencing
The file path determines the URL:
Content/console/how-to/example.md→/console/how-to/example
Create a .md file in Content/blog/:
---
title: "Spectre.Console 0.51.0: Amazing New Features"
author: "Your Name"
description: "Brief summary of the blog post"
date: 2025-01-15
tags: ["release", "features"]
series: "Release Notes"
isDraft: false
---
Your blog content here...Additional Blog Fields:
author- Author nameseries- Groups related posts together (optional)
Blog posts are automatically sorted by date (newest first) and appear at /blog/your-file-name.
The site uses Pennington.TreeSitter to embed live code from your source files directly into documentation. This ensures code samples are always up-to-date with the actual implementation.
Use the special code fence ```csharp:symbol. The body is a source file path (relative to the repo root) optionally followed by > Type.Member:
```csharp:symbol
Spectre.Docs.Examples/Showcase/ProgressSample.cs > ProgressSample.Run
Spectre.Docs.Examples/Showcase/ProgressSample.cs > ProgressSample.CreateTasks
```Address code by file path + name path — a name path survives the line shifts that break hard-coded ranges:
| Target | Body shape | Example |
|---|---|---|
| Whole file | <path> |
Spectre.Docs.Examples/Showcase/ProgressSample.cs |
| A type | <path> > Type |
... > ProgressSample |
| A member | <path> > Type.Member |
... > ProgressSample.Run |
| Nested member | <path> > Outer.Inner.Member |
... > DrawCommand.Settings |
Modifiers (comma-separated, order-independent) follow the suffix:
| Modifier | Effect |
|---|---|
,bodyonly |
Render only the member body, stripping the declaration and braces |
,imports |
Prepend the file's top-of-file using statements |
,signatures |
Replace member bodies with { … } for an outline view |
symbol-diff |
Emit a unified diff between two members (exactly two references) |
Example from progress.md:
```csharp:symbol,bodyonly
Spectre.Docs.Examples/Showcase/ProgressSample.cs > ProgressSample.Run
```This extracts the body of the Run method from ProgressSample.cs and renders it with syntax highlighting.
Tree-sitter is wired in Program.cs, reading source files directly — no MSBuild workspace, no compilation:
builder.Services.AddTreeSitter(treeSitter =>
{
treeSitter.ContentRoot = ".."; // repo root, so fence paths resolve against the sibling example projects
});When Pennington encounters a csharp:symbol fence:
- Resolves the file path relative to
ContentRoot - Uses tree-sitter to locate the named member within the file
- Extracts the source text (applying any modifiers)
- Renders as syntax-highlighted HTML
This approach provides:
- Always up-to-date code - Changes in source automatically reflect in docs
- Rename-safe references - A name path tolerates line shifts; broken references surface in the build report
- No duplication - Single source of truth for code
Animated samples show your library features in action using VCR tape recordings. The project supports two types of samples: Console samples (widget demonstrations) and CLI samples (command-line application tutorials).
Install VCR from GitHub.
Console samples demonstrate Spectre.Console widgets and features. They run with no command-line arguments and assume the project has been built.
Create a new sample in Spectre.Docs.Examples/Showcase/:
public class MyFeatureSample : BaseSample
{
public override void Run(IAnsiConsole console)
{
console.Write(
new Panel("[bold yellow]Hello, Spectre![/]")
.BorderColor(Color.Blue));
Thread.Sleep(2000);
}
}The class name determines the sample name (MyFeatureSample → my-feature).
Create a .tape file in Spectre.Docs.Examples/VCR/:
Output "Spectre.Docs/Content/assets/my-feature.svg"
Set DisableCursor true
Set FontSize 22
Set Theme "one dark"
Set TransparentBackground "true"
Set Cols 82
Set Rows 12
Set EndBuffer 5s
Exec "dotnet run --project .\Spectre.Docs.Examples\ --no-build showcase my-feature"
Key points:
- Use
--no-buildbecause the build script compiles the project first - The sample name in
showcase <name>matches the kebab-case class name (minus "Sample")
CLI samples demonstrate Spectre.CLI command-line application patterns. They use an environment variable to select which demo to run from the compiled example.exe.
Create a demo in Spectre.Docs.Cli.Examples/DemoApps/[Tutorial]/[SubFolder]/:
namespace Spectre.Docs.Cli.Examples.DemoApps.MyTutorial.Complete;
public class Demo
{
public static async Task<int> RunAsync(string[] args)
{
var app = new CommandApp<MyCommand>();
return await app.RunAsync(args);
}
}Create a .tape file in Spectre.Docs.Cli.Examples/VCR/:
Output "Spectre.Docs/Content/assets/cli-my-tutorial.svg"
Set Shell "pwsh"
Set FontSize 22
Set Theme "one dark"
Set TransparentBackground "true"
Set Cols 70
Set Rows 12
Set EndBuffer 5s
Set WorkingDirectory "Spectre.Docs.Cli.Examples/bin/Debug/net10.0"
Env SPECTRE_APP "M:Spectre.Docs.Cli.Examples.DemoApps.MyTutorial.Complete.Demo.RunAsync(System.String[])"
Type "./example --help"
Sleep 400ms
Enter
Sleep 2s
Type "./example Alice"
Sleep 400ms
Enter
Sleep 1s
Key points:
SPECTRE_APPis set to the XmlDocId of the demo'sRunAsyncmethod- Use
TypeandEntercommands to simulate interactive terminal input - The working directory points to the compiled binary location
Run the build script from the repository root:
.\Generate-WidgetScreenshots.ps1This script:
- Builds both
Spectre.Docs.ExamplesandSpectre.Docs.Cli.Examples - Finds all
.tapefiles in both VCR directories - Executes each tape with VCR to generate SVG files
- Outputs SVG files to
Spectre.Docs/Content/assets/
Use the razor component
<Screenshot Src="/assets/my-image.svg" Alt="Alt Text" />