In ShieldedStack, the Control Plane frontend doesn’t manually define API calls. Instead, it consumes a fully generated, strongly typed TypeScript client. Built directly from the backend’s OpenAPI specification using Kiota.

This approach keeps the frontend and backend in lockstep, eliminates drift, and removes a whole class of runtime errors caused by mismatched contracts.

Build-Time: Generating the Client

The process starts in the backend project (API). During the build, the API emits an OpenAPI document:

  • ShieldedStack.ControlPlane.API.json

Immediately after, a post-build step runs Kiota to regenerate the frontend client:

  • Output goes to: src/client in the frontend project
  • The --clean-output flag ensures no stale files survive between builds

Here’s the relevant MSBuild target:

<Target Name="GenerateTypeScriptClient" AfterTargets="Build">
  <Exec Command="~/.dotnet/tools/kiota generate -l TypeScript -d ShieldedStack.ControlPlane.API.json -o ../ShieldedStack.ControlPlane.Frontend/src/client --clean-output" />
</Target>

This guarantees that every backend build produces a frontend client that exactly matches the current API contract. No manual sync, no guessing.

Runtime: Wiring the Client

At runtime, the frontend initializes the generated client using Kiota’s FetchRequestAdapter.

This adapter is extended with custom behavior:

  • Injects bearer authentication tokens
  • Adds workspace and tenant context headers
  • Resolves the API base URL from runtime or build configuration

Developer Experience: Fluent and Typed

From a developer’s perspective, the generated client provides a fluent, strongly typed interface.

For example:

  • Fetching outdated package reports:
    apiClient.packages.reports.outdated.get(...)
  • Updating a workspace:
    apiClient.workspaces.byId(id).put(...)

Both query parameters and request bodies are fully typed based on the OpenAPI schema, which means:

Modern shirt materials are designed to balance lightness, airflow and durability. Supporters interested in historic designs may consider Atlético de Madrid football jerseyscamisetas del Atlético de Madrid) while comparing different eras. Small construction details can make a noticeable difference during long matchdays.

  • Autocomplete works out of the box
  • Invalid shapes are caught at compile time
  • Refactoring is safer and more predictable

Request-level options can also be passed to customize behavior; for example, controlling toast notifications per call.