Skip to main content
If your plugin needs more than one page, you implement routing inside your root component. The shell doesn’t impose a router — you match the current path and render the appropriate page.

How Routing Works

When your plugin is active, the shell’s URL path looks like:
/plugins/{your-plugin-id}/overview
/plugins/{your-plugin-id}/roster
/plugins/{your-plugin-id}/roster/pilot-123
Your root component reads the current path, strips the plugin prefix, and renders the matching page.

Basic Router Pattern

import { usePluginContext } from "@skyvexsoftware/stratos-sdk";
import OverviewPage from "./pages/OverviewPage";
import RosterPage from "./pages/RosterPage";
import PilotDetailPage from "./pages/PilotDetailPage";

function useSubPath(): string {
  const ctx = usePluginContext();
  const fullPath = ctx.navigation.getCurrentPath();
  const prefix = `/plugins/${ctx.pluginId}/`;
  return fullPath.startsWith(prefix) ? fullPath.slice(prefix.length) : "";
}

function Router() {
  const subPath = useSubPath() || "overview";

  // Dynamic routes — match before static routes
  const pilotMatch = subPath.match(/^roster\/(.+)$/);
  if (pilotMatch) return <PilotDetailPage pilotId={pilotMatch[1]} />;

  // Static routes
  if (subPath === "roster") return <RosterPage />;
  return <OverviewPage />;
}

export default function MyPlugin() {
  return <Router />;
}
Use useShellNavigation() to navigate between sub-pages:
import { useShellNavigation } from "@skyvexsoftware/stratos-sdk";

function OverviewPage() {
  const nav = useShellNavigation();

  return (
    <button onClick={() => nav.navigateTo("roster")}>
      View Roster
    </button>
  );
}
const nav = useShellNavigation();

// Navigate within your plugin (relative path)
nav.navigateTo("roster");
nav.navigateTo("roster/pilot-123");

// Navigate to another plugin
nav.navigateToPlugin("flight-tracking", "history");

// Navigate to a shell page
nav.navigateToShell("settings");

// Read the current full path
const path = nav.getCurrentPath();

Reading Route Params

For dynamic segments, extract params yourself from the sub-path:
function useSubPath(): string {
  const ctx = usePluginContext();
  const fullPath = ctx.navigation.getCurrentPath();
  const prefix = `/plugins/${ctx.pluginId}/`;
  return fullPath.startsWith(prefix) ? fullPath.slice(prefix.length) : "";
}

function PilotDetailPage() {
  const subPath = useSubPath();
  // subPath === "roster/pilot-abc-123"
  const pilotId = subPath.split("/")[1];

  // fetch pilot by pilotId...
}
Or parse it at the router level and pass as props:
function Router() {
  const subPath = useSubPath() || "overview";

  const pilotMatch = subPath.match(/^roster\/(.+)$/);
  if (pilotMatch) {
    return <PilotDetailPage pilotId={pilotMatch[1]} />;
  }

  if (subPath === "roster") return <RosterPage />;
  return <OverviewPage />;
}

Full Example

A plugin with three pages: Overview, Roster, and Pilot Detail.
src/
├── ui/
│   └── index.tsx          ← root component with router
├── pages/
│   ├── OverviewPage.tsx
│   ├── RosterPage.tsx
│   └── PilotDetailPage.tsx
src/ui/index.tsx:
import { usePluginContext } from "@skyvexsoftware/stratos-sdk";
import OverviewPage from "../pages/OverviewPage";
import RosterPage from "../pages/RosterPage";
import PilotDetailPage from "../pages/PilotDetailPage";

function useSubPath(): string {
  const ctx = usePluginContext();
  const fullPath = ctx.navigation.getCurrentPath();
  const prefix = `/plugins/${ctx.pluginId}/`;
  return fullPath.startsWith(prefix) ? fullPath.slice(prefix.length) : "";
}

function Router() {
  const subPath = useSubPath() || "overview";

  const pilotMatch = subPath.match(/^roster\/(.+)$/);
  if (pilotMatch) return <PilotDetailPage pilotId={pilotMatch[1]} />;

  if (subPath === "roster") return <RosterPage />;
  return <OverviewPage />;
}

export default function MyPlugin() {
  return (
    <div className="flex h-full flex-col overflow-y-auto">
      <Router />
    </div>
  );
}
src/pages/OverviewPage.tsx:
import { useShellNavigation, Button } from "@skyvexsoftware/stratos-sdk";

export default function OverviewPage() {
  const nav = useShellNavigation();

  return (
    <div className="p-6">
      <h1 className="text-2xl font-bold">Overview</h1>
      <Button className="mt-4" onClick={() => nav.navigateTo("roster")}>
        View Roster
      </Button>
    </div>
  );
}
src/pages/RosterPage.tsx:
import { useShellNavigation } from "@skyvexsoftware/stratos-sdk";

type Pilot = { id: string; name: string };

export default function RosterPage({ pilots }: { pilots: Pilot[] }) {
  const nav = useShellNavigation();

  return (
    <div className="p-6">
      <h1 className="text-2xl font-bold">Roster</h1>
      <ul className="mt-4 space-y-2">
        {pilots.map((pilot) => (
          <li
            key={pilot.id}
            className="cursor-pointer rounded border p-3 hover:bg-muted"
            onClick={() => nav.navigateTo(`roster/${pilot.id}`)}
          >
            {pilot.name}
          </li>
        ))}
      </ul>
    </div>
  );
}