What is Smithy?

Smithy is an Interface Definition Language (IDL) created by AWS. You write your API contract once in .smithy files, and tools generate code for multiple languages from that single definition. In this project, Smithy is the single source of truth for:
  • Rust backend DTOs (request/response types)
  • Shared enums used across the backend (Gender, Currency, AccountStatus, MandateStatus, etc.)
  • TypeScript interfaces for the frontend
  • Zod runtime validation schemas (optional)

The Files You’ll Work With

Smithy Models (you edit these)

Generated Code (never edit these manually)


How the Pipeline Works

The Big Picture

Step 1: You Write Smithy

A Smithy file defines what your API looks like — the operations, inputs, outputs, and errors:
The @rust* traits are codegen hints — they tell our custom code generator how to produce the Rust output. They don’t affect the Smithy model itself.

Step 2: just gen Runs the Pipeline

Internally, the codegen tool:
  1. Parses model.json — classifies each shape as Structure, Enum, List, Map, or Skipped
  2. Reads codegen traits@rustDerives, @rustSecret, @rustRename, @rustCrate, etc.
  3. Groups by module — shapes go into auth.rs, user.rs, etc. based on namespace
  4. Topologically sorts — ensures a struct is defined before another struct references it
  5. Emits code — generates Rust structs/enums and TypeScript interfaces

Step 3: What Gets Generated

From this Smithy input:
Rust output (api_models/src/auth.rs):
TypeScript output (sdk.ts):
Notice:
  • @rustRename changed the struct name
  • @rustSecret wrapped phone_number in Secret<T> (Rust only — TS has no equivalent)
  • camelCase member names are lowered to snake_case automatically (these members are already snake_case)
  • Optional fields (without @required) get Option<T> in Rust and ?: in TypeScript

Codegen Traits

Traits are annotations on Smithy shapes that control code generation. They’re defined in codegen-traits.smithy.

The Most Important Traits


Shared Enums: The @rustCrate Flow

Enums like Gender, Currency, AccountStatus, MandateStatus are used across many backend crates — not just api_models. They live in the common_enums crate. The key: @rustCrate has dual behavior. When generating api_models, it acts like “import this from another crate”. When generating common_enums (via --common-enums-out), it generates the actual enum code.

The Codegen Tool Architecture

Key Source Files


Developer Workflow

Adding a New Field

Adding a New Shared Enum

Adding a New API Domain

  1. Create smithy/model/new_domain.smithy
  2. Define resource, operations, structures with codegen traits
  3. Register resource in main.smithy
  4. Run just gen
  5. New module appears in api_models/src/new_domain.rs

Testing & CI

Two Layers of Protection

Snapshot tests catch bugs in the emitter code itself. They use fake test data and compare emitter output against saved .snap files. Your Smithy model changes don’t affect these tests — they only break if someone modifies the emitter functions. gen-check catches forgotten regeneration. It runs the full pipeline and diffs the output against what’s committed. If you edited a Smithy file but forgot just gen, CI catches it.

CI Pipeline


Quick Reference

Commands

File Ownership