I’ve been playing with a fun side project: my pickleball app. As it’s grown, I’ve found myself wanting the same thing most side projects eventually want — an actual REST API behind it that I can use from different client applications. Sometimes that client will be a React web app. Sometimes it’ll be a mobile app. In my case, mobile means C#/.NET because I’m using MAUI.

And here’s the part I’m trying to avoid: writing and maintaining all the repetitive client “plumbing” by hand in every front end.

In React, that means a bunch of TypeScript models, request wrappers, endpoint functions, error handling conventions, and so on. In MAUI, I’d be doing the same thing in C# with HttpClient, DTOs, and mapping code. It’s not hard work, but it’s the kind of work that becomes a tax — every backend change forces more client work, and the two inevitably drift apart.

So generating clients in multiple languages isn’t just a “nice-to-have.” It’s a big part of keeping the project moving.

The Key: Generate Clients from an OpenAPI Spec

If you can generate an OpenAPI specification for your backend, you can feed that spec into client generation tools and output strongly-typed clients for TypeScript, C#, and whatever else you need. It’s also really nice if you can automate this so that every time you change your backend, the clients get regenerated automatically.

The tricky part, though, is getting your backend to reliably generate the OpenAPI specification in the first place.

OpenAPI is essentially the old Swagger JSON file, rebranded and standardized. In ASP.NET, you can host it pretty easily. In your program setup you can do something like:

builder.Services.AddOpenApi(); 
var openApi = app.MapOpenApi();
openApi.AllowAnonymous();

That AllowAnonymous() is mostly about convenience: it makes it easier for automation tools to fetch the spec without needing to negotiate auth just to read the document. It does not mean you’ve suddenly made your API insecure or opened up your endpoints to anonymous traffic. It’s simply saying the spec endpoint is accessible without auth.

To host the OpenAPI spec, the NuGet package you need is:

Microsoft.AspNetCore.OpenApi

Once that’s in place, your ASP.NET app will host a JSON file when the app is running — whether that’s locally, on a VM, in a container, or however you deploy.

The Pain: “Go Run the App So the Spec Exists”

But here’s the workflow snag: a lot of automation tools need to go get that JSON to generate clients. If the only way to get the spec is “run the service somewhere and fetch it,” you end up doing awkward things like:

  • copying the OpenAPI JSON into a GitHub repo just to trigger client generation, or
  • manually deploying to a dev environment so CI can fetch the spec from a URL, or
  • spinning up containers just to extract one artifact.

And that’s the exact kind of friction I’m trying to remove.

Wouldn’t it be nicer if simply merging backend changes into main caused the OpenAPI spec to update and client generation to happen automatically?

That’s what I’m aiming for. This article covers the first step: generating the OpenAPI spec at build time.

Build-Time OpenAPI Generation in ASP.NET

ASP.NET has a feature that allows you to emit the OpenAPI spec during build. That means you don’t have to deploy the app or run it in a container just to get the specification — you can build the project and the spec drops out as an artifact.

Pretty sweet… but it’s not as easy as it sounds.

First, you need to add a couple of things to your project file. You’ll enable build-time generation, and you’ll put the output into a predictable directory.

Here’s the property group:

<PropertyGroup>
  <!-- Turn on build-time OpenAPI generation -->
  <OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>
  <!-- Put the generated JSON somewhere predictable -->
  <OpenApiDocumentsDirectory>$(MSBuildProjectDirectory)\openapi</OpenApiDocumentsDirectory>
 </PropertyGroup>

You also need a prerequisite package reference. Add this to the .csproj:

<PackageReference Include="Microsoft.Extensions.ApiDescription.Server" Version="9.0.9">
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  <PrivateAssets>all</PrivateAssets>
</PackageReference>

That package reference is the prereq that makes the build-time document generation possible. The OpenApiGenerateDocuments flag turns it on, and OpenApiDocumentsDirectory tells MSBuild where to put the output so you can depend on the location in CI.

Now you’ve got a clean, repeatable path: build the project, and the OpenAPI JSON appears in your chosen folder.

Don’t Commit Generated Specs

Once you do this, I recommend adding a .gitignore rule:

**/openapi/**/*.json

Why? Because you want your CI process to automatically generate the spec, not have it committed into the repo.

The OpenAPI spec is an artifact. It’s useful for generating code, but it doesn’t really need to be maintained under source control. In fact, committing it tends to cause annoying churn — every change creates diffs in an auto-generated file that humans aren’t meant to edit anyway.

Conclusion

That’s it. With a couple of project settings and a prerequisite package, you can generate OpenAPI specifications during build in your .NET projects. This sets you up for the bigger goal: a workflow where merging backend changes into main can automatically regenerate the spec and produce updated clients for React (TypeScript) and MAUI (C#) without you hand-coding all the plumbing every time.

If you’re building a side project like my pickleball app and you want to move fast without letting the client/server boundary slow you down, this is a really solid first step.