Docs navigation
Templates
GenX API treats templates as pluggable adapters. Templates own generator-specific behaviour; GenX API core owns orchestration. The monorepo currently ships two first-party template packages:
- Orval API Client Template (
@genxapi/template-orval)- Produces TypeScript SDK packages with Orval-specific client, mock, and bundling behaviour.
- Uses the unified configuration (
project.config,clients[].config) to drive Orval’s output options.
- Kubb API Client Template (
@genxapi/template-kubb)- Wraps the Kubb plugin ecosystem (
plugin-client,plugin-ts,plugin-oas). - Accepts transport and plugin overrides through the same unified interface.
- Wraps the Kubb plugin ecosystem (
Both templates:
- Expose a stable
genxTemplatecontract so the CLI can validate, transform, plan, and invoke them explicitly. - Ship Rollup + Vitest tooling for building and testing generated SDKs.
- Honour
project.templateOptions(variables, install toggles, local template path) for bespoke customisations. - Are responsible for how generator outputs become a stable package interface for consumers.
Selecting a Template
Built-in templates
Use the short aliases or package names for first-party templates:
{
"project": {
"template": "orval"
}
}
"kubb" and fully-qualified package names such as @genxapi/template-orval remain valid.
External templates
Use an explicit external template reference when a team owns a separate template package or a local template module:
{
"project": {
"template": {
"provider": "external",
"module": "@acme/genxapi-template",
"export": "genxTemplate"
}
}
}
For local development, module can point at a relative or absolute filesystem path. Relative paths resolve from the directory that contains the GenX API config file.
This path is intentional:
- GenX API knows whether it is loading a built-in or external template.
- Explicit external references require a stable contract export; they do not fall back to the legacy
MultiClientConfigSchema + generateClientssurface. - Capability discovery, validation, and planning still run through the same contract as built-in templates.
Legacy package strings still work for backwards compatibility, but the explicit provider: "external" form is the recommended path for new integrations.
Stable Template Contract
Built-in and external templates now register themselves through a stable template contract:
idanddisplayNamemake template identity explicit inside the CLI registry.capabilityManifestdeclares which features are universal, template first-class, or escape hatches.transformUnifiedConfigowns template-specific translation from the unified GenX API config into native Orval/Kubb config.validateConfigkeeps template-specific validation inside the template boundary.planGenerationderives selected capabilities, package dependencies, and documentation hints before generation.generateClientsremains the template-owned generation lifecycle entrypoint.
The CLI registry resolves built-in templates explicitly instead of branching on template names across the core. Explicit external references load through the same contract and are validated before the CLI accepts them. Legacy package strings can still load through MultiClientConfigSchema + generateClients, but unified-config translation belongs to templates that export genxTemplate.
External Template Contract
An external template should provide:
- Template identity:
id,name,displayName, and anyaliasesit wants to claim. - Capability manifest:
capabilityManifest.summaryplus capability entries that classify ownership asuniversal,template-first-class, orescape-hatch. - Validation hooks:
schemafor structural parsing andvalidateConfigfor template-specific guardrails. - Config transformation:
transformUnifiedConfigwhen the template accepts the shared GenX API unified config. - Generation hook:
generateClientsas the template-owned execution entrypoint. - Dependency planning:
planGenerationshould declare selected capabilities plus the dependency plan for the generated package. - Output metadata or documentation hints:
planGeneration.outputandplanGeneration.documentationHintswhen the template wants CLI plans and generated READMEs to explain package boundaries or follow-up steps.
The CLI now validates capability manifests and ensures planGeneration.selectedCapabilities only references capabilities declared in the manifest. That keeps external templates inside the same discovery and reporting model as first-party templates.
Capability Ownership
Template manifests classify capabilities into three groups:
universalmeans GenX API core owns the user intent and lifecycle, while templates map that intent into generator-native config. Examples: contract inputs, output layout,httpClient,baseUrl.template-first-classmeans the feature is generator-specific but intentionally promoted as a documented part of that template surface. Examples: Orvalclient/mode/mock, Kubb plugin-client / plugin-ts / plugin-oas behaviour.escape-hatchmeans the template owns the capability entirely and GenX API keeps it explicit without pretending it is universal. Examples: local scaffold overrides, template variables, raw Kubb plugin pass-through.
This keeps the core generic while preserving generator richness where it belongs.
Choose the Right Path
Built-in template
Use a built-in template when Orval or Kubb already cover the generator you need and you want the narrowest maintenance surface.
External template
Use an external template when your team owns a different generator or needs package-assembly behaviour that does not belong inside GenX API core.
Escape hatch
Use escape hatches when you still want a built-in template but need local scaffold tweaks or generator-native pass-through:
project.templateOptions.pathswaps the scaffold files used by the selected template.project.templateOptions.variablesinjects template-local placeholder values.- Template-native pass-through such as Kubb plugin overrides stay inside that template boundary.
Escape hatches do not create a new template contract. They customise an existing template.
Current vs Planned
Current:
- First-party Orval and Kubb templates.
- Unified config mapped into those templates through template-owned translation.
- Built-in template registry with explicit capability manifests and dependency planning.
- Explicit external template loading through a stable contract.
- Legacy package-string loading for older custom templates.
Planned:
- Additional first-party templates and richer ecosystem support in later phases.
- A separate authoring SDK can still be extracted later if the contract proves stable enough to freeze independently from
@genxapi/cli.
Authoring and Adoption Guides
Consumer Boundary Reminder
Consumers should import the generated package boundary, not generator internals. Good examples:
import { pets } from "petstore-sdk";
Bad examples:
import { getPets } from "./src/pets/client";
import "../../generated/petstore-sdk/dist/index.js";