# How the Typed API Client Library Is Generated for Kaneo: OpenAPI to TypeScript Pipeline

> Discover how Kaneo automatically generates its typed API client library from OpenAPI specs using openapi-typescript and Hono for compile-time type safety.

- Repository: [kaneo.app/kaneo](https://github.com/usekaneo/kaneo)
- Tags: internals
- Published: 2026-08-30

---

**Kaneo generates its typed API client library automatically from an OpenAPI specification using `openapi-typescript`, then wraps the generated types in a lightweight Hono client that provides compile-time type safety for all API operations.**

The Kaneo project (`usekaneo/kaneo`) maintains a type-safe API client that React applications and external consumers import as `@kaneo/libs`. Rather than maintaining handwritten type definitions that drift out of sync with the backend, the typed API client library is generated directly from the OpenAPI specification, ensuring zero-runtime-overhead type safety across the entire stack.

## The OpenAPI-to-TypeScript Generation Pipeline

### OpenAPI Specification Source

The single source of truth for the API surface resides in [`apps/docs/openapi.json`](https://github.com/usekaneo/kaneo/blob/main/apps/docs/openapi.json). This file is produced from Hono route definitions in [`apps/api/src/openapi.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/openapi.ts) that use the `@hono/zod-openapi` library to attach Zod schemas to each route. Keeping the specification in a JSON file allows the codebase to treat it as a stable contract between the backend implementation and the client types.

### TypeScript Declaration Generation

The `packages/libs` workspace automates type generation through a dedicated npm script. In [`packages/libs/package.json`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/package.json), the `gen:libs` script executes:

```json
"scripts": {
  "gen:libs": "openapi-typescript apps/docs/openapi.json --output packages/libs/src/openapi.d.ts"
}

```

This command processes the canonical spec and outputs [`packages/libs/src/openapi.d.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/openapi.d.ts), a declaration file containing fully typed representations of every request payload, query parameter, and response shape. Because this file contains only type declarations, it adds zero bytes to the JavaScript bundle while providing full IntelliSense support in IDEs.

### Hono Client Wrapper

The generated types are consumed by a minimal wrapper located in [`packages/libs/src/hono.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/hono.ts). This module imports the `paths` type from the generated declarations and creates a `client` instance typed against the OpenAPI specification:

```typescript
import { Hono } from "hono";
import type { paths } from "./openapi";

export const client = new Hono<paths>();
export const windowId = "kaneo-client";

```

The wrapper integrates with `resolveApiBaseUrl` from [`packages/libs/src/api-url.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/api-url.ts) to handle runtime URL resolution while maintaining strict compile-time constraints on all request paths and payloads.

## Key Files in the Generation Architecture

- **[`apps/docs/openapi.json`](https://github.com/usekaneo/kaneo/blob/main/apps/docs/openapi.json)** – The canonical OpenAPI specification generated from Hono route definitions using `@hono/zod-openapi`.
- **[`apps/api/src/openapi.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/openapi.ts)** – Source file containing the Zod-annotated Hono routes that produce the OpenAPI output.
- **[`packages/libs/src/openapi.d.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/openapi.d.ts)** – Auto-generated TypeScript declarations produced by the `openapi-typescript` tool.
- **[`packages/libs/src/hono.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/hono.ts)** – Hono client factory that imports the generated `paths` type and exports the typed `client` instance.
- **[`packages/libs/src/api-url.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/api-url.ts)** – Utility function `resolveApiBaseUrl` for determining API endpoints across different environments.
- **[`packages/libs/src/index.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/index.ts)** – Public API surface that re-exports `client`, `resolveApiBaseUrl`, and `windowId` for consumers.

## Using the Generated Typed Client

Consumers import the fully typed client from `@kaneo/libs`. The TypeScript compiler validates request parameters and response types against the OpenAPI specification at build time, catching mismatches before runtime.

### Fetching Workspace Data

```typescript
import { client } from "@kaneo/libs";

async function listWorkspaces() {
  const resp = await client.get("/workspace");
  const workspaces = await resp.json(); // Typed as Workspace[]
  return workspaces;
}

```

### Creating Resources with Typed Payloads

```typescript
import { client } from "@kaneo/libs";

async function createTask(projectId: string, title: string) {
  const resp = await client.post("/task/{projectId}", {
    json: { title },
    params: { projectId },
  });

  const task = await resp.json(); // Type: Task (from generated OpenAPI types)
  return task;
}

```

### Configuring Custom API Endpoints

```typescript
import { resolveApiBaseUrl, client } from "@kaneo/libs";

const apiUrl = resolveApiBaseUrl({ apiUrl: "https://api.my-kaneo.com" });
client.baseURL = apiUrl;

```

## Build Automation and Type Synchronization

The generation process integrates with the workspace build system to prevent type drift. Running `pnpm build` in the `libs` workspace triggers `npm run gen:libs` first, guaranteeing that [`packages/libs/src/openapi.d.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/openapi.d.ts) always reflects the current API surface defined in [`apps/docs/openapi.json`](https://github.com/usekaneo/kaneo/blob/main/apps/docs/openapi.json).

This automation ensures that any modification to the Hono routes in [`apps/api/src/openapi.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/openapi.ts) cascades through to the TypeScript declarations before the library compiles. Developers never need to manually update client types when adding new endpoints or changing request schemas.

## Summary

- **Single Source of Truth**: The OpenAPI specification in [`apps/docs/openapi.json`](https://github.com/usekaneo/kaneo/blob/main/apps/docs/openapi.json) drives all client types.
- **Automatic Generation**: The `openapi-typescript` tool produces [`packages/libs/src/openapi.d.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/openapi.d.ts) via the `gen:libs` npm script.
- **Type-Safe Wrapper**: [`packages/libs/src/hono.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/hono.ts) wraps generated types in a Hono client instance with runtime URL resolution via `resolveApiBaseUrl`.
- **Zero Runtime Overhead**: Generated files contain only TypeScript declarations; network logic remains in the lightweight Hono wrapper.
- **Build Integration**: The `pnpm build` command regenerates types automatically, ensuring synchronization between API implementation and client library.

## Frequently Asked Questions

### How does Kaneo keep the API client types synchronized with the backend?

Kaneo uses a build-time generation pipeline. The `gen:libs` script in [`packages/libs/package.json`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/package.json) runs `openapi-typescript` against [`apps/docs/openapi.json`](https://github.com/usekaneo/kaneo/blob/main/apps/docs/openapi.json) before compilation. This ensures the TypeScript declarations in [`packages/libs/src/openapi.d.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/openapi.d.ts) always match the current Hono route definitions in [`apps/api/src/openapi.ts`](https://github.com/usekaneo/kaneo/blob/main/apps/api/src/openapi.ts), eliminating manual type maintenance.

### Can I use the Kaneo typed client in a non-React project?

Yes. The `@kaneo/libs` package exports framework-agnostic utilities including the typed `client` instance, `resolveApiBaseUrl` for URL configuration, and `windowId` constants. Any TypeScript project can import these to make type-safe API calls using the Hono client pattern without React dependencies.

### What tool generates the TypeScript definitions from OpenAPI?

The project uses `openapi-typescript`, an open-source CLI tool that converts OpenAPI 3.x specifications into TypeScript declaration files. Kaneo invokes this tool via the `gen:libs` script, outputting to [`packages/libs/src/openapi.d.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/openapi.d.ts) to provide compile-time type checking for all API operations defined in the spec.

### Where is the API base URL configured in the typed client?

URL resolution logic lives in [`packages/libs/src/api-url.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/api-url.ts). The `resolveApiBaseUrl` function determines the appropriate API endpoint from environment variables or explicit configuration objects. The Hono client in [`packages/libs/src/hono.ts`](https://github.com/usekaneo/kaneo/blob/main/packages/libs/src/hono.ts) consumes this resolver to set `client.baseURL` while maintaining full type safety for all routes defined in the generated `paths` interface.