Framework Integrations
Apical TS works best as a contract-first generator: you describe the API once in OpenAPI, then let every integration consume the generated artifacts instead of re-declaring paths, params, and response shapes for each framework.
The main reusable outputs are:
generated/routes/*: route metadata plus request/response schemasgenerated/server/*: typed request-validation wrappers for explicit server integrationsgenerated/client/*: typed operation functions for frontend and SDK usage
Static vs Dynamic Route Usage
Different integrations reuse the same contract in different ways:
| Style | Generated input | Example | What you write |
|---|---|---|---|
| Static, wrapper-based | --server (server/ + routes/) | Express | explicit framework route registration and business handlers |
| Dynamic, metadata-driven | --routes (or the routes/ emitted alongside --client/--server) | Hono | a second generator or adapter that derives framework glue from route metadata |
| Dynamic, contract-derived consumers | --client or --server, plus routes/ | React Query, MSW | hooks, mock handlers, and utilities generated from the same operations |
The important part is that the OpenAPI contract stays the single source of truth no matter which style you choose.
Example Integrations
We provide complete working examples in the
examples/ folder:
Express: explicit wrapper-based integration
The
Express example
shows the more static style: generate --server, then register each route in
Express with the generated wrapper.
What it demonstrates
- request/response validation from generated wrappers
- explicit route registration with framework-specific adapters
- custom business logic without redefining the API contract
createExpressAdapter(getPetByIdRoute(), getPetByIdHandler)(app);
Hono: route-metadata-driven generation
The Hono example
shows the more dynamic style: generate --routes, then run a second generator
that turns route metadata into a Hono registration layer.
What it demonstrates
- route-metadata-driven code generation
- automatic request validation for path, query, headers, and body
- zero manual remodelling of endpoints when switching from Express to Hono
registerGeneratedRoutes(app);
React Query: hooks derived from generated operations
The
React Query example
shows how the same contract can feed frontend hooks. Apical generates the client
and routes once, then a secondary generator emits useX and useXMutation
hooks from those artifacts.
What it demonstrates
useXhooks for GET/HEAD operationsuseXMutationhooks for write operations- type inference from generated client operations and route methods
const { data, isLoading, error } = useFindPetsByStatus({
query: { status: ["available"] },
});
MSW: mock handlers derived from generated wrappers
The MSW example shows a dynamic mock integration. It iterates the generated operations, creates one MSW handler per route, and still reuses the generated wrapper validation and response maps.
What it demonstrates
- dynamic handler registration from generated operations
- request validation aligned with the OpenAPI contract
- mock payload generation from response schemas via
zocker
const handlers = Object.values(routes).map((routeFn) => {
const routeInfo = routeFn();
return createMswHandler(routeInfo, createMockHandler(routeInfo));
});
Adapting to Other Frameworks
Once you have generated routes/, server/, or client/, every other
integration follows the same pattern:
- Import the generated contract artifacts
- Derive framework-specific adapters, handlers, or hooks from those artifacts
- Keep framework code thin and avoid redefining API models by hand
That is the main advantage of the contract-first flow: you can swap or add integrations without remodeling the API every time.
Getting Started
To explore these integrations:
- Clone the repository
- Navigate to the desired example:
cd examples/[framework] - Install dependencies:
pnpm install - Generate the code:
pnpm run generate - Run the example using the command documented in that example's README
Each example README now documents which generated artifacts it consumes and how to extend that integration without breaking the contract-first workflow.