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.