Openapi scalar
Skill FaysilAlshareef/dotnet-ai-kit/skills/api/openapi-scalar
Use when setting up OpenAPI spec generation or Scalar API documentation UI.From its SKILL.md
npx -y skills add FaysilAlshareef/dotnet-ai-kit --skill openapi-scalarAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.0 KB, as published. Nobody here has run it
OpenAPI & Scalar API Documentation
Core Principles
- Use native
Microsoft.AspNetCore.OpenApi(.NET 9+) instead of Swashbuckle - Configure document transformers for metadata, security schemes, and customization
- Use Scalar as the modern API documentation UI replacement for Swagger UI
- Add OpenAPI metadata to every endpoint for accurate documentation
- Protect documentation endpoints in production
Patterns
Native OpenAPI Setup (.NET 9+)
// Program.cs
builder.Services.AddOpenApi("v1", options =>
{
options.AddDocumentTransformer((document, context, ct) =>
{
document.Info = new OpenApiInfo
{
Title = "{Domain} API",
Version = "v1",
Description = "API for {Company} {Domain} management"
};
return Task.CompletedTask;
});
// Add JWT security scheme
options.AddDocumentTransformer<BearerSecuritySchemeTransformer>();
});
Bearer Security Scheme Transformer
internal sealed class BearerSecuritySchemeTransformer(
IAuthenticationSchemeProvider schemeProvider)
: IOpenApiDocumentTransformer
{
public async Task TransformAsync(
OpenApiDocument document,
OpenApiDocumentTransformerContext context,
CancellationToken ct)
{
var schemes = await schemeProvider.GetAllSchemesAsync();
if (schemes.Any(s =>
s.Name == JwtBearerDefaults.AuthenticationScheme))
{
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes["Bearer"] =
new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
Description = "Enter JWT token"
};
}
}
}
Scalar UI Configuration
// Install: Scalar.AspNetCore
// Development setup
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.MapScalarApiReference(options =>
{
options
.WithTitle("{Domain} API")
.WithTheme(ScalarTheme.BluePlanet)
.WithDefaultHttpClient(
ScalarTarget.CSharp, ScalarClient.HttpClient)
.WithPreferredScheme("Bearer")
.WithHttpBearerAuthentication(bearer =>
{
bearer.Token = "your-dev-token-here";
});
});
}
// Production with auth protection
if (!app.Environment.IsDevelopment())
{
app.MapOpenApi()
.RequireAuthorization("ApiDocAccess");
app.MapScalarApiReference()
.RequireAuthorization("ApiDocAccess");
}
Versioned API Documents
// Register multiple OpenAPI documents
builder.Services.AddOpenApi("v1", options =>
{
options.AddDocumentTransformer((doc, _, _) =>
{
doc.Info.Title = "{Domain} API v1";
doc.Info.Version = "1.0";
return Task.CompletedTask;
});
});
builder.Services.AddOpenApi("v2", options =>
{
options.AddDocumentTransformer((doc, _, _) =>
{
doc.Info.Title = "{Domain} API v2";
doc.Info.Version = "2.0";
return Task.CompletedTask;
});
});
// Map both documents
app.MapOpenApi(); // serves /openapi/v1.json and /openapi/v2.json
Endpoint Metadata
// Minimal API metadata
app.MapGet("/orders/{id}", GetOrder)
.WithSummary("Get order by ID")
.WithDescription("Returns full order details including line items")
.Produces<OrderResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.WithTags("Orders");
// Controller metadata
[HttpGet("{id:guid}")]
[EndpointSummary("Get order by ID")]
[EndpointDescription("Returns full order details")]
[ProducesResponseType(typeof(OrderResponse), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult<OrderResponse>> GetOrder(Guid id) { }
Build-Time Document Generation
<!-- Generate OpenAPI spec at build time for CI -->
<PackageReference Include="Microsoft.Extensions.ApiDescription.Server" />
# Generate OpenAPI document at build time
dotnet build
# Output: obj/ApiDescription/v1.json
Anti-Patterns
- Using Swashbuckle with .NET 9+ (use native OpenAPI instead)
- Missing security scheme documentation
- No endpoint summaries or descriptions
- Exposing API docs without auth in production
- Hardcoding server URLs in OpenAPI document
Detect Existing Patterns
- Search for
AddOpenApiinProgram.cs(native .NET 9+) - Search for
AddSwaggerGen(Swashbuckle — legacy, migration candidate) - Check for
Scalar.AspNetCorepackage in.csproj - Look for
MapScalarApiReferenceorMapSwaggercalls - Check for
Microsoft.AspNetCore.OpenApipackage reference
Adding to Existing Project
- Replace Swashbuckle with
Microsoft.AspNetCore.OpenApi(if on .NET 9+) - Add Scalar —
dotnet add package Scalar.AspNetCore - Configure OpenAPI with document transformers for metadata
- Add security scheme transformer for JWT/API key
- Add metadata to all endpoints (
WithSummary,WithTags) - Protect docs in production with authorization
Migration from Swashbuckle
// BEFORE (Swashbuckle)
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API" });
});
app.UseSwagger();
app.UseSwaggerUI();
// AFTER (Native OpenAPI + Scalar)
builder.Services.AddOpenApi("v1", options =>
{
options.AddDocumentTransformer((doc, _, _) =>
{
doc.Info.Title = "My API";
return Task.CompletedTask;
});
});
app.MapOpenApi();
app.MapScalarApiReference();