pyrpc has grown to 7 packages, 30+ internal components, and 4 framework adapters. Understanding how it all fits together means bouncing between READMEs, docstrings, and source files. We wanted a single source of truth for the architecture — one that stays in sync with the code, is reviewable in PRs, and can be explored interactively.
We found it in LikeC4 — an open-source tool that treats architecture as code. LikeC4 uses the C4 model (Context, Container, Component, Code) to describe systems at multiple levels of detail. You write plain-text .c4 files, and LikeC4 renders them as interactive diagrams.
Why architecture-as-code matters
Traditional architecture documentation (draw.io, Excalidraw, Google Slides) has a fundamental problem: it lives outside the codebase. When the code changes, the diagrams get stale. Nobody updates them because that means finding the source file, opening the right tool, and manually dragging boxes around.
Architecture-as-code fixes this:
- Version-controlled —
architecture/pyrpc.c4lives in the repo alongside the code - PR-reviewable — changes to the architecture ship with the code that causes them
- Multi-level — one file describes the system landscape, containers, components, and dynamic flows
- Interactive —
npx likec4 start architectureopens a browser with navigable diagrams
What we built
We installed LikeC4 as an npm dev dependency and created a single 580-line architecture/pyrpc.c4 file. It contains:
- 5 element kinds — actor, system, container, component, storage
- 30+ model elements — every package, subpackage, and key class
- 25+ relationships — data flows, HTTP calls, function invocations
- 5 static views — system landscape, containers, core internals, codegen pipeline, client internals, adapter comparison
- 3 dynamic views — RPC call flow, codegen flow, dev loop flow
How the C4 model maps to pyrpc
The C4 model defines four abstraction levels. Here's how we mapped pyrpc:
- Level 1: System Landscape — Python Developer, TypeScript Developer, JSON-RPC 2.0 Protocol, and pyrpc as a black-box system.
- Level 2: Container Diagram — All 7 packages (pyrpc-core, pyrpc-fastapi, pyrpc-flask, pyrpc-django-adapter, pyrpc-codegen, @pyrpc/client, @pyrpc/types) with their HTTP and function-call relationships.
- Level 3: Component Diagrams — Deep dives into pyrpc-core (Router, Procedure, Interpreter, CLI, ASGI, 10 components total), pyrpc-codegen (5-component pipeline), and @pyrpc/client (Proxy dispatch, CLI sync, postinstall).
- Dynamic Views — Sequence-style diagrams showing the RPC call flow, code generation pipeline, and dev loop workflow.
What we learned from the exercise
The process of writing the diagrams had me having an overview of the big picture of pyrpc:
The adapter pattern is beautifully consistent. Each adapter — mount_fastapi(), mount_flask(), mount_django(), PyRPCAsgiApp — follows the exact same "thin shell" pattern: translate HTTP into handle_request() calls, zero protocol logic. The Flask adapter uniquely uses anyio.run() to bridge sync Flask to the async interpreter.
The codegen pipeline has a hidden npm dependency. generate_typescript_client() depends on the jsonschema_ts npm package for converting Pydantic JSON schemas to TypeScript interfaces — but this dependency only exists at generation time. Meanwhile, the standalone Node.js CLI (cli.js) duplicates the type conversion logic because it must work without Python installed.
The dev loop is a state machine. The pyrpc dev command isn't just starting a server. It's 12 steps: read config → import module → watch files → debounce changes → reload module → regenerate types → update console. Mapping this as a dynamic view revealed the full complexity.
How to explore the diagrams
# Start the interactive LikeC4 server npx likec4 start architecture # Or build static HTML npx likec4 build architecture --output-dir architecture/dist
Open http://localhost:5173 and start with the System Landscape view for the big picture, then zoom into the Container Diagram, then drill into specific packages.
Read the next post in this series for a guided visual tour of every diagram.

pyRPC