skills/api/openapi-scalar/SKILL.md
Use when setting up OpenAPI spec generation or Scalar API documentation UI.
npx skillsauth add faysilalshareef/dotnet-ai-kit openapi-scalarInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Microsoft.AspNetCore.OpenApi (.NET 9+) instead of Swashbuckle// 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>();
});
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"
};
}
}
}
// 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");
}
// 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
// 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) { }
<!-- 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
AddOpenApi in Program.cs (native .NET 9+)AddSwaggerGen (Swashbuckle — legacy, migration candidate)Scalar.AspNetCore package in .csprojMapScalarApiReference or MapSwagger callsMicrosoft.AspNetCore.OpenApi package referenceMicrosoft.AspNetCore.OpenApi (if on .NET 9+)dotnet add package Scalar.AspNetCoreWithSummary, WithTags)// 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();
data-ai
Use when about to claim work is complete, fixed, passing, or ready — before committing, creating PRs, or moving to the next task. Requires running verification commands and confirming output before making any success claims.
development
Use when encountering any bug, test failure, build error, or unexpected behavior — before proposing fixes or making changes.
development
Use when checkpointing, wrapping up, or handing off an AI-assisted development session.
development
Use when following the Specification-Driven Development lifecycle from plan through ship.