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

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, which configures three custom sebuf protoc plugins:

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:

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:

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:

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:

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:

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 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.

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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →