Serving under a sub-path

Sometimes the app doesn't own the whole domain, but lives under a path like https://example.com/panel/, next to other apps. Tell the server about it with --mount-point:

vertigo serve --mount-point /panel

The server then expects requests starting with /panel (so a reverse proxy in front of it should pass the path unchanged) and serves the build files under /panel/build. Paths returned by include_static! already contain the mount point.

Routes

During server-side rendering the router gets the path without the mount point (/users), but in the browser it gets the full path (/panel/users). So convert the paths in both directions: route_from_public cuts the mount point off and route_to_public adds it back:

    use vertigo::{dom, get_driver, router::Router, DomDisplay};

    #[derive(Clone, PartialEq)]
    enum Route {
        Home,
        Users,
        NotFound,
    }

    impl From<String> for Route {
        fn from(url: String) -> Self {
            // Cuts off the mount point, f. ex. /panel/users -> /users
            match get_driver().route_from_public(url).as_str() {
                "/" | "" => Self::Home,
                "/users" => Self::Users,
                _ => Self::NotFound,
            }
        }
    }

    impl std::fmt::Display for Route {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            let path = match self {
                Self::Home => "/",
                Self::Users => "/users",
                Self::NotFound => "/not-found",
            };
            // Adds the mount point, f. ex. /users -> /panel/users
            f.write_str(&get_driver().route_to_public(path))
        }
    }

    impl DomDisplay for Route {}

    let router = Router::<Route>::new_history_router();

    let page = router.route.render_value(|route| match route {
        Route::Home => dom! { <p>"Home"</p> },
        Route::Users => dom! { <p>"Users"</p> },
        Route::NotFound => dom! { <p>"Not found"</p> },
    });

    dom! {
        <div>
            <nav>
                <a href={Route::Home}>"Home"</a>
                " "
                <a href={Route::Users}>"Users"</a>
            </nav>
            {page}
        </div>
    }

Without a mount point both functions return the path unchanged, so such route works in both setups.