# How the Proto-First API Contract System Generates TypeScript Clients and OpenAPI Docs in World Monitor

> Learn how the proto-first API contract system in World Monitor generates TypeScript clients and OpenAPI docs from Protocol Buffer definitions using buf generate and custom protoc plugins.

- Repository: [Elie Habib/worldmonitor](https://github.com/koala73/worldmonitor)
- Tags: how-to-guide
- Published: 2026-03-09

---

**The proto-first API contract system in koala73/worldmonitor uses `buf generate` with three custom `sebuf` protoc plugins to transform Protocol Buffer definitions into typed TypeScript clients, server interfaces, and OpenAPI 3.1 specifications from a single source of truth.**

The koala73/worldmonitor repository implements a **proto-first API contract system** that elevates Protocol Buffer schemas to the canonical source for all API artifacts. By defining services, messages, and HTTP bindings in `.proto` files, the system automatically generates type-safe client libraries and comprehensive API documentation through an automated build pipeline.

## The Proto-First Architecture

### Single Source of Truth in Proto Definitions

All public API contracts reside in the `proto/` directory, following the convention `proto/worldmonitor/<service>/v<version>/service.proto`. These files contain:

- **Message schemas** with `buf.validate` field constraints (e.g., latitude ∈ [-90, 90]) that enable automatic request validation
- **Service definitions** declaring RPC methods with their input and output types

### Sebuf HTTP Annotations and Validation

The system extends standard protobuf with custom `sebuf` HTTP annotations (`option (sebuf.http) = {...}`) that specify:

- HTTP method mappings (typically POST)
- Endpoint paths
- Request/response body schemas
- Example payloads for documentation

These annotations bridge the gap between protobuf's binary RPC model and RESTful HTTP APIs, while `buf.validate` constraints ensure field-level validation rules propagate to all generated artifacts.

## The Generation Pipeline

### Build Configuration and Plugins

The generation process centers on [`proto/buf.gen.yaml`](https://github.com/koala73/worldmonitor/blob/main/proto/buf.gen.yaml), which configures three custom `sebuf` protoc plugins:

```yaml
plugins:
  - local: protoc-gen-ts-client
    out: ../src/generated/client
    opt:
      - paths=source_relative
  - local: protoc-gen-ts-server
    out: ../src/generated/server
    opt:
      - paths=source_relative
  - local: protoc-gen-openapiv3
    out: ../docs/api
  - local: protoc-gen-openapiv3
    out: ../docs/api
    opt:
      - format=json

```

The first two plugins generate TypeScript source files, while the third produces both YAML and JSON OpenAPI specifications.

### Makefile Automation

The `Makefile` target (lines 55-58) orchestrates the build:

```make
generate: clean ## Generate code from proto definitions

	@mkdir -p $(GEN_CLIENT_DIR) $(GEN_SERVER_DIR) $(DOCS_API_DIR)
	cd $(PROTO_DIR) && buf generate
	@echo "Code generation complete!"

```

Running `make generate` executes `buf generate`, which reads the configuration and invokes the plugin chain to populate:
- `src/generated/client/` – Typed client classes
- `src/generated/server/` – Handler interfaces
- `docs/api/` – OpenAPI specifications

## TypeScript Client Generation

### Fetch-Based Client Architecture

The `protoc-gen-ts-client` plugin generates thin, fetch-based client classes that wrap RPC methods. Each generated method:
- Accepts strongly-typed request objects derived from protobuf message schemas
- Serializes the request to the appropriate format
- POSTs to the HTTP endpoint defined by `sebuf` annotations
- Deserializes the response into typed TypeScript objects

### Practical Implementation Example

For the Wildfire service defined in `proto/worldmonitor/wildfire/v1/service.proto`, the generated client resides at [`src/generated/client/worldmonitor/wildfire/v1/service_client.ts`](https://github.com/koala73/worldmonitor/blob/main/src/generated/client/worldmonitor/wildfire/v1/service_client.ts):

```typescript
import { WildfireServiceClient } from '@/generated/client/worldmonitor/wildfire/v1/service_client';

// Initialise with the global fetch implementation (or a custom wrapper)
const client = new WildfireServiceClient(fetch);

// Call an RPC – listFireDetections returns a typed response object
const resp = await client.listFireDetections({
  cursor: '',
  region: 'Ukraine',
  minConfidence: 'FIRE_CONFIDENCE_HIGH',
});

console.log('Detected fires:', resp.detections);

```

The `listFireDetections` method accepts a `ListFireDetectionsRequest` type and returns `Promise<ListFireDetectionsResponse>`, ensuring compile-time validation of request parameters and response handling.

## OpenAPI Documentation Generation

### Dual-Format Specification Output

The `protoc-gen-openapiv3` plugin emits **OpenAPI 3.1** specifications in two formats:
- **YAML** ([`docs/api/WildfireService.openapi.yaml`](https://github.com/koala73/worldmonitor/blob/main/docs/api/WildfireService.openapi.yaml)) for human readability and Swagger UI integration
- **JSON** ([`docs/api/WildfireService.openapi.json`](https://github.com/koala73/worldmonitor/blob/main/docs/api/WildfireService.openapi.json)) for machine consumption and automated tooling

Both formats derive from the same `sebuf` HTTP annotations and protobuf schemas, ensuring documentation accuracy.

### OpenAPI Schema Structure

The generated specifications map protobuf services to RESTful paths with complete schema definitions:

```yaml
openapi: 3.1.0
info:
  title: WildfireService API
  version: 1.0.0
paths:
  /api/wildfire/v1/list-fire-detections:
    post:
      summary: ListFireDetections
      operationId: ListFireDetections
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ListFireDetectionsRequest'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListFireDetectionsResponse'
components:
  schemas:
    ListFireDetectionsRequest:
      type: object
      properties:
        cursor:
          type: string
        region:
          type: string
        minConfidence:
          type: string
          enum:
            - FIRE_CONFIDENCE_UNSPECIFIED
            - FIRE_CONFIDENCE_LOW
            - FIRE_CONFIDENCE_NOMINAL
            - FIRE_CONFIDENCE_HIGH

```

Because these files live under version control in `docs/api/`, consumers can access accurate, up-to-date documentation without additional build steps.

## Contract Safety and Validation

The repository maintains API integrity through automated validation tooling. The `buf lint` command enforces protobuf style conventions, while `buf breaking` (invoked via `make breaking`) analyzes changes against the `main` branch to detect backward-incompatible modifications—such as field number changes or type alterations—before they merge.

This validation ensures that the **proto-first API contract system** never silently breaks consumer contracts. When combined with version-controlled generated artifacts, the system guarantees that TypeScript clients, server interfaces, and OpenAPI documentation reflect exactly the same contract state.

## Quick Implementation Guide

For developers consuming the API, integration requires only three steps:

```typescript
import { TradeServiceClient } from '@/generated/client/worldmonitor/trade/v1/service_client';

// 1️⃣ Create the client
const tradeClient = new TradeServiceClient(fetch);

// 2️⃣ Call an RPC (example: GetTariffTrends)
const trends = await tradeClient.getTariffTrends({
  reportingCountry: '840', // US ISO‑numeric
  productSector: '01',     // HS chapter
  years: 5,
});

// 3️⃣ Use the typed response
console.log('Tariff trend points:', trends.datapoints);

```

This pattern applies identically across all World Monitor services, from Wildfire detection to Trade analytics, ensuring consistent developer experience throughout the koala73/worldmonitor ecosystem.

## Summary

- The **proto-first API contract system** treats Protocol Buffer schemas as the canonical source for all API artifacts in koala73/worldmonitor.
- Three custom `sebuf` protoc plugins (`protoc-gen-ts-client`, `protoc-gen-ts-server`, `protoc-gen-openapiv3`) generate TypeScript clients, server interfaces, and OpenAPI 3.1 specifications via `buf generate`.
- Generated TypeScript clients reside in `src/generated/client/` and provide thin, fetch-based wrappers with compile-time type safety for RPC methods defined in `.proto` files like `proto/worldmonitor/wildfire/v1/service.proto`.
- OpenAPI documentation generates as both YAML and JSON to `docs/api/`, remaining synchronized with the implementation because all artifacts derive from the same protobuf contracts.
- Automated tooling (`buf lint`, `buf breaking`) enforces contract safety, while version-controlled generated artifacts prevent drift between documentation and implementation.

## Frequently Asked Questions

### What is a proto-first API contract system?

A proto-first API contract system is an architectural pattern where Protocol Buffer (protobuf) definitions serve as the single source of truth for all API-related artifacts. In koala73/worldmonitor, `.proto` files containing service definitions, message schemas, and HTTP annotations automatically generate TypeScript client libraries, server handler interfaces, and OpenAPI documentation through the `buf generate` pipeline, ensuring perfect synchronization between code and documentation.

### How does buf generate TypeScript clients from protobuf definitions?

The `buf generate` command reads [`proto/buf.gen.yaml`](https://github.com/koala73/worldmonitor/blob/main/proto/buf.gen.yaml) to invoke the custom `protoc-gen-ts-client` plugin. This plugin processes the protobuf service definitions and `sebuf` HTTP annotations to emit fetch-based TypeScript classes to `src/generated/client/`. Each RPC method becomes a typed class method that serializes protobuf messages, POSTs to the annotated HTTP endpoint, and deserializes responses into TypeScript types, as implemented in files like [`src/generated/client/worldmonitor/wildfire/v1/service_client.ts`](https://github.com/koala73/worldmonitor/blob/main/src/generated/client/worldmonitor/wildfire/v1/service_client.ts).

### What are sebuf HTTP annotations used for?

`sebuf` HTTP annotations are custom protobuf options that map RPC methods to RESTful HTTP endpoints. Defined within `.proto` files using `option (sebuf.http) = {...}`, these annotations specify HTTP methods (typically POST), URL paths, request/response body schemas, and example payloads. The `sebuf` protoc plugins read these annotations to generate HTTP-compatible TypeScript clients and OpenAPI 3.1 specifications, effectively bridging protobuf's binary protocol with web-based REST APIs.

### How are breaking changes detected in the API contracts?

The repository employs `buf breaking`, executed via `make breaking`, to compare proposed changes against the `main` branch before merging. This command analyzes `.proto` files for backward-incompatible modifications such as field number changes, type alterations, or required field additions that would break existing clients. Combined with `buf lint` for style enforcement, this validation ensures that the proto-first API contract system maintains backward compatibility or explicitly versions breaking changes.