Rust architecture
Curated Rust skill files for Claude Code: ownership, async, errors, types, architecture, DDD, and more
npx -y skills add dawidpereira/rust-skills --skill rust-architectureAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Rust project architecture patterns — vertical slice architecture for web APIs, component-based TUI structure for Ratatui apps, and cross-feature communication strategies. Use when organizing features into slices, wiring routes and services, choosing how features communicate, structuring a Ratatui terminal application, or deciding between single-crate and workspace layouts. Also use when setting up a new Axum/Actix-web project structure or adding a new feature to an existing sliced codebase.
SKILL.md
7.5 KB, as published. Nobody here has run it
Architecture
Core Question
How should this project's modules, boundaries, and data flow be organized so that adding a feature means changing one place?
The right architecture makes features independently addable, deletable, and testable. The wrong one scatters a single change across the entire codebase.
Quick Decisions
| Situation | Reach For | Why |
|---|---|---|
| Web API with distinct features | Vertical Slice Architecture | Each feature is self-contained |
| Complex read vs write models | VSA + CQRS variant | Separates command and query paths within a slice |
| Large API, team-per-feature | VSA workspace layout | Compile-time boundaries, independent deps |
| Terminal UI with interactive views | TUI component-based (Ratatui) | Each component owns state, rendering, input |
| TUI app with business logic / data layers | TUI components + vertical slices | Feature slices own their components, services, and models |
| Feature needs data from another | Cross-slice communication | Pick the lightest strategy that works |
| Custom request validation | Axum extractor (FromRequestParts) | Compile-time enforced, reusable across handlers |
| Per-request context (user, tenant, correlation ID) | RequestContext extractor | Single struct, extracted once, threaded through layers |
| Simple middleware (logging, auth) | axum::middleware::from_fn | Minimal boilerplate, async-friendly |
| Middleware ordering | outermost = first executed | CORS and tracing before auth, auth before handlers |
| Shared state (DB pool, config) | State<AppState> with FromRef | Compile-time checked, no runtime downcasting |
| Route-specific auth | .route_layer(middleware::from_fn(require_auth)) | Protects only routes in that group |
| Request/response transformation | Tower Layer implementation | Full control over Service wrapping |
| Project has < 10 source files | Don't architect — flat structure | See rust-quality → Quick Decisions |
Architecture Selection
Start with the application type:
- Web API → Vertical slices. Single crate for < 15 features, workspace for more. If reads and writes have very different shapes, add CQRS within the slice.
- Terminal UI → Component-based. Each screen or widget is a component with init/update/draw. If the app has data persistence or distinct feature domains, combine with vertical slices — each feature owns its components alongside service/model/repository.
- Library → Feature-based modules. See rust-quality for module organization patterns.
- CLI tool → Flat or feature-based depending on size. See rust-quality for thresholds.
Then consider domain complexity:
- Simple CRUD → Standard VSA slice (handler, service, model, repository, dto, routes, tests).
- Complex domain logic → VSA + CQRS commands/queries within each slice.
- Rich domain model → DDD building blocks within VSA slices. See rust-ddd skill for aggregates, value objects, events, repository separation.
Key Rules
- One feature = one directory. Never scatter a feature across layers.
- Slices and components never import each other's internals.
- Shared code lives in an explicit
shared/module — infrastructure and config only. - New feature = new directory + register route or component. Nothing else changes.
- Delete a feature = delete its directory. If other code breaks, the boundary leaked.
- Handlers and components stay thin — delegate to services or state logic.
- Each slice or component owns its tests.
- Domain models are the source of truth; DTOs exist for the boundary.
- Start with one crate. Split to workspace only when compile times or team size demand it.
- When in doubt, duplicate between slices rather than coupling them with a shared abstraction.
Usage Scenarios
Scenario 1: "I'm building a new web API with Axum"
→ Start with VSA single-crate layout. Create features/ with one
directory per resource. Wire routes in router.rs, shared
infrastructure in shared/.
Scenario 2: "Feature A needs to read data from Feature B" → Check cross-slice communication strategies. For display: use a read model (SQL JOIN). For business logic: use a public API trait. For async reactions: domain events.
Scenario 3: "I'm building a terminal UI with Ratatui" → Use the component-based structure. Each component implements the Component trait with init/handle_events/update/draw. If the app has data layers or multiple feature domains, combine with vertical slices — each feature owns its components + service + model.
Scenario 4: "My web API has 20+ features and builds are slow" → Graduate to VSA workspace layout. One crate per feature, shared crate for infrastructure. Inherit dependencies and lints from workspace root.
Scenario 5: "My handler knows the authenticated user but my
repository doesn't"
→ Define a RequestContext struct in shared/context.rs, extract
it via FromRequestParts, pass &ctx to services and repository
methods. See references/request-context.md.
Reference Index
| Reference | Read When |
|---|---|
| references/vertical-slices.md | Setting up a web API: slice structure, file responsibilities, root wiring, CQRS variant, workspace layout, shared infrastructure, common dependencies |
| references/cross-slice.md | One feature needs data or behavior from another: 4 strategies (API traits, read models, shared types, domain events) with decision guide |
| references/tui-components.md | Building a Ratatui TUI: component trait, file structure, app loop, state management |
| references/web-middleware.md | Axum extractors (ordering, custom, rejection), tower middleware (from_fn, Layer, ordering), State vs Extension, auth patterns, CORS/compression/rate-limiting |
| references/request-context.md | Threading per-request identity through layers: RequestContext struct, extractor, context-aware repository traits, tenant scoping, audit logging, tracing integration |
| rust-ddd skill | Rich domain models within slices: aggregates, value objects, domain events, repository separation. Use when domain complexity warrants DDD building blocks |
Cross-References
| When | Check |
|---|---|
| Cargo.toml defaults, workspace setup, module organization basics | rust-quality → Quick Decisions |
| Async handler patterns, tokio runtime in web APIs | rust-async → Quick Decisions |
| Error type design for shared error module | rust-errors → Quick Decisions |
| Trait design for service boundaries and API traits | rust-types → Quick Decisions |
| Public API design within slices, naming conventions | rust-api → Quick Decisions |
| Rich domain model, aggregates, value objects, events | rust-ddd → Quick Decisions |
| Request tracing middleware, correlation IDs | rust-tracing → Quick Decisions |
| Rejection/error responses from extractors | rust-errors → Quick Decisions |