# Routing

For SPAs, the widget needs to know what page the visitor is on. Three props handle this: `pathname` (required for App Router), `showOn` / `hideOn` (route filters), and `onNavigate` (router integration).

## `pathname` — make routing aware

Pass the current pathname so the widget can:

- Evaluate `showOn` / `hideOn` patterns
- Invalidate page-context cache between routes
- Use route-aware navigation (avoid full page reloads)

**Next.js App Router:**

```tsx title="app/layout.tsx"
"use client";
import { usePathname, useRouter } from "next/navigation";
import { AvatarWidget } from "@livelayer/react";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  const pathname = usePathname();
  const router = useRouter();

  return (
    <html>
      <body>
        {children}
        <AvatarWidget
          agentId="agt_abc123"
          pathname={pathname}
          onNavigate={(href) => router.push(href)}
        />
      </body>
    </html>
  );
}
```

> [!WARNING]
> For Next.js App Router, `pathname` is **required**. Without it the widget falls back to `window.location.pathname`, which doesn't update on route transitions until React re-renders.

**Next.js Pages Router:**

```tsx title="pages/_app.tsx"
import { useRouter } from "next/router";
import { AvatarWidget } from "@livelayer/react";

export default function App({ Component, pageProps }: AppProps) {
  const router = useRouter();
  return (
    <>
      <!-- omitted: Component -->
      <AvatarWidget
        agentId="agt_abc123"
        pathname={router.pathname}
        onNavigate={(href) => router.push(href)}
      />
    </>
  );
}
```

**React Router v6+:**

```tsx title="app.tsx"
import { useLocation, useNavigate } from "react-router-dom";
import { AvatarWidget } from "@livelayer/react";

export default function AppLayout() {
  const { pathname } = useLocation();
  const navigate = useNavigate();
  return (
    <>
      <!-- omitted: Outlet -->
      <AvatarWidget
        agentId="agt_abc123"
        pathname={pathname}
        onNavigate={(href) => navigate(href)}
      />
    </>
  );
}
```

**TanStack Router:**

```tsx title="routes/__root.tsx"
import { useLocation, useRouter } from "@tanstack/react-router";
import { AvatarWidget } from "@livelayer/react";

function RootLayout() {
  const { pathname } = useLocation();
  const router = useRouter();
  return (
    <>
      <!-- omitted: Outlet -->
      <AvatarWidget
        agentId="agt_abc123"
        pathname={pathname}
        onNavigate={(href) => router.navigate({ to: href })}
      />
    </>
  );
}
```

## `showOn` / `hideOn` — render conditionally

```tsx
<!-- omitted: AvatarWidget -->
```

Both accept arrays of `RoutePattern`:

- **String** — glob pattern (`*` matches a single segment, `**` matches across segments)
- **RegExp** — full regular expression
- **Function** — `(pathname: string) => boolean`

`hideOn` wins over `showOn`. Empty / omitted = render everywhere (subject to the other filter).

### Pattern examples

```tsx
hideOn={[
  "/admin",                  // exact match
  "/admin/*",                // /admin/users, /admin/billing — but not /admin/users/123
  "/admin/**",               // /admin/anything/at/any/depth
  /^\/legal\/(privacy|tos)$/, // regex for exact paths
  (path) => path.includes("checkout") || path.endsWith(".pdf"),
]}
```

### Common combinations

**Marketing-site only:**

```tsx
<!-- omitted: AvatarWidget -->
```

The widget is hidden on every authenticated page.

**Hide during sensitive flows:**

```tsx
<!-- omitted: AvatarWidget -->
```

The widget can interrupt or distract during checkout / billing — easier to hide it there.

**Per-section agents:**

```tsx
{section === "sales" && (
  <!-- omitted: AvatarWidget -->
)}
{section === "support" && (
  <!-- omitted: AvatarWidget -->
)}
```

## `onNavigate` — agent-driven navigation

When the agent emits a `navigate` command (e.g., "let me show you pricing"), this callback fires with the target href. Wire it to your router so navigation feels native.

```tsx
<AvatarWidget
  agentId="agt_abc123"
  pathname={pathname}
  onNavigate={(href) => {
    // Internal links → router push
    if (href.startsWith("/")) {
      router.push(href);
      return;
    }
    // External links → open new tab
    window.open(href, "_blank", "noopener,noreferrer");
  }}
/>
```

Without `onNavigate`, the widget falls back to:

1. Try to click an `<a>` element with matching `href` (preserves your router's link handling)
2. Fall back to `history.pushState` + `popstate` event

The fallback works for most cases, but custom `onNavigate` is faster and more reliable.

## Routing with `getRoutes` — feed the agent your sitemap

By default, the widget extracts links from the visible DOM. To give the agent the full sitemap upfront (especially for SPAs where most links aren't rendered), pass `getRoutes`:

```tsx
import { AvatarWidget } from "@livelayer/react";

<AvatarWidget
  agentId="agt_abc123"
  pathname={pathname}
  onNavigate={(href) => router.push(href)}
  getRoutes={() => [
    { path: "/", title: "Home", description: "Marketing landing" },
    { path: "/pricing", title: "Pricing" },
    { path: "/docs", title: "Documentation" },
    { path: "/docs/recipes/sales-assistant", title: "Sales Assistant recipe" },
    { path: "/contact", title: "Contact us" },
  ]}
/>
```

Now when the visitor says "take me to the sales recipe," the agent has a stable map and emits the right `navigate`.

## Read next

- [Page awareness](/docs/develop/npm/react/page-awareness) — what the agent sees on each route
- [`AvatarWidget` props](/docs/develop/npm/react/avatar-widget) — full reference
