Using Scalar with Optimizely CMS
OpenAPI, Content Delivery API, and Modern API Documentation
Modern Optimizely CMS solutions are increasingly API-first. Whether you are building a headless frontend, integrating external services, or exposing internal platform APIs, having clear and discoverable API contracts is essential. With .NET 8, this becomes even more relevant, as the way API documentation is handled has subtly but importantly changed.
This article shows how to combine OpenAPI, Scalar, and Optimizely CMS to create a clean, future-proof API documentation setup. We’ll look at custom APIs, Optimizely Content Delivery, and how everything fits together in a single developer-friendly UI.
A complete working example is available here:
github.com/andreas-valtech/OptimizelyScalarContentDelivery
Swagger UI, .NET 8, and What Actually Changed
When upgrading to .NET 8+, many teams notice that Swagger UI no longer appears automatically in new ASP.NET Core projects. This can feel like something has been removed, but in practice it reflects a deliberate architectural shift.
In recent ASP.NET Core versions, Microsoft has separated OpenAPI document generation from API documentation user interfaces. The framework now focuses on producing a standards-compliant OpenAPI specification, while leaving the choice of UI entirely up to the application. Swagger UI is still fully supported via libraries such as Swashbuckle, but it is no longer assumed to be the default.
This separation reinforces an important idea: OpenAPI is the contract, not the UI. Once that contract exists, it can be rendered using Swagger UI, Scalar, or any other compatible tool. For Optimizely CMS solutions—where custom APIs, content delivery, search, and external integrations often live side by side—this flexibility is a clear advantage.
Generating OpenAPI in .NET 8
Swashbuckle remains the most common way to generate OpenAPI documents in ASP.NET Core.
After adding the Swashbuckle.AspNetCore package, you can configure OpenAPI generation directly in Startup.cs:
public class Startup(IWebHostEnvironment webHostingEnvironment) { public void ConfigureServices(IServiceCollection services) {
... services.AddCms(); // Content Delivery API services.AddContentDeliveryApi(options => { options.SiteDefinitionApiEnabled = true; }); // Content Delivery Search API services.AddContentSearchApi(options => { options.MaximumSearchResults = 10; }); // Swashbuckle services.AddEndpointsApiExplorer(); services.AddSwaggerGen(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... app.UseSwagger(); app.UseSwaggerUI(); app.UseEndpoints(endpoints => { endpoints.MapContent(); // Maps both Content Delivery API and Commerce Content Delivery API endpoints.MapSwagger("/openapi/{documentName}.json", options => { options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1; }); endpoints.MapScalarApiReference(options => { options.WithTitle("Alloy Example API"); }); }); } }
At this stage, it is worth clarifying what is happening in the pipeline. The MapSwagger() call comes from Microsoft’s OpenAPI support in ASP.NET Core and is responsible for exposing the generated OpenAPI document as JSON. It does not provide any user interface. Scalar is added separately and uses its MapScalarApiReference() extension method to build an API documentation UI on top of that contract. This includes all API controllers defined in the application, as well as any external OpenAPI (swagger.json) documents added to the project, such as those provided by Optimizely or other services. In this way, ASP.NET Core owns the generation of the OpenAPI specification, while Scalar is responsible for presenting both internal and external APIs in a single, unified view.
Scalar as the API Documentation UI
Scalar is a modern OpenAPI UI that consumes the same OpenAPI JSON but presents it in a cleaner, faster, and more developer-focused way. Because Scalar only depends on the OpenAPI specification, it fits perfectly with the direction ASP.NET Core has taken.
To set up scalar you can follow their getting started guide for ASP.NET Core here: https://scalar.com/products/api-references/integrations/aspnetcore/integration or use my linked GitHub project for reference.
Once Scalar is wired up, it automatically renders everything described in your OpenAPI document, including custom controllers, schemas, and authentication definitions.
To confirm everything works, a simple controller is enough:[ApiController] [Route("api/hello")] public class HelloController : ControllerBase { [HttpGet] public IActionResult Get() => Ok(new { message = "Hello from Optimizely + Scalar" }); }
This endpoint is auto-discovered, included in the OpenAPI document, and immediately visible in Scalar without any additional configuration.
Bringing in Optimizely Content Delivery API
Optimizely provides official OpenAPI (swagger.json) definitions for its Content Delivery APIs. These can be downloaded from the Optimizely developer documentation:
By adding these JSON files directly to your project and serving them as static OpenAPI documents, Scalar can display Optimizely’s APIs alongside your own. This creates a single API surface where frontend and integration developers can explore both custom endpoints and content delivery endpoints in one place.
The Content Delivery API is central to headless Optimizely solutions, exposing pages, blocks, and content structures as JSON. Documenting it explicitly makes content contracts clearer and reduces friction between backend and frontend teams.
Content Management and Content Search APIs
In addition to content delivery, Optimizely’s Content Management and Content Search APIs are often part of larger integrations and automation workflows. Including their OpenAPI definitions in the same documentation UI improves internal developer experience and makes search queries, filters, and response structures easier to reason about.
Scalar handles multiple OpenAPI documents well, which makes it suitable as a lightweight internal API portal for Optimizely-based platforms.
External APIs and a Unified API View
Many Optimizely solutions integrate with external services such as commerce platforms, DAM systems, or personalization engines. When those services provide OpenAPI definitions, they can be included alongside Optimizely and custom APIs, giving teams a single, consistent documentation experience.
Example Repository
All of this is demonstrated in a runnable .NET 8 example here:
https://github.com/andreas-valtech/OptimizelyScalarContentDelivery/
What’s Next: Authentication with Keycloak
This article focuses on unauthenticated APIs. In the next part of the series, we’ll introduce authentication using Keycloak, covering OAuth 2.0 and OpenID Connect, securing both custom APIs and Optimizely Content Delivery endpoints, and documenting authentication flows in OpenAPI and Scalar.
Closing Thoughts
By treating OpenAPI as the primary contract and using a modern UI like Scalar, Optimizely CMS solutions align naturally with the direction of ASP.NET Core and modern headless architectures. The result is clearer APIs, better developer experience, and a setup that scales well as platforms grow more composable.
Comments