Repository navigation
Getting Started
dotnet add package Folio.AspNetCoreSupports .NET 6, 7, 8, and 9.
The package doesn't care how you generate your OpenAPI document — it just renders whatever you point it at via SpecUrl. Any source works.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();
var app = builder.Build();
app.MapOpenApi(); // publishes /openapi/v1.json
app.UseFolio(options =>
{
options.RoutePrefix = "docs"; // UI will be at /docs
options.SpecUrl = "/openapi/v1.json";
options.Title = "My API"; // optional
});
app.Run();builder.Services.AddSwaggerGen();
// ...
app.UseSwagger(); // publishes /swagger/v1/swagger.json
app.UseFolio(options =>
{
options.SpecUrl = "/swagger/v1/swagger.json";
});Same idea — point SpecUrl at whatever URL serves your OpenAPI JSON.
Open /folio (or your configured RoutePrefix):
- Endpoint list and model schema catalog, generated from the spec.
- A type-aware request builder for parameters and request bodies.
- In-browser request execution, with generated code snippets (cURL, JavaScript, Python, C#, Go, PowerShell).
- Environment support (switch base URLs without editing anything).
- Authorization against the spec's declared security schemes (
apiKey, HTTP Bearer/Basic). - Dark mode, instant search, saved examples, shareable deep links.
| Property | Default | Description |
|---|---|---|
RoutePrefix |
"folio" |
Path the UI is served under (no leading/trailing slashes). |
SpecUrl |
"/openapi/v1.json" |
URL of the OpenAPI document — required for a real project. |
Title |
null |
Page/header title. Falls back to the spec's info.title if not set. |
AuthorizationPolicy |
null |
Name of an ASP.NET Core authorization policy the UI is gated behind. See Authorization. |
LogoutUrl |
null |
Shows a "Log out" button in the header, pointing here. Hidden if unset. |
ShowTryItOut |
true |
Shows the "Send request" button that executes real requests against your API. |
ShowRoles |
true |
Shows the role badges/popover read from your endpoints' own [Authorize(Roles = "...")]. See Features. |
ShowCodeGenerator |
true |
Shows the multi-language code generator (cURL/JS/Python/C#/Go/PowerShell). |
ShowSchema |
true |
Shows the Schema button for viewing a model's JSON schema. |
ShowHome |
true |
Shows the "Home" button (returns to the welcome screen). |
ShowEnvironmentSwitcher |
true |
Shows the environment/base-URL switcher. |
ShowGlobalHeaders |
true |
Shows the "Global headers" button. |
ShowAuthorize |
true |
Shows the OpenAPI security scheme "Authorization" button, when the spec declares one. |
ShowExamples |
true |
Shows "Save example" / "My examples". |
ShowShare |
true |
Shows the "Copy endpoint link" button. |
Every ShowXxx flag above can be set directly in code:
app.UseFolio(options =>
{
options.SpecUrl = "/openapi/v1.json";
options.ShowTryItOut = false; // e.g. a read-only docs deployment
options.ShowCodeGenerator = false;
});...or bound from appsettings.json (or any other IConfiguration source). Folio never reads configuration on its own — you opt in explicitly, the same way Serilog's ReadFrom.Configuration(...) works:
{
"Folio": {
"ShowTryItOut": false,
"ShowCodeGenerator": false
}
}app.UseFolio((context, options) =>
{
options.SpecUrl = "/openapi/v1.json";
options.ReadFrom.Configuration(context.Configuration, "Folio");
});Both paths write to the same options, so you can combine them — config as the base, with specific values overridden in code afterward (or vice versa, depending on call order). There's no built-in dev/prod switch inside Folio itself; if you want different values per environment, use ASP.NET Core's own appsettings.{Environment}.json layering — the code above stays identical on every environment.
The UI (HTML/CSS/JS) is embedded into the package assembly as embedded resources and served through the standard StaticFileMiddleware on top of a ManifestEmbeddedFileProvider — with proper ETag/Last-Modified/conditional requests, not hand-rolled file serving. index.html is served by a small dedicated handler that injects configuration (SpecUrl, Title, ...) into a <script> tag on the fly before the rest of the scripts load — the UI itself hardcodes nothing and works with whatever OpenAPI document you point it at.
Fully offline: fonts, Tailwind CSS, marked.js, and flatpickr are all bundled locally and embedded into the package assembly — zero external requests, both at build time and in the user's browser.