AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Dioxus Routing

skill-bwbioinfo-skill-dioxus-dioxus-routing · by bwbioinfo

Implement client-side routing in Dioxus applications using dioxus-router. Use when building multi-page applications, setting up navigation, implementing nested routes, or handling route parameters and navigation guards.

No reviews yet
0 installs
25 views
0.0% view→install

Install

$ agentstack add skill-bwbioinfo-skill-dioxus-dioxus-routing

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution Used
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-bwbioinfo-skill-dioxus-dioxus-routing)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
4mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Dioxus Routing? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Dioxus Routing

This skill helps you implement robust client-side routing in Dioxus applications using the dioxus-router crate.

When to use this skill

  • Setting up client-side routing for single-page applications (SPAs)
  • Creating multi-page Dioxus applications with navigation
  • Implementing nested routes and route hierarchies
  • Handling route parameters, query strings, and navigation state
  • Setting up route guards and authentication-based routing
  • Managing browser history and navigation programmatically

Router Setup

1. Add Router Dependencies

Add the router dependency to your Cargo.toml:

[dependencies]
dioxus = { version = "0.7", features = ["web", "router"] }
dioxus-router = "0.7"

2. Define Route Structure

Create a route enum that represents your application's pages:

use dioxus::prelude::*;
use dioxus_router::prelude::*;

#[derive(Clone, Routable, Debug, PartialEq)]
enum Route {
    #[route("/")]
    Home {},
    
    #[route("/about")]
    About {},
    
    #[route("/blog")]
    Blog {},
    
    #[route("/blog/:id")]
    BlogPost { id: usize },
    
    #[route("/user/:user_id")]
    UserProfile { user_id: String },
    
    #[route("/user/:user_id/settings")]
    UserSettings { user_id: String },
    
    #[route("/products?:category&:sort")]
    Products { 
        category: Option, 
        sort: Option 
    },
    
    // Catch-all route for 404 pages
    #[route("/:..route")]
    PageNotFound { route: Vec },
}

3. Basic Router Implementation

Set up the main application with router:

#![allow(non_snake_case)]
use dioxus::prelude::*;
use dioxus_router::prelude::*;

fn main() {
    dioxus::launch(App);
}

#[component]
fn App() -> Element {
    rsx! {
        Router:: {}
    }
}

#[component]
fn Home() -> Element {
    rsx! {
        div {
            class: "home-page",
            h1 { "Welcome to Home Page" }
            nav {
                Link { to: Route::About {}, "About" }
                Link { to: Route::Blog {}, "Blog" }
            }
        }
    }
}

#[component]
fn About() -> Element {
    rsx! {
        div {
            class: "about-page",
            h1 { "About Us" }
            p { "This is the about page" }
            Link { to: Route::Home {}, "Back to Home" }
        }
    }
}

Advanced Routing Patterns

1. Nested Routes with Layout

#[derive(Clone, Routable, Debug, PartialEq)]
enum Route {
    #[route("/")]
    Home {},
    
    #[layout(DashboardLayout)]
        #[route("/dashboard")]
        Dashboard {},
        
        #[route("/dashboard/analytics")]
        Analytics {},
        
        #[route("/dashboard/settings")]
        Settings {},
    #[end_layout]
    
    #[route("/:..route")]
    PageNotFound { route: Vec },
}

#[component]
fn DashboardLayout() -> Element {
    rsx! {
        div {
            class: "dashboard-layout",
            header {
                class: "dashboard-header",
                h1 { "Dashboard" }
                nav {
                    class: "dashboard-nav",
                    Link { 
                        to: Route::Dashboard {}, 
                        class: "nav-link",
                        "Overview" 
                    }
                    Link { 
                        to: Route::Analytics {}, 
                        class: "nav-link",
                        "Analytics" 
                    }
                    Link { 
                        to: Route::Settings {}, 
                        class: "nav-link",
                        "Settings" 
                    }
                }
            }
            main {
                class: "dashboard-content",
                // This is where nested route components render
                Outlet:: {}
            }
        }
    }
}

2. Route Parameters and Query Handling

