The Problem We Solved

In a traditional setup, API contracts drift between backend and frontend: the Rust team writes structs, the TypeScript team writes matching types, and they diverge silently. We eliminated this entirely.

Before: 3 Sources of Truth

Hand-written Rust structs + hand-written TypeScript types + an OpenAPI doc nobody keeps in sync.

After: 1 Source of Truth

One .smithy model file generates everything — Rust server traits, TypeScript SDK, and DTO types.

Zero Drift

If the Smithy model doesn’t compile, nothing builds. Contract mismatch caught at compile time, not runtime.

Codegen Pipeline Diagram


Step-by-Step

1

Define the contract in Smithy IDL

API shapes, operations, and errors are described once in .smithy files under smithy/model/. The service is com.aarokya.api#AarokyaService.
@restJson1
service AarokyaService {
    version: "2025-01-01"
    operations: [TriggerOtp, VerifyOtp, GetWallet, ...]
}

@http(method: "POST", uri: "/auth/otp/trigger")
operation TriggerOtp {
    input: TriggerOtpInput
    output: TriggerOtpOutput
    errors: [ValidationException, InternalServerError]
}
2

Generate the Rust server (smithy-rs)

cd smithy
smithy build --projection server-rust
Produces the aarokya_server_api Rust crate with generated handler traits. Your Actix-web handlers implement these traits — the compiler enforces the contract.
3

Generate the TypeScript client

cd smithy
smithy build --projection client-typescript
# Then patch tsconfig for Yarn 4 compatibility:
node scripts/patch-typescript-client-tsconfig.mjs
Produces @aarokya/api-client — a fully typed npm package. The Expo app consumes it directly via a file: dependency path.
4

Generate DTO types (Rust + TypeScript)

cd smithy-codegen
cargo run --release -- \
  --model ../smithy/build/smithy/server-rust/model/model.json
Outputs:
  • backend/smithy-api-model-generated/dto-rust/dto.rs
  • backend/smithy-api-model-generated/dto-ts/api.ts
5

OpenAPI docs (separate, from Rust annotations)

The Rust backend uses utoipa to generate OpenAPI 3.1 from code annotations. This powers the Swagger UI at /api_docs/ui and is independent of the Smithy codegen pipeline.
GET /api_docs/openapi.json  raw OpenAPI spec
GET /api_docs/ui  Swagger UI

Build Matrix

ProjectionMaven PluginOutputUsed By
server-rustsmithy-rs:codegen-server:0.1.6Rust crate with server traitsActix-web backend
client-typescriptsmithy-aws-typescript-codegen:0.47.0npm package @aarokya/api-clientExpo React Native app
(codegen binary)cargo run (Rust binary)dto.rs + api.tsBoth ends

Why No OpenAPI in Codegen?

Smithy generates Rust server code and TypeScript clients directly, bypassing OpenAPI entirely in the codegen path. OpenAPI is only generated from Rust code annotations (via utoipa) — separately — for documentation/developer tooling purposes.This means the Smithy model is the authoritative contract, not an OpenAPI document that could drift.
See ADR-001: Smithy as IDL and ADR-002: Rust Stack for the full reasoning.