Navigation
Handle in-plugin page routing and navigate the Whatalo admin from your plugin using the App Bridge.
Plugins support two distinct types of navigation: routing between your own pages and directing the admin shell to a different section of the store management interface.
Internal Page Routing
Plugins do not use a client-side router like React Router. The Whatalo admin controls which page is active by updating the currentPage value in the bridge context. Your plugin reads that value and renders the appropriate view.
import { useAppBridge } from "@whatalo/plugin-sdk/bridge";
import { DashboardPage } from "./pages/dashboard";
import { SettingsPage } from "./pages/settings";
function App() {
const { currentPage } = useAppBridge();
switch (currentPage) {
case "settings":
return <SettingsPage />;
case "dashboard":
default:
return <DashboardPage />;
}
}currentPage always matches the path field you registered in adminUI.pages inside your manifest. When the user clicks a different page entry in the admin sidebar, the host sends an updated whatalo:context message and currentPage changes, triggering a re-render.
Defining Pages in the Manifest
adminUI: {
pages: [
{ path: "dashboard", title: "Dashboard", icon: "puzzle", position: "sidebar" },
{ path: "settings", title: "Settings", icon: "settings", position: "sidebar" },
],
},The first page in the array is the default — it loads when the merchant opens your plugin for the first time or clicks the plugin name in the sidebar.
Navigating the Admin Shell
To direct the merchant to a page in the Whatalo admin (outside your plugin), use bridge.navigate():
import { useAppBridge } from "@whatalo/plugin-sdk/bridge";
function OrderLink({ orderId }: { orderId: string }) {
const bridge = useAppBridge();
return (
<button onClick={() => bridge.navigate(`/store/ABC123/orders/${orderId}`)}>
View Order in Admin
</button>
);
}Allowed Paths
Only paths starting with /store/ or /admin/ are accepted. Any other path is rejected and the returned promise resolves with { success: false, error: "invalid_path" }.
// Allowed
bridge.navigate("/store/ABC123/orders");
bridge.navigate("/store/ABC123/products");
// Rejected
bridge.navigate("/");
bridge.navigate("https://external.com");Return Value
bridge.navigate() returns a Promise<ActionAck>:
const ack = await bridge.navigate("/store/ABC123/orders");
if (!ack.success) {
console.error("Navigation failed:", ack.error);
}