#[component]
fn BlogPost(id: usize) -> Element {
    let mut post_data = use_signal(|| None::);
    let navigator = use_navigator();
    
    // Load post data based on ID
    use_effect(move || {
        spawn(async move {
            match fetch_blog_post(id).await {
                Ok(post) => post_data.set(Some(post)),
                Err(_) => navigator.push(Route::PageNotFound { 
                    route: vec!["blog".to_string(), id.to_string()] 
                }),
            }
        });
    });
    
    match post_data() {
        Some(post) => rsx! {
            article {
                class: "blog-post",
                header {
                    h1 { "{post.title}" }
                    p { class: "meta", "Published: {post.date}" }
                }
                div {
                    class: "content",
                    dangerous_inner_html: "{post.content}"
                }
                nav {
                    class: "post-navigation",
                    Link { to: Route::Blog {}, "← Back to Blog" }
                    if let Some(next_id) = post.next_id {
                        Link { 
                            to: Route::BlogPost { id: next_id }, 
                            "Next Post →" 
                        }
                    }
                }
            }
        },
        None => rsx! {
            div { class: "loading", "Loading post..." }
        }
    }
}

#[component]
fn Products(category: Option, sort: Option) -> Element {
    let mut products = use_signal(|| Vec::::new());
    let navigator = use_navigator();
    
    // Update URL when filters change
    let update_filters = use_callback(move |new_category: Option, new_sort: Option| {
        navigator.push(Route::Products { 
            category: new_category, 
            sort: new_sort 
        });
    });
    
    rsx! {
        div {
            class: "products-page",
            h1 { "Products" }
            
            div {
                class: "filters",
                select {
                    onchange: move |evt| {
                        let new_category = if evt.value().is_empty() { 
                            None 
                        } else { 
                            Some(evt.value()) 
                        };
                        update_filters.call((new_category, sort.clone()));
                    },
                    option { value: "", "All Categories" }
                    option { 
                        value: "electronics", 
                        selected: category.as_deref() == Some("electronics"),
                        "Electronics" 
                    }
                    option { 
                        value: "clothing", 
                        selected: category.as_deref() == Some("clothing"),
                        "Clothing" 
                    }
                }
                
                select {
                    onchange: move |evt| {
                        let new_sort = if evt.value().is_empty() { 
                            None 
                        } else { 
                            Some(evt.value()) 
                        };
                        update_filters.call((category.clone(), new_sort));
                    },
                    option { value: "", "Default Sort" }
                    option { 
                        value: "price_asc", 
                        selected: sort.as_deref() == Some("price_asc"),
                        "Price: Low to High" 
                    }
                    option { 
                        value: "price_desc", 
                        selected: sort.as_deref() == Some("price_desc"),
                        "Price: High to Low" 
                    }
                }
            }
            
            div {
                class: "products-grid",
                for product in products() {
                    ProductCard { product: product.clone() }
                }
            }
        }
    }
}

3. Programmatic Navigation

#[component]
fn LoginForm() -> Element {
    let mut username = use_signal(|| String::new());
    let mut password = use_signal(|| String::new());
    let mut is_loading = use_signal(|| false);
    let navigator = use_navigator();
    
    let handle_login = move |_| {
        if !username().is_empty() && !password().is_empty() {
            is_loading.set(true);
            
            let nav = navigator.clone();
            let user = username();
            let pass = password();
            
            spawn(async move {
                match authenticate(&user, &pass).await {
                    Ok(user_data) => {
                        // Store user session
                        store_user_session(user_data).await;
                        
                        // Navigate to dashboard
                        nav.push(Route::Dashboard {});
                    }
                    Err(e) => {
                        // Handle error (you might want to show an error message)
                        eprintln!("Login failed: {}", e);
                        is_loading.set(false);
                    }
                }
            });
        }
    };
    
    rsx! {
        form {
            class: "login-form",
            onsubmit: handle_login,
            
            input {
                r#type: "text",
                placeholder: "Username",
                value: "{username}",
                oninput: move |evt| username.set(evt.value())
            }
            
            input {
                r#type: "password",
                placeholder: "Password",
                value: "{password}",
                oninput: move |evt| password.set(evt.value())
            }
            
            button {
                r#type: "submit",
                disabled: is_loading(),
                if is_loading() { "Logging in..." } else { "Login" }
            }
        }
    }
}

