> For AI agents: the complete Sanity documentation index is available at [https://www.sanity.io/docs/llms.txt](https://www.sanity.io/docs/llms.txt).

# Navigate the Dashboard

Keep your app's router in sync with the Dashboard and link to other apps, Studios, and documents.

The Dashboard owns the browser URL. Your app's routes live under the app's own path in the Dashboard, and links to other apps or Studios go through the Dashboard's router.

## Keep your router in sync

Pass `useNavigate` a callback when your app has its own router. The callback receives the navigations the Dashboard asks your app to perform, such as the back button or a link into your app, and the function it returns reports your app's own navigations so the browser URL follows. Render this component inside your router and `SanityApp`:

**src/DashboardNavigationSync.tsx**

```tsx
import {useNavigate} from '@sanity/sdk-react/dashboard'
import {useEffect} from 'react'
import {useLocation, useNavigate as useRouterNavigate} from 'react-router'

export function DashboardNavigationSync() {
  const routerNavigate = useRouterNavigate()
  const {pathname, search, hash} = useLocation()
  const navigate = useNavigate(({path, type}) => {
    routerNavigate(path, {replace: type === 'replace'})
  })

  useEffect(() => {
    navigate({path: `${pathname.slice(1)}${search}${hash}`})
  }, [navigate, pathname, search, hash])

  return null
}
```

`path` is relative to your app's route, with no leading slash, and can include a query string and hash. Pass `type: 'replace'` to replace the current history entry instead of adding one.

## Navigate to another app

Build the destination with `urlFor`, then call the navigate function with `scope: 'dashboard'`. A component that only sends the user somewhere doesn't need a callback. Calling `useNavigate()` without one needs `@sanity/sdk-react` 3.9.0 or later:

**src/OpenApp.tsx**

```tsx
import {urlFor, useNavigate} from '@sanity/sdk-react/dashboard'

export function OpenApp({applicationId}: {applicationId: string}) {
  const navigate = useNavigate()
  const url = urlFor.applications(applicationId).url()

  return (
    <button type="button" onClick={() => navigate({path: url, scope: 'dashboard'})}>
      Open app
    </button>
  )
}
```

`urlFor` also builds URLs with `studios(appId)`, `mediaLibrary()`, `canvas()`, and `home()`. Call `.url()` to get the string. To open a document in a Studio, use `useNavigateToStudioDocument` instead.

## Render a link

For a real link, set `href` to the `urlFor` URL so users can open it in a new tab, and navigate through the Dashboard on a plain click:

**src/DashboardLink.tsx**

```tsx
import {useNavigate} from '@sanity/sdk-react/dashboard'
import type {MouseEvent, ReactNode} from 'react'

export function DashboardLink({url, children}: {url: string; children: ReactNode}) {
  const navigate = useNavigate()

  function handleClick(event: MouseEvent<HTMLAnchorElement>) {
    if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey) return
    event.preventDefault()
    navigate({path: url, scope: 'dashboard'})
  }

  return (
    <a href={url} onClick={handleClick}>
      {children}
    </a>
  )
}
```

## Open a Studio document

`useNavigateToStudioDocument` finds a Studio for the document's project and dataset and opens the document there. The hook suspends while it looks up the Studio, so wrap the component in `Suspense`:

**src/EditButton.tsx**

```tsx
import {type DocumentHandle} from '@sanity/sdk-react'
import {useNavigateToStudioDocument} from '@sanity/sdk-react/dashboard'
import {Suspense} from 'react'

function EditButtonInner({documentHandle}: {documentHandle: DocumentHandle}) {
  const {navigateToStudioDocument} = useNavigateToStudioDocument(documentHandle)
  return (
    <button type="button" onClick={navigateToStudioDocument}>
      Edit in Studio
    </button>
  )
}

export function EditButton({documentHandle}: {documentHandle: DocumentHandle}) {
  return (
    <Suspense
      fallback={
        <button type="button" disabled>
          Edit in Studio
        </button>
      }
    >
      <EditButtonInner documentHandle={documentHandle} />
    </Suspense>
  )
}
```

## Next steps

[Read Dashboard state](https://www.sanity.io/docs/dashboard-beta/read-dashboard-state)
Read the organization, user, and color scheme.

[Open and close panels](https://www.sanity.io/docs/dashboard-beta/open-and-close-panels)
Control your app's panels from code.

