Rust Async And Web
Use this skill for async Rust services and full-stack Rust applications. Keep
runtime, HTTP, UI, and persistence boundaries explicit so domain logic remains
testable without the framework. Use
hexagonal-architecture when handlers,
jobs, server functions, message consumers, persistence, or external clients need
formal ports/adapters or shared application use cases.
Load rust-engineering when async/web work also
changes core Rust implementation such as types, ownership, traits, errors,
features, modules, or macros. Do not load it for review-only async/web guidance.
Do not use this skill for API-contract-only work such as endpoint/resource
shape, request/response/error envelopes, versioning, pagination, idempotency, or
OpenAPI/AsyncAPI/protobuf artifacts; use api-design
for those contracts. Do not use it for observability-only work such as
log/metric/trace schemas, context-propagation standards, labels/cardinality,
dashboards, alerts, SLOs, or telemetry sampling; use
observability-engineering. Add this
skill only when the task also changes Tokio, Axum, Leptos, SSR, hydration, WASM,
task, or runtime behavior.
Native desktop GUI implementation is not this skill's primary scope. Use
rust-desktop-gui for iced, egui/eframe, Slint,
Tauri shell, and native event-loop work. Compose with this skill when the GUI
change needs Tokio task, cancellation, channel, or backpressure mechanics, but
never block the GUI event-loop thread.
Workflow
- Inspect the runtime and stack:
Cargo.toml features, tokio runtime setup,
bacon.toml, Justfile/scripts, Axum routers, Leptos/cargo-leptos app and
hydration configuration, server functions, WASM build target,
stylesheet/static asset pipeline, middleware, tracing, and existing test
recipes.
- Define externally observable behavior with BDD-style acceptance criteria.
Keep domain invariants in framework-independent types where practical.
- Design task ownership, cancellation, timeouts, backpressure, shared state,
and error propagation before adding handlers or components.
- Implement narrow vertical slices: domain logic, adapter/handler/server
function, UI or response behavior, and tests.
- Verify the server side, client/WASM side, and hydration/SSR behavior with the
repository's commands.
Security Review Prompts
Load security-review when async/web work
touches auth, authorization, sessions or cookies, CORS/CSRF/CSP, redirects,
SSR/hydration trust boundaries, server functions, uploads/downloads, path
handling, request/response redaction, secrets, external-service calls,
telemetry that may leak sensitive data, or artifact handling. Use
threat-modeling before or during new auth
middleware, request/SSR/server-function boundaries, background workers, queues,
webhooks, external-service integrations, or sensitive data flows. Use
dependency-supply-chain-review
when Tokio/Axum/Leptos or toolchain dependency changes, generated assets, CI
bootstrap, installers, or binaries raise provenance or advisory questions. Pair
security-sensitive reviews with
security-review-evidence when evidence
includes sanitized HTTP traces, logs/spans, browser or server-function payloads,
screenshots, generated assets, or test artifacts.
When To Choose Async Rust
- Use async deliberately for I/O-bound or high-concurrency work: network
servers and clients, database calls, queues, workers, orchestration layers,
file or process I/O with async APIs, and fan-out/fan-in workflows.
- Do not make code async by default. Synchronous Rust is usually clearer for
CPU-bound algorithms, pure domain logic, simple CLIs, low-concurrency tools,
and code where blocking APIs are sufficient.
- Async changes API shape. It affects trait boundaries, dependency injection,
lifetimes,
Send + 'static requirements for spawned work, cancellation,
error propagation, and which tests need a runtime.
- Keep blocking libraries behind explicit boundaries. In an async service, wrap
unavoidable blocking or CPU-heavy work with
tokio::task::spawn_blocking, a
dedicated thread pool, or a separate worker process instead of blocking Tokio
runtime threads.
- Distinguish concurrency from parallelism. Async lets many tasks wait on I/O;
it does not make CPU-heavy work faster unless that work is moved to real
parallel execution.
Architecture Boundaries
- Keep domain logic pure, deterministic, and preferably synchronous. Avoid
leaking Tokio types, channels, timers, task handles, database pools, request
types, or framework state into the domain model.
- Put async I/O at application, infrastructure, adapter, or port boundaries.
Application services/use cases may orchestrate async repositories, clients,
queues, clocks, and external services while domain objects enforce rules.
- Use ports/traits for async dependencies only where the boundary earns it:
repositories, external clients, queues, clocks, id generators, and background
job interfaces. Do not force async into every layer because one adapter is
async.
- Keep Tokio-specific details in infrastructure adapters and process wiring:
runtime flavor, channels, task spawning, cancellation tokens, signal handling,
tracing setup, and adapter-specific retry/timeout policy.
- For async traits, prefer the simplest option the repository supports. Native
async fn in traits can work for static dispatch when the MSRV and auto-trait
bounds fit; use explicit future return types, boxed futures, or async-trait
when object safety, dyn dispatch, or tighter Send control matters.
- Use BDD examples at the system, inbound adapter, or use-case boundary; TDD
domain rules with sync unit tests; test async application services with fakes;
and test real adapters with
#[tokio::test] integration tests.
Tokio Runtime, Coordination, And Cancellation
Use the Tokio runtime reference when the task
requires runtime construction, spawning, coordination primitives, cancellation,
or graceful shutdown. Keep the core constraints visible: never block runtime
threads, give every task an owner and shutdown path, bound concurrency and
queues, and treat cancellation as real control flow.
Local CPU Parallelism Routing
Compose with parallelism-engineering
when an async/web application must redesign a local CPU-bound workload around
data or task decomposition, partition sizing, bounded executor ownership,
deterministic reduction, cancellation, or nested-parallelism control. That skill
owns the parallel design; this skill owns the Tokio integration, such as keeping
blocking CPU work off runtime threads and applying the chosen design through
Rust runtime APIs.
Do not route ordinary Tokio scheduling, async I/O, channels, task lifetimes,
timeouts, backpressure, or Axum/Leptos concurrency to
parallelism-engineering; they remain here. Spark/PySpark execution belongs to
data-platform-engineering, not this
local parallelism handoff.
WebAssembly Routing
Compose with webassembly-engineering
when async/web work includes a general WebAssembly decision: a WAT or .wasm
artifact, WASI or WIT, the Component Model, host/guest contract, runtime or
target selection, capability grants, or Wasm packaging and deployment. That
skill owns those Wasm boundary and compatibility decisions. This skill retains
Leptos, wasm-bindgen, Cargo, Rust target compilation, SSR/hydration, browser
framework, host-integration, and test mechanics; the Wasm skill does not
establish their source-level or framework support.
Axum
- Keep routers, handlers, extractors, state, and middleware thin. Move domain
decisions into services or domain modules that can be tested without HTTP.
- Use typed extractors for inputs and
State/substates for application state.
Store shared state in Arc when it must be cloned into handlers.
- Convert domain and adapter errors into HTTP responses at the edge. Avoid
leaking database, framework, or internal error details to clients. Use
api-design when status codes, error envelopes,
route shapes, or request/response payloads are contract decisions.
- Validate payload size, content type, authentication, authorization, and input
shape before invoking domain behavior.
- Prefer Tower middleware or extractors for cross-cutting HTTP concerns such as
tracing, auth, timeouts, compression, and request ids.
- Expose application assembly separately from listener startup so tests can
construct the
Router with controlled state.
- Test HTTP semantics by calling the router as a Tower service with
tower::ServiceExt::oneshot; assert status, relevant headers, and a bounded or
collected response body. Cover extractor rejection, middleware, error mapping,
and state wiring where those behaviors matter.
- Use pure or application-service tests when routing adds no behavior. Bind a
loopback listener on port
0 only when the test requires real transport,
connection metadata, protocol behavior, or client/server integration.
Leptos And Axum-Leptos
For a technical-debt audit of an Axum + Leptos SSR application, read the
Axum + Leptos technical-debt audit reference
before selecting commands or diagnosing hydration, feature-gating, route, or
multi-instance concerns.
- Decide whether behavior belongs in CSR, SSR, server functions, actions,
resources, or ordinary backend routes. Keep security-sensitive work on the
server.
- Server functions are trust boundaries. Validate input, authorization, and
idempotency server-side even when the client UI already checks them.
- Components should keep state derivation clear. Avoid burying domain rules in
signal plumbing when a normal Rust function or type can own the rule.
- SSR and hydration must render compatible markup. Avoid browser-only APIs,
nondeterministic values, or time-dependent output during server rendering
unless guarded for the target.
- WASM code should avoid unavailable server APIs and large unnecessary
dependencies. Check crate features and target-specific modules.
- Axum-Leptos integrations should keep router state, server function context,
static assets, fallback handling, and error pages explicit.
- Test framework-independent component and application logic with ordinary host
Rust tests. Test SSR output, server functions, and backend routes through the
server application with the repository's server-side features enabled.
- Test browser-targeted components with
wasm-bindgen-test or the repository's
established WASM harness when DOM-level behavior is the narrowest useful
boundary. Match the runner and browser mode to the pinned toolchain.
- Test hydration, navigation, forms, and other user-visible full-stack behavior
in a real browser. Load
playwright-e2e when
adding or changing checked-in Playwright tests.
Leptos-Use
- Consult the current Leptos-Use documentation and the
repository's pinned Leptos and
leptos-use versions before using an API.
Consider the crate before hand-writing reusable reactive wrappers for browser
events, media queries and preferences, storage, observers, timers, sensors,
streams, or other Web APIs. Prefer native Leptos or direct web-sys code when
the behavior is small, unsupported, or clearer without another abstraction.
- Inspect each function's documented SSR behavior; server fallbacks vary by
utility. Use SSR-safe targets such as
use_window() and use_document()
instead of accessing browser globals during server rendering, and verify that
fallback values cannot produce incorrect initial markup or hydration mismatches.
- In an SSR application, enable
leptos-use/ssr through the application's
server-only feature, not globally on the dependency. Inspect function-level
crate features and avoid shipping unused defaults when WASM size or compile
time matters, while preserving the repository's established feature policy.
- Prefer utilities that bind cleanup to the Leptos owner for listeners,
observers, timers, and streams. Retain and call returned cleanup, pause, stop,
or close controls when behavior must end before owner cleanup; confirm any
same-thread restrictions in the selected API's documentation.
- Treat local/session storage as user-visible, origin-scoped client state, not
trusted or secret storage. Account for decoding failures, unavailable storage,
cross-tab updates, and hydration timing. For permissions and sensors, handle
unsupported, denied, unavailable, and paused states rather than assuming a
successful browser API call.
Load css-scss-styling when Leptos/Axum work
touches .css, .scss, .sass, stylesheet entrypoints, Trunk/cargo-leptos
style assets, class/style bindings, design tokens, responsive layout, CSS
modules, or browser-visible cascade behavior. Keep this skill focused on Rust
runtime, SSR, hydration, server functions, routing, and WASM constraints.
Development And Commands
Prefer repository scripts for full-stack apps because they often manage CSS,
WASM, assets, environment, and services.
For an ordinary long-running Axum service, use a checked-in Bacon job when the
repository adopts Bacon:
[jobs.server]
command = ["cargo", "run"]
need_stdout = true
background = false
Run it with bacon server. Adapt the command, package, features, environment,
and watched paths to the repository. Add a custom kill command only when the
application needs graceful shutdown and the command is verified for the target
platform. Keep generic check/test jobs in
rust-testing-quality.
When a project uses cargo-leptos, prefer its documented cargo leptos watch
workflow because it coordinates server and browser/WASM builds. Do not wrap one
file-watching development server inside another; use Bacon separately for
focused Cargo quality jobs.
Useful direct checks include:
cargo check -p <server-package> --all-targets
cargo check -p <client-package> --target wasm32-unknown-unknown
cargo test -p <package>
cargo clippy -p <package> --all-targets -- -D warnings
For cargo-leptos projects, use cargo leptos test and configured
cargo leptos end-to-end lanes when the pinned version and repository scripts
support them. Verify host/SSR features separately from the hydrate
wasm32-unknown-unknown build instead of assuming one command covers both.
For final confidence, run the repository's broader Rust, browser, and service
tests when the change affects hydrated UI, routing, server functions, or HTTP
behavior.
Common Pitfalls
- Introducing async where synchronous code is simpler and sufficient.
- Coupling domain models, value objects, or invariants to Tokio types.
- Confusing async concurrency with CPU parallelism.
- Creating nested runtimes instead of keeping the runtime at process edges.
- Detached tasks that hide panics, ignore shutdown, or continue using stale
state after a request is gone.
- Ignoring
JoinHandle results or losing task errors.
- Missing cancellation paths for background workers, request fan-out, or
long-running orchestration.
- Blocking the async runtime with sync I/O, CPU-heavy work, thread sleeps, or
long critical sections.
- Holding locks, transactions, or borrowed request data across unrelated awaits.
- Unbounded channels or queues that turn overload into memory growth.
- Mixing blocking and async I/O without an explicit adapter or
spawn_blocking
boundary.
- Surprising
Send + 'static requirements from tokio::spawn after borrowing
request-local data.
- Hiding async trait allocation, object-safety, or
Send tradeoffs behind a port
abstraction without documenting the reason.
- Mapping every error to
500 or every auth failure to the same response without
preserving observability.
- Calling SQL or external services directly from UI components instead of a
server-side boundary.
- Hydration mismatches caused by random ids, current time, locale, feature
differences, or browser-only APIs during SSR.
- Sharing mutable state because it is convenient rather than because the domain
requires shared mutation.
Review Checklist
- Async work has bounded lifetime, cancellation, timeout, and backpressure.
- Handler/component/server-function boundaries are thin and testable.
- Domain invariants are not duplicated across UI, HTTP, and persistence layers.
- Errors are actionable internally and safe externally.
- Shared state and locks cannot deadlock, block the runtime, or leak across
unrelated requests.
- Server-rendered and client-hydrated output agree for the changed behavior.
- Tests cover the behavior at the lowest useful layer plus at least one
framework boundary when routing, extraction, hydration, or server functions
are part of the change.
1---2name: rust-async-web3description: Async Rust and Rust web/full-stack guidance. Use when working with Tokio, async tasks, cancellation, timeouts, backpressure, channels, shared state, synchronization, Axum handlers/extractors/state/middleware, Leptos components, leptos-use, server functions, SSR/hydration/WASM, or Axum-Leptos full-stack applications. Use rust-desktop-gui for native desktop GUI event-loop integration, api-design for endpoint contracts, observability-engineering for durable telemetry, css-scss-styling for CSS/SCSS/Leptos styling decisions, rust-persistence-sql for SQLx/database work, and rust-testing-quality for test lanes.4---56# Rust Async And Web78Use this skill for async Rust services and full-stack Rust applications. Keep9runtime, HTTP, UI, and persistence boundaries explicit so domain logic remains10testable without the framework. Use11[`hexagonal-architecture`](../hexagonal-architecture/SKILL.md) when handlers,12jobs, server functions, message consumers, persistence, or external clients need13formal ports/adapters or shared application use cases.1415Load [`rust-engineering`](../rust-engineering/SKILL.md) when async/web work also16changes core Rust implementation such as types, ownership, traits, errors,17features, modules, or macros. Do not load it for review-only async/web guidance.1819Do not use this skill for API-contract-only work such as endpoint/resource20shape, request/response/error envelopes, versioning, pagination, idempotency, or21OpenAPI/AsyncAPI/protobuf artifacts; use [`api-design`](../api-design/SKILL.md)22for those contracts. Do not use it for observability-only work such as23log/metric/trace schemas, context-propagation standards, labels/cardinality,24dashboards, alerts, SLOs, or telemetry sampling; use25[`observability-engineering`](../observability-engineering/SKILL.md). Add this26skill only when the task also changes Tokio, Axum, Leptos, SSR, hydration, WASM,27task, or runtime behavior.2829Native desktop GUI implementation is not this skill's primary scope. Use30[`rust-desktop-gui`](../rust-desktop-gui/SKILL.md) for iced, egui/eframe, Slint,31Tauri shell, and native event-loop work. Compose with this skill when the GUI32change needs Tokio task, cancellation, channel, or backpressure mechanics, but33never block the GUI event-loop thread.3435## Workflow36371. Inspect the runtime and stack: `Cargo.toml` features, `tokio` runtime setup,38 `bacon.toml`, Justfile/scripts, Axum routers, Leptos/cargo-leptos app and39 hydration configuration, server functions, WASM build target,40 stylesheet/static asset pipeline, middleware, tracing, and existing test41 recipes.422. Define externally observable behavior with BDD-style acceptance criteria.43 Keep domain invariants in framework-independent types where practical.443. Design task ownership, cancellation, timeouts, backpressure, shared state,45 and error propagation before adding handlers or components.464. Implement narrow vertical slices: domain logic, adapter/handler/server47 function, UI or response behavior, and tests.485. Verify the server side, client/WASM side, and hydration/SSR behavior with the49 repository's commands.5051## Security Review Prompts5253Load [`security-review`](../security-review/SKILL.md) when async/web work54touches auth, authorization, sessions or cookies, CORS/CSRF/CSP, redirects,55SSR/hydration trust boundaries, server functions, uploads/downloads, path56handling, request/response redaction, secrets, external-service calls,57telemetry that may leak sensitive data, or artifact handling. Use58[`threat-modeling`](../threat-modeling/SKILL.md) before or during new auth59middleware, request/SSR/server-function boundaries, background workers, queues,60webhooks, external-service integrations, or sensitive data flows. Use61[`dependency-supply-chain-review`](../dependency-supply-chain-review/SKILL.md)62when Tokio/Axum/Leptos or toolchain dependency changes, generated assets, CI63bootstrap, installers, or binaries raise provenance or advisory questions. Pair64security-sensitive reviews with65[`security-review-evidence`](../security-review-evidence/SKILL.md) when evidence66includes sanitized HTTP traces, logs/spans, browser or server-function payloads,67screenshots, generated assets, or test artifacts.6869## When To Choose Async Rust7071- Use async deliberately for I/O-bound or high-concurrency work: network72 servers and clients, database calls, queues, workers, orchestration layers,73 file or process I/O with async APIs, and fan-out/fan-in workflows.74- Do not make code async by default. Synchronous Rust is usually clearer for75 CPU-bound algorithms, pure domain logic, simple CLIs, low-concurrency tools,76 and code where blocking APIs are sufficient.77- Async changes API shape. It affects trait boundaries, dependency injection,78 lifetimes, `Send + 'static` requirements for spawned work, cancellation,79 error propagation, and which tests need a runtime.80- Keep blocking libraries behind explicit boundaries. In an async service, wrap81 unavoidable blocking or CPU-heavy work with `tokio::task::spawn_blocking`, a82 dedicated thread pool, or a separate worker process instead of blocking Tokio83 runtime threads.84- Distinguish concurrency from parallelism. Async lets many tasks wait on I/O;85 it does not make CPU-heavy work faster unless that work is moved to real86 parallel execution.8788## Architecture Boundaries8990- Keep domain logic pure, deterministic, and preferably synchronous. Avoid91 leaking Tokio types, channels, timers, task handles, database pools, request92 types, or framework state into the domain model.93- Put async I/O at application, infrastructure, adapter, or port boundaries.94 Application services/use cases may orchestrate async repositories, clients,95 queues, clocks, and external services while domain objects enforce rules.96- Use ports/traits for async dependencies only where the boundary earns it:97 repositories, external clients, queues, clocks, id generators, and background98 job interfaces. Do not force async into every layer because one adapter is99 async.100- Keep Tokio-specific details in infrastructure adapters and process wiring:101 runtime flavor, channels, task spawning, cancellation tokens, signal handling,102 tracing setup, and adapter-specific retry/timeout policy.103- For async traits, prefer the simplest option the repository supports. Native104 `async fn` in traits can work for static dispatch when the MSRV and auto-trait105 bounds fit; use explicit future return types, boxed futures, or `async-trait`106 when object safety, dyn dispatch, or tighter `Send` control matters.107- Use BDD examples at the system, inbound adapter, or use-case boundary; TDD108 domain rules with sync unit tests; test async application services with fakes;109 and test real adapters with `#[tokio::test]` integration tests.110111## Tokio Runtime, Coordination, And Cancellation112113Use the [Tokio runtime reference](references/tokio-runtime.md) when the task114requires runtime construction, spawning, coordination primitives, cancellation,115or graceful shutdown. Keep the core constraints visible: never block runtime116threads, give every task an owner and shutdown path, bound concurrency and117queues, and treat cancellation as real control flow.118119## Local CPU Parallelism Routing120121Compose with [`parallelism-engineering`](../parallelism-engineering/SKILL.md)122when an async/web application must redesign a local CPU-bound workload around123data or task decomposition, partition sizing, bounded executor ownership,124deterministic reduction, cancellation, or nested-parallelism control. That skill125owns the parallel design; this skill owns the Tokio integration, such as keeping126blocking CPU work off runtime threads and applying the chosen design through127Rust runtime APIs.128129Do not route ordinary Tokio scheduling, async I/O, channels, task lifetimes,130timeouts, backpressure, or Axum/Leptos concurrency to131`parallelism-engineering`; they remain here. Spark/PySpark execution belongs to132[`data-platform-engineering`](../data-platform-engineering/SKILL.md), not this133local parallelism handoff.134135## WebAssembly Routing136137Compose with [`webassembly-engineering`](../webassembly-engineering/SKILL.md)138when async/web work includes a general WebAssembly decision: a WAT or `.wasm`139artifact, WASI or WIT, the Component Model, host/guest contract, runtime or140target selection, capability grants, or Wasm packaging and deployment. That141skill owns those Wasm boundary and compatibility decisions. This skill retains142Leptos, `wasm-bindgen`, Cargo, Rust target compilation, SSR/hydration, browser143framework, host-integration, and test mechanics; the Wasm skill does not144establish their source-level or framework support.145146## Axum147148- Keep routers, handlers, extractors, state, and middleware thin. Move domain149 decisions into services or domain modules that can be tested without HTTP.150- Use typed extractors for inputs and `State`/substates for application state.151 Store shared state in `Arc` when it must be cloned into handlers.152- Convert domain and adapter errors into HTTP responses at the edge. Avoid153 leaking database, framework, or internal error details to clients. Use154 [`api-design`](../api-design/SKILL.md) when status codes, error envelopes,155 route shapes, or request/response payloads are contract decisions.156- Validate payload size, content type, authentication, authorization, and input157 shape before invoking domain behavior.158- Prefer Tower middleware or extractors for cross-cutting HTTP concerns such as159 tracing, auth, timeouts, compression, and request ids.160- Expose application assembly separately from listener startup so tests can161 construct the `Router` with controlled state.162- Test HTTP semantics by calling the router as a Tower service with163 `tower::ServiceExt::oneshot`; assert status, relevant headers, and a bounded or164 collected response body. Cover extractor rejection, middleware, error mapping,165 and state wiring where those behaviors matter.166- Use pure or application-service tests when routing adds no behavior. Bind a167 loopback listener on port `0` only when the test requires real transport,168 connection metadata, protocol behavior, or client/server integration.169170## Leptos And Axum-Leptos171172For a technical-debt audit of an Axum + Leptos SSR application, read the173[Axum + Leptos technical-debt audit reference](references/axum-leptos-debt-audit.md)174before selecting commands or diagnosing hydration, feature-gating, route, or175multi-instance concerns.176177- Decide whether behavior belongs in CSR, SSR, server functions, actions,178 resources, or ordinary backend routes. Keep security-sensitive work on the179 server.180- Server functions are trust boundaries. Validate input, authorization, and181 idempotency server-side even when the client UI already checks them.182- Components should keep state derivation clear. Avoid burying domain rules in183 signal plumbing when a normal Rust function or type can own the rule.184- SSR and hydration must render compatible markup. Avoid browser-only APIs,185 nondeterministic values, or time-dependent output during server rendering186 unless guarded for the target.187- WASM code should avoid unavailable server APIs and large unnecessary188 dependencies. Check crate features and target-specific modules.189- Axum-Leptos integrations should keep router state, server function context,190 static assets, fallback handling, and error pages explicit.191- Test framework-independent component and application logic with ordinary host192 Rust tests. Test SSR output, server functions, and backend routes through the193 server application with the repository's server-side features enabled.194- Test browser-targeted components with `wasm-bindgen-test` or the repository's195 established WASM harness when DOM-level behavior is the narrowest useful196 boundary. Match the runner and browser mode to the pinned toolchain.197- Test hydration, navigation, forms, and other user-visible full-stack behavior198 in a real browser. Load [`playwright-e2e`](../playwright-e2e/SKILL.md) when199 adding or changing checked-in Playwright tests.200201### Leptos-Use202203- Consult the current [Leptos-Use documentation](https://leptos-use.rs/) and the204 repository's pinned Leptos and `leptos-use` versions before using an API.205 Consider the crate before hand-writing reusable reactive wrappers for browser206 events, media queries and preferences, storage, observers, timers, sensors,207 streams, or other Web APIs. Prefer native Leptos or direct `web-sys` code when208 the behavior is small, unsupported, or clearer without another abstraction.209- Inspect each function's documented SSR behavior; server fallbacks vary by210 utility. Use SSR-safe targets such as `use_window()` and `use_document()`211 instead of accessing browser globals during server rendering, and verify that212 fallback values cannot produce incorrect initial markup or hydration mismatches.213- In an SSR application, enable `leptos-use/ssr` through the application's214 server-only feature, not globally on the dependency. Inspect function-level215 crate features and avoid shipping unused defaults when WASM size or compile216 time matters, while preserving the repository's established feature policy.217- Prefer utilities that bind cleanup to the Leptos owner for listeners,218 observers, timers, and streams. Retain and call returned cleanup, pause, stop,219 or close controls when behavior must end before owner cleanup; confirm any220 same-thread restrictions in the selected API's documentation.221- Treat local/session storage as user-visible, origin-scoped client state, not222 trusted or secret storage. Account for decoding failures, unavailable storage,223 cross-tab updates, and hydration timing. For permissions and sensors, handle224 unsupported, denied, unavailable, and paused states rather than assuming a225 successful browser API call.226227Load [`css-scss-styling`](../css-scss-styling/SKILL.md) when Leptos/Axum work228touches `.css`, `.scss`, `.sass`, stylesheet entrypoints, Trunk/cargo-leptos229style assets, class/style bindings, design tokens, responsive layout, CSS230modules, or browser-visible cascade behavior. Keep this skill focused on Rust231runtime, SSR, hydration, server functions, routing, and WASM constraints.232233## Development And Commands234235Prefer repository scripts for full-stack apps because they often manage CSS,236WASM, assets, environment, and services.237238For an ordinary long-running Axum service, use a checked-in Bacon job when the239repository adopts Bacon:240241```toml242[jobs.server]243command = ["cargo", "run"]244need_stdout = true245background = false246on_change_strategy = "kill_then_restart"247```248249Run it with `bacon server`. Adapt the command, package, features, environment,250and watched paths to the repository. Add a custom `kill` command only when the251application needs graceful shutdown and the command is verified for the target252platform. Keep generic check/test jobs in253[`rust-testing-quality`](../rust-testing-quality/SKILL.md).254255When a project uses cargo-leptos, prefer its documented `cargo leptos watch`256workflow because it coordinates server and browser/WASM builds. Do not wrap one257file-watching development server inside another; use Bacon separately for258focused Cargo quality jobs.259260Useful direct checks include:261262```sh263cargo check -p <server-package> --all-targets264cargo check -p <client-package> --target wasm32-unknown-unknown265cargo test -p <package>266cargo clippy -p <package> --all-targets -- -D warnings267```268269For cargo-leptos projects, use `cargo leptos test` and configured270`cargo leptos end-to-end` lanes when the pinned version and repository scripts271support them. Verify host/SSR features separately from the `hydrate`272`wasm32-unknown-unknown` build instead of assuming one command covers both.273274For final confidence, run the repository's broader Rust, browser, and service275tests when the change affects hydrated UI, routing, server functions, or HTTP276behavior.277278## Common Pitfalls279280- Introducing async where synchronous code is simpler and sufficient.281- Coupling domain models, value objects, or invariants to Tokio types.282- Confusing async concurrency with CPU parallelism.283- Creating nested runtimes instead of keeping the runtime at process edges.284- Detached tasks that hide panics, ignore shutdown, or continue using stale285 state after a request is gone.286- Ignoring `JoinHandle` results or losing task errors.287- Missing cancellation paths for background workers, request fan-out, or288 long-running orchestration.289- Blocking the async runtime with sync I/O, CPU-heavy work, thread sleeps, or290 long critical sections.291- Holding locks, transactions, or borrowed request data across unrelated awaits.292- Unbounded channels or queues that turn overload into memory growth.293- Mixing blocking and async I/O without an explicit adapter or `spawn_blocking`294 boundary.295- Surprising `Send + 'static` requirements from `tokio::spawn` after borrowing296 request-local data.297- Hiding async trait allocation, object-safety, or `Send` tradeoffs behind a port298 abstraction without documenting the reason.299- Mapping every error to `500` or every auth failure to the same response without300 preserving observability.301- Calling SQL or external services directly from UI components instead of a302 server-side boundary.303- Hydration mismatches caused by random ids, current time, locale, feature304 differences, or browser-only APIs during SSR.305- Sharing mutable state because it is convenient rather than because the domain306 requires shared mutation.307308## Review Checklist309310- Async work has bounded lifetime, cancellation, timeout, and backpressure.311- Handler/component/server-function boundaries are thin and testable.312- Domain invariants are not duplicated across UI, HTTP, and persistence layers.313- Errors are actionable internally and safe externally.314- Shared state and locks cannot deadlock, block the runtime, or leak across315 unrelated requests.316- Server-rendered and client-hydrated output agree for the changed behavior.317- Tests cover the behavior at the lowest useful layer plus at least one318 framework boundary when routing, extraction, hydration, or server functions319 are part of the change.