rust-architecture
Skill0 starsChanged 8 months agoMITView on GitHub
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.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- JSBtechnologies/rustkbtheir own version, first seen Oct 11, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- JSBtechnologies/rustkb★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository16 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- rust-apiSkill
- rust-asyncSkill
- rust-ci-deploySkill
- rust-databaseSkill
- rust-dddSkill
- rust-errorsSkill
- rust-macrosSkill
- rust-ownershipSkill
- rust-perfSkill
- rust-qualitySkill
- rust-serdeSkill
- rust-testsSkill
- rust-tracingSkill
- rust-typesSkill
- rust-unsafeSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 4 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 48
Start with the application type:
- Distinctive: line 80
Delete a feature = delete its directory.
- Distinctive: line 84
Start with one crate. Split to workspace only when compile times or team size demand it.
- Distinctive: line 85
When in doubt, duplicate between slices rather than coupling them with a shared abstraction.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
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 |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

