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:
Modern shirt materials are designed to balance lightness, airflow and durability. Supporters interested in historic designs may consider Atlético de Madrid football jerseys(camisetas 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.