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/clientin the frontend project - The
--clean-outputflag 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:
- 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.