4. Route Guards and Protection

#[component]
fn ProtectedRoute(children: Element) -> Element {
    let auth_state = use_context::();
    let navigator = use_navigator();
    
    use_effect(move || {
        if !auth_state.is_authenticated() {
            navigator.push(Route::Home {});
        }
    });
    
    if auth_state.is_authenticated() {
        rsx! { {children} }
    } else {
        rsx! {
            div {
                class: "access-denied",
                h2 { "Access Denied" }
                p { "Please log in to access this page." }
                Link { to: Route::Home {}, "Go to Home" }
            }
        }
    }
}

// Usage in route definition
#[component]
fn Dashboard() -> Element {
    rsx! {
        ProtectedRoute {
            div {
                class: "dashboard",
                h1 { "Dashboard" }
                p { "Welcome to your dashboard!" }
            }
        }
    }
}

5. Active Link Styling

#[component]
fn Navigation() -> Element {
    let current_route = use_route::();
    
    rsx! {
        nav {
            class: "main-navigation",
            Link {
                to: Route::Home {},
                class: if matches!(current_route, Route::Home {}) {
                    "nav-link active"
                } else {
                    "nav-link"
                },
                "Home"
            }
            Link {
                to: Route::About {},
                class: if matches!(current_route, Route::About {}) {
                    "nav-link active"
                } else {
                    "nav-link"
                },
                "About"
            }
            Link {
                to: Route::Blog {},
                class: if matches!(current_route, Route::Blog {} | Route::BlogPost { .. }) {
                    "nav-link active"
                } else {
                    "nav-link"
                },
                "Blog"
            }
        }
    }
}

Advanced Features

1. Route Transitions

#[component]
fn App() -> Element {
    rsx! {
        div {
            class: "app",
            style: "transition: all 0.3s ease-in-out;",
            Router:: {}
        }
    }
}

2. Lazy Loading Routes

#[component]
fn LazyRoute() -> Element {
    let mut component = use_signal(|| None::);
    
    use_effect(|| {
        spawn(async move {
            // Simulate dynamic import
            let loaded_component = load_component().await;
            component.set(Some(loaded_component));
        });
    });
    
    match component() {
        Some(comp) => comp,
        None => rsx! {
            div { class: "loading", "Loading..." }
        }
    }
}

3. Error Boundaries for Routes

#[component]
fn PageNotFound(route: Vec) -> Element {
    let path = route.join("/");
    
    rsx! {
        div {
            class: "not-found",
            h1 { "404 - Page Not Found" }
            p { "The page '/{path}' could not be found." }
            nav {
                Link { to: Route::Home {}, "Go Home" }
                button {
                    onclick: move |_| {
                        web_sys::window()
                            .unwrap()
                            .history()
                            .unwrap()
                            .back()
                            .ok();
                    },
                    "Go Back"
                }
            }
        }
    }
}

Best Practices

1. Route Organization

  • Keep routes organized in a logical hierarchy
  • Use consistent naming conventions
  • Group related routes with layouts
  • Keep route parameters type-safe

2. Performance Optimization

  • Use lazy loading for heavy route components
  • Implement proper loading states
  • Cache route data when appropriate
  • Minimize route component re-renders

3. User Experience

  • Provide clear navigation indicators
  • Implement proper loading and error states
  • Use browser back/forward button correctly
  • Handle deep linking and bookmarking

4. SEO Considerations

  • Use meaningful URLs
  • Implement proper meta tags per route
  • Consider server-side rendering for better SEO
  • Provide fallback routes for better crawling

Common Patterns

Breadcrumb Navigation

#[component]
fn Breadcrumbs() -> Element {
    let route = use_route::();
    let breadcrumbs = generate_breadcrumbs(&route);
    
    rsx! {
        nav {
            class: "breadcrumbs",
            for (i, crumb) in breadcrumbs.iter().enumerate() {
                if i > 0 {
                    span { class: "separator", ">" }
                }
                if let Some(route) = &crumb.route {
                    Link { to: route.clone(), "{crumb.label}" }
                } else {
                    span { class: "current", "{crumb.label}" }
                }
            }
        }
    }
}

This skill provides comprehensive routing capabilities for building sophisticated single-page applications with Dioxus.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.