> For the complete documentation index, see [llms.txt](https://docs.akinon.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.akinon.com/akinon-ui/ui-protocol/shell-application/configuration/navigation.md).

# Navigation

AppShell's navigation helpers allow micro-frontend applications to trigger navigation in the main application.

### <mark style="color:red;">Overview</mark>

This enables clients to redirect users to different pages within the shell application without direct access to the shell's router.

{% hint style="info" %}
Navigation helpers are router-agnostic. You implement them using your preferred routing library (React Router, Next.js Router, etc.).
{% endhint %}

### <mark style="color:red;">How It Works</mark>

1. Shell defines a `navigate` function and passes it to `AppShellProvider`
2. Client calls `navigation.navigate({ path: '/some-path' })`
3. Shell receives the navigation request via framebus
4. Shell executes the navigation using its router

### <mark style="color:red;">Usage</mark>

Pass the `navigation` prop to `AppShellProvider`:

```tsx
import { AppShellProvider, type ShellNavigation } from '@akinon/app-shell';
import { useNavigate } from 'react-router';

const App = () => {
  const routerNavigate = useNavigate();

  const navigation: ShellNavigation = {
    navigate: (payload) => {
      routerNavigate(payload.path);
    }
  };

  return (
    <AppShellProvider
      apps={registeredApps}
      data={sharedData}
      navigation={navigation}
      actions={shellActions}
    >
      {/* Your shell application */}
    </AppShellProvider>
  );
};
```

### <mark style="color:red;">ShellNavigation Type</mark>

```typescript
interface ShellNavigation {
  navigate: (payload: NavigationPayload) => void;
}

interface NavigationPayload {
  path: string;
  id?: number;
}
```

| Property | Type     | Description                          |
| -------- | -------- | ------------------------------------ |
| `path`   | `string` | The target path to navigate to       |
| `id`     | `number` | Optional. Application ID for context |

### <mark style="color:red;">Implementation Examples</mark>

#### React Router

```tsx
import { useNavigate } from 'react-router';
import { AppShellProvider, type ShellNavigation } from '@akinon/app-shell';

const App = () => {
  const navigate = useNavigate();

  const navigation: ShellNavigation = {
    navigate: ({ path }) => {
      navigate(path);
    }
  };

  return (
    <AppShellProvider navigation={navigation} {...otherProps}>
      {children}
    </AppShellProvider>
  );
};
```

#### TanStack Router

```tsx
import { useNavigate } from '@tanstack/react-router';
import { AppShellProvider, type ShellNavigation } from '@akinon/app-shell';

const App = () => {
  const navigate = useNavigate();

  const navigation: ShellNavigation = {
    navigate: ({ path }) => {
      navigate({ to: path });
    }
  };

  return (
    <AppShellProvider navigation={navigation} {...otherProps}>
      {children}
    </AppShellProvider>
  );
};
```

#### With Application ID

You can use the optional `id` parameter to handle navigation with application context:

```tsx
const navigation: ShellNavigation = {
  navigate: ({ path, id }) => {
    if (id) {
      // Navigate to app-specific route
      navigate(`/apps/${id}${path}`);
    } else {
      navigate(path);
    }
  }
};
```

### <mark style="color:red;">Using Navigation (Client Side)</mark>

Clients trigger navigation via the `useAppClient` hook:

```tsx
// In the client application
import { useAppClient } from '@akinon/app-client';

const ClientComponent = () => {
  const { navigation } = useAppClient();

  const handleViewOrder = (orderId: string) => {
    navigation.navigate({ path: `/orders/${orderId}` });
  };

  const handleGoBack = () => {
    navigation.navigate({ path: '/dashboard' });
  };

  return (
    <div>
      <button onClick={() => handleViewOrder('123')}>
        View Order
      </button>
      <button onClick={handleGoBack}>
        Back to Dashboard
      </button>
    </div>
  );
};
```

{% hint style="info" %}
For detailed information about using navigation on the client side, see the Client Application documentation.
{% endhint %}

### <mark style="color:red;">Advanced Usage</mark>

#### Handling External Navigation

You may want to handle external URLs differently:

```tsx
const navigation: ShellNavigation = {
  navigate: ({ path }) => {
    if (path.startsWith('http://') || path.startsWith('https://')) {
      // External URL - open in new tab
      window.open(path, '_blank');
    } else {
      // Internal path - use router
      routerNavigate(path);
    }
  }
};
```

#### Navigation with Query Parameters

Query parameters can be included in the path:

```tsx
// Client
navigation.navigate({ path: '/products?category=electronics&page=2' });

// Shell handles it naturally
const navigation: ShellNavigation = {
  navigate: ({ path }) => {
    routerNavigate(path); // Includes query params
  }
};
```

#### Navigation with State

If you need to pass state data during navigation, use a combination of navigation and actions:

```tsx
// Shell
const actions = {
  navigateWithState: (path: string, state: any) => {
    routerNavigate(path, { state });
  }
};

// Client
actions.actions.navigateWithState('/details', { fromPage: 'list' });
```

### <mark style="color:red;">Best Practices</mark>

#### 1. Keep Navigation Logic Simple

The navigation handler should focus on routing. Complex logic should be in actions.

```typescript
// ❌ Bad - Too much logic in navigation
navigate: ({ path }) => {
  logAnalytics(path);
  saveToHistory(path);
  checkPermissions(path);
  routerNavigate(path);
}

// ✅ Good - Simple navigation, side effects in actions
navigate: ({ path }) => {
  routerNavigate(path);
}
```

#### 2. Handle Unknown Paths Gracefully

Consider what happens when a client requests an invalid path:

```typescript
navigate: ({ path }) => {
  const validRoutes = ['/dashboard', '/orders', '/products'];
  const isValidPrefix = validRoutes.some(route => path.startsWith(route));
  
  if (isValidPrefix) {
    routerNavigate(path);
  } else {
    routerNavigate('/404');
  }
}
```

#### 3. Consider Navigation Timing

If clients navigate immediately on mount, ensure the shell is ready:

```tsx
// Shell - wrap navigation in a safe check
navigate: ({ path }) => {
  if (isAppReady) {
    routerNavigate(path);
  } else {
    pendingNavigation.current = path;
  }
}
```

### <mark style="color:red;">Next Steps</mark>

* [Data Sharing](/akinon-ui/ui-protocol/shell-application/configuration/data-sharing.md) - Share data with clients
* [Actions](/akinon-ui/ui-protocol/shell-application/configuration/actions.md) - Define custom actions


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.akinon.com/akinon-ui/ui-protocol/shell-application/configuration/navigation.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
