DocQL.Net
1.1.0
dotnet add package DocQL.Net --version 1.1.0
NuGet\Install-Package DocQL.Net -Version 1.1.0
<PackageReference Include="DocQL.Net" Version="1.1.0" />
<PackageVersion Include="DocQL.Net" Version="1.1.0" />
<PackageReference Include="DocQL.Net" />
paket add DocQL.Net --version 1.1.0
#r "nuget: DocQL.Net, 1.1.0"
#:package DocQL.Net@1.1.0
#addin nuget:?package=DocQL.Net&version=1.1.0
#tool nuget:?package=DocQL.Net&version=1.1.0
DocQL
API reference docs for any GraphQL endpoint, served straight from your ASP.NET Core app. Point it at your schema, add two lines to Program.cs, and get a browsable docs site at /docs.
The UI ships inside the package as a single embedded page. No static files to copy, no separate frontend to deploy.

Features
- Every query, mutation and subscription, with arguments, return types and nested fields you can expand inline
- Reads your schema as SDL or through introspection
- Descriptions rendered as Markdown
- Operations grouped in the sidebar, from a description tag, your own regex, or a directive
- Nested root types (
query { billing { invoices } }) shown as a navigable tree - Required scopes shown on operations and fields marked with
@requiresScopes - Deprecated fields flagged, with a toggle to hide them
- Your own Markdown guide pages (authentication, samples, anything) in the sidebar
- Optional link to your GraphQL playground
- Light and dark themes
Install
dotnet add package DocQL.Net
Targets .NET 8 and later.
Quick start
using DocQL.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDocQL(options =>
{
options.Title = "My API";
options.SchemaUrl = "https://api.example.com/graphql/schema.graphql";
options.SchemaType = "sdl";
});
var app = builder.Build();
app.UseDocQL("/docs");
app.Run();
Open /docs.
Example: GitHub's API
GitHub publishes its GraphQL schema as SDL, and tags every mutation with its own @docsCategory directive. This is a complete app that documents it:
using DocQL.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDocQL(options =>
{
options.Title = "GitHub GraphQL API";
options.SchemaUrl = "https://raw.githubusercontent.com/github/docs/main/src/graphql/data/fpt/schema.docs.graphql";
options.SchemaType = "sdl";
options.Grouping = DocQLGrouping.FromDirective("docsCategory", "name");
options.PlaygroundUrl = "https://docs.github.com/en/graphql/overview/explorer";
});
var app = builder.Build();
app.UseDocQL("/docs");
app.Run();
Run it and open /docs. Mutations are grouped into GitHub's categories (issues, pulls, repos and so on), and every type is browsable.
Loading the schema
The schema is downloaded by the visitor's browser, so SchemaUrl must be either:
- a URL that allows cross-origin requests, like the
raw.githubusercontent.comaddress above, or - a path your own app serves, such as
/schema.graphql.
If the source does not allow cross-origin requests, download the SDL once and serve it yourself:
curl -o schema.graphql https://docs.github.com/public/fpt/schema.docs.graphql
builder.Services.AddDocQL(options =>
{
options.SchemaUrl = "/schema.graphql";
options.SchemaType = "sdl";
});
var app = builder.Build();
app.MapGet("/schema.graphql", () => Results.File(Path.Combine(app.Environment.ContentRootPath, "schema.graphql"), "text/plain"));
app.UseDocQL("/docs");
Options
| Option | Description |
|---|---|
Title |
Name shown in the header and the browser tab. Default GraphQL Documentation. |
SchemaUrl |
Where the schema is loaded from: an SDL file, or your GraphQL endpoint for introspection. Absolute or relative to your app. |
SchemaType |
sdl or introspection. Default introspection. |
PlaygroundUrl |
Optional link to a GraphQL playground. |
Theme |
Starting theme, light or dark. Default: the visitor's system setting. The visitor's own choice always wins. |
Grouping |
How operations are grouped in the sidebar. See Groups. |
Namespaces |
How nested root types are found. See Namespaces. |
ScopesDirective |
Name of the directive that carries required scopes. Default requiresScopes. |
DocsNav |
Markdown guide pages shown in the sidebar. |
The route comes from UseDocQL, /docs by default.
Guide pages
Add Markdown pages and nest them into sections:
builder.Services.AddDocQL(options =>
{
options.SchemaUrl = "https://api.example.com/graphql/schema.graphql";
options.SchemaType = "sdl";
options.DocsNav = new List<DocsSection>
{
new("Getting started",
new DocsSection(DocQLPage.FromFile("welcome", "Welcome", "docs/welcome.md"))),
new("Authentication",
new DocsSection(DocQLPage.FromFile("auth", "Overview", "docs/auth.md")),
new DocsSection(new DocQLPage("tokens", "Tokens", "# Tokens\n\nInline Markdown works too."))),
};
});
DocQLPage.FromFilereads the file on every request, so edits show up without a restart.DocQLPage.FromFileCachedreads it once, with an optionalmaxAgeto refresh.new DocQLPage(slug, title, markdown)takes Markdown inline, or aFunc<CancellationToken, Task<string>>to load it from anywhere.
Groups
By default, a tag in square brackets at the start of an operation's description puts it in a group:
type Query {
"[Invoices] List invoices for the current account."
invoices: [Invoice!]!
}
The tag is removed from the displayed description. Choose another source with Grouping:
// default: "[Invoices] ..." at the start of the description
options.Grouping = DocQLGrouping.FromDescription();
// your own convention, e.g. "Invoices: List invoices..."
options.Grouping = DocQLGrouping.FromDescription(@"^(?<group>\w+):\s*");
// a directive, e.g. @tag(name: "Invoices")
options.Grouping = DocQLGrouping.FromDirective("tag", "name");
// no groups
options.Grouping = DocQLGrouping.None;
- A description pattern adds one group per match, named by its
groupcapture (or the first capture). Passstrip: falseto keep the matched text in the description. Patterns run in the browser, so use JavaScript regex syntax. - Directive grouping needs
SchemaType = "sdl", because directives are not part of introspection results.
Namespaces
Some APIs nest operations under wrapper fields, like query { billing { invoices } }. DocQL detects these and shows them as a tree. Override the detection when needed:
options.Namespaces = DocQLNamespaces.Auto; // default
options.Namespaces = DocQLNamespaces.None; // every root field is an operation
options.Namespaces = DocQLNamespaces.FromTypes("BillingQueries", "BillingMutations");
Scopes
When the schema is loaded as SDL, DocQL reads the @requiresScopes directive (the same shape Apollo Federation uses) and shows the required scopes as a chip on the operation or field:
directive @requiresScopes(scopes: [[String!]!]!) on FIELD_DEFINITION
type Client {
arAging: ClientArAging @requiresScopes(scopes: [["invoice_read"]])
}
Inner lists are scopes that are all required. Outer lists are alternatives, so [["a"], ["b"]] shows as a or b. Use ScopesDirective if your directive has another name.
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- GraphQL (>= 8.5.0)
- GraphQL.IntrospectionModel (>= 0.0.22)
- GraphQL-Parser (>= 9.5.0)
- Microsoft.AspNetCore.Http.Abstractions (>= 2.3.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.6)
- Microsoft.Extensions.Options (>= 9.0.6)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.