Welcome to the documentation of all Duende Software products and open-source tools!
You will need the following installed:
- .NET 10 SDK
- Node.js 22+
cd astro
npm install
npm run devFor local development with the full stack (Astro dev server + ASP.NET Core):
dotnet build.cs aspireThis starts:
- Astro dev server at http://localhost:4321 (with hot reload)
- ASP.NET Core server (for production-like static file serving)
- Aspire Dashboard at https://localhost:17001 (for traces, logs, metrics)
Alternatively in VS Code, GitHub Codespaces, or WebStorm, you can use the devcontainer to get a development environment set up.
All commands use the build.cs file-based build script and can be run from any directory in the repository:
| Command | Action |
|---|---|
dotnet build.cs |
Build everything (Astro + .NET) |
dotnet build.cs astro-build |
Build Astro to wwwroot |
dotnet build.cs dotnet-build |
Build .NET solution |
dotnet build.cs container |
Build container image |
dotnet build.cs aspire |
Start Aspire dev environment |
dotnet build.cs clean |
Clean all build outputs |
dotnet build.cs verify-formatting |
Check .NET code formatting |
dotnet build.cs --list-targets |
List all available targets |
The container is built using dotnet publish /t:PublishContainer (no Dockerfile required).
dotnet build.cs containerdocker run -p 8080:8080 docsThe site will be available at http://localhost:8080.
This project uses Astro + Starlight for the documentation site, served by ASP.NET Core in production.
.
├── build.cs # File-based build script
├── astro/ # Astro documentation site
│ ├── public/
│ ├── src/
│ │ ├── assets/
│ │ ├── content/
│ │ │ └── docs/
│ │ └── content.config.ts
│ ├── astro.config.mjs
│ ├── package.json
│ └── tsconfig.json
└── server/ # ASP.NET Core server
├── src/
│ ├── Docs.Web/ # Static file server
│ │ └── wwwroot/ # Astro build output (gitignored)
│ ├── Docs.AppHost/ # .NET Aspire orchestrator
│ └── Docs.ServiceDefaults/ # Shared configuration
└── tests/
└── Docs.Web.Tests/ # Integration tests
Starlight looks for .md or .mdx files in the astro/src/content/docs/ directory. Each file is exposed as a route based on its file name.
Images can be added to astro/src/assets/ and embedded in Markdown with a relative link.
Static assets, like favicons, can be placed in the astro/public/ directory.
The astro/ folder has been configured as a VS Code and WebStorm project, which you can open from that location to work on content.
Content can be authored in Markdown, in a .md or .mdx file. The Starlight documentation has some guidance on Markdown syntax, components, and more:
- Authoring Content in Markdown
- Using Components (only in
.mdx)
Use a spell checker like Grazie or Grammarly to check your content for spelling and grammar errors. WebStorm has Grazie as a built-in spell checker and grammar checker, and supports a good default writing style.
- Use the active voice. For example, use "Enable" instead of "Enabled" or "Enabling".
- Use the second person ("you" not "I" or "we"). "You" is the reader of the documentation. "We" is Duende Software.
- Use sentence case in text. Titles use Title Case.
- Use the Oxford comma.
- Avoid words like "very", "simple", "easy", ...
- "As well as" can be written as "and".
- Avoid flowery language.
- When using acronyms, use the full form with parentheses the first time you use it. For example, use "Multi-Factor Authentication (MFA)" instead of "MFA".
- Always prefer linking internally over linking externally. For example, when you talk about data protection, prefer an internal link over a link to external sites.
- When linking to external content, consider writing one or two sentences about the context and what the reader will learn on the linked page.
- When linking other pages, use a path that starts at the content root, like
/identityserver/troubleshooting/index.md. Use the.md(x)file extension - Starlight will update the link to the correct format on build. - When linking to external resources, use the full URL using HTTPS.
- You can link to header anchors using the
#symbol, for example[multiple authentication methods](/identityserver/ui/federation.md#multiple-authentication-methods-for-users). - Link relevant text. Prefer
learn more about [improving the sign-in experience]overclick [here] to learn more. - Run
dotnet build.cs link-checkto build Astro for link validation (actual lychee check runs in CI). - When a markdown link is long (75+ characters) or a link is repeated multiple times on a page, prefer moving the link to the bottom of the file and using markdown anchor syntax
[test.cs][repo-test-file]
- Use
*for lists. Do not use-. - Use
[link title](https://example.com)for links, avoid reference-style links unless you need to repeat the same link multiple times. - For internal links, always include the extension (e.g.
.mdor.mdx) - Prefer
csharpovercsto set the language for C# code blocks.
- Use triple backticks to enclose code blocks.
- Use a language identifier to specify the language (e.g.
csharp,bash,json,html,javascript,typescript,css,json) - Add a title to the code block. You can do this adding the title as a comment in the first line of the code block (e.g.
// Program.cs). - Use expressive code features.
- Readers should not need to scroll horizontally to read a code example. Simplify and condense the code as much as possible.
- If writing C#, use the latest syntax — including top-level statements, collection expressions, ...
- Make sure examples are runnable and complete. The goal is "Copy-paste from docs". Include namespaces, a result, and other prerequisites that are not obvious to someone new to the code.
- Inline comments can be used to explain essential parts of the code. Expressive code can highlight line numbers, show diffs, and more.
- Mention NuGet packages as a
bashcode block showing how to install it (dotnet add package ...). Link to the NuGet Gallery. - When referencing a property, field, class, or other symbol in text, use the
testformat instead of test. - Values should also be back-ticked, especially HTTP Status codes like
404or401. - Make sure code blocks start at the very first character space and don't have excessive starting padding.
-
Always have a
titleproperty to set the page title. -
Always have a
descriptionproperty to set the page description. This is a summary of the page's core content. -
Always have a
dateproperty to set the creation/significant update date for a page. Use theYYYY-MM-DDformat. -
Add the
sidebarproperty and must include thelabelandorder. Thelabelis used in the menu, and should typically be shorter than the more descriptivetitle. For example:title: "Using IdentityServer As A Federation Gateway" sidebar: label: "Federation" order: 1
Astro commands are run from the astro/ directory:
| Command | Action |
|---|---|
npm install |
Installs dependencies |
npm run dev |
Starts local dev server at localhost:4321 |
npm run build |
Build production site (use dotnet build.cs astro-build instead) |
npm run preview |
Preview your build locally |
npm run astro ... |
Run CLI commands like astro add, astro check |
There are two ways to restructure content:
- Internal (move content around in the current structure)
- External (move content outside the current structure)
When doing internal restructuring, move the page to its new location and then update its frontmatter to include the old location:
---
title: Page title
redirect_from:
- /old-path-to/content
---
Page content goes hereThis will generate the page at the new location, and put a redirect to it at the old location.
When moving a page outside the structure, or you need a redirect to another location altogether,
edit the astro/astro.config.mjs file and append a key/value pair to the redirects property:
redirects: {
"/identityserver/product-page": "https://duendesoftware.com/products/identityserver",
},This will remove the old page from the navigation structure, but keeps the URL around with a redirect to the new location.
For all licensing information, refer to the relevant license files:
- LICENSE - License for the documentation site content.
- LICENSE-CODE - License for the code samples.
The Astro documentation engine is licensed under the MIT license.