Problem
The router documentation does not explain the stateful scoping behavior of the #[layout()] attribute, nor does it mention the #[end_layout] attribute needed to close layout scopes.
This leads to a common bug where developers accidentally create nested/duplicate layouts when trying to apply the same layout to multiple routes.
Current Documentation Gap
The layouts documentation shows only single-route examples:
#[layout(Wrapper)]
#[route("/")]
Index {},
When developers want multiple routes to share the same layout, they naturally assume they need to add #[layout()] to each route:
// ❌ Creates NESTED layouts (2 Wrapper components rendered)
#[layout(Wrapper)]
#[route("/")]
Home {},
#[layout(Wrapper)] // This NESTS inside the first layout!
#[route("/tokens")]
Tokens {},
This results in duplicate UI elements (e.g., 2 navigation bars, 2 headers) with no compile-time warning.
Root Cause
The #[layout()] attribute creates a persistent, stateful scope that remains active for all subsequent routes until explicitly closed with #[end_layout] (similar to how #[nest()] works with #[end_nest]).
What Should Be Documented
- Layout scoping is stateful - Once opened, it affects all subsequent routes
- The
#[end_layout] attribute exists - Explicitly closes a layout scope
- Proper indentation convention - Visual hierarchy helps prevent mistakes
- Multiple routes under one layout - Show the correct pattern:
#[layout(Wrapper)]
#[route("/")]
Home {},
#[route("/tokens")]
Tokens {},
#[end_layout]
- Warning about duplicate layouts - Explain what happens if scopes aren't closed
- Debugging technique - Mention
cargo expand to verify nesting levels
Real-World Impact
This bit us in production - our /tokens page rendered with 2 complete layouts (duplicate navigation, duplicate sidebars) while / rendered correctly. Debugging required:
- Inspecting generated HTML with curl
- Using
cargo expand to examine macro-generated code
- Reading Dioxus router source code
The fix was simple (#[end_layout]), but discovering it was not.
Comparison with Nested Routes
The nested routes documentation does explain this pattern for #[nest()]:
To finish a nest, we use the #[end_nest] attribute or the end of the enum.
Layouts should have equivalent documentation for #[end_layout].
Proposed Solution
Add a new section to the layouts documentation showing:
- How to apply one layout to multiple routes
- The
#[end_layout] attribute
- Warning about accidental nesting
- Example of the wrong pattern vs correct pattern
- Optional: debugging tips
References
Problem
The router documentation does not explain the stateful scoping behavior of the
#[layout()]attribute, nor does it mention the#[end_layout]attribute needed to close layout scopes.This leads to a common bug where developers accidentally create nested/duplicate layouts when trying to apply the same layout to multiple routes.
Current Documentation Gap
The layouts documentation shows only single-route examples:
When developers want multiple routes to share the same layout, they naturally assume they need to add
#[layout()]to each route:This results in duplicate UI elements (e.g., 2 navigation bars, 2 headers) with no compile-time warning.
Root Cause
The
#[layout()]attribute creates a persistent, stateful scope that remains active for all subsequent routes until explicitly closed with#[end_layout](similar to how#[nest()]works with#[end_nest]).What Should Be Documented
#[end_layout]attribute exists - Explicitly closes a layout scopecargo expandto verify nesting levelsReal-World Impact
This bit us in production - our
/tokenspage rendered with 2 complete layouts (duplicate navigation, duplicate sidebars) while/rendered correctly. Debugging required:cargo expandto examine macro-generated codeThe fix was simple (
#[end_layout]), but discovering it was not.Comparison with Nested Routes
The nested routes documentation does explain this pattern for
#[nest()]:Layouts should have equivalent documentation for
#[end_layout].Proposed Solution
Add a new section to the layouts documentation showing:
#[end_layout]attributeReferences