diff --git a/packages/sanity/src/core/bundles/util/dummyGetters.ts b/packages/sanity/src/core/bundles/util/dummyGetters.ts
index b12cf2d436bc..e6aee37afdb6 100644
--- a/packages/sanity/src/core/bundles/util/dummyGetters.ts
+++ b/packages/sanity/src/core/bundles/util/dummyGetters.ts
@@ -25,7 +25,7 @@ export async function getAllVersionsOfDocument(
 
   return await client.fetch(query, {}, {tag: 'document.list-versions'}).then((documents) => {
     return documents.map((doc: SanityDocument) => {
-      const sluggedName = getVersionName(doc._id)
+      const sluggedName = getBundleSlug(doc._id)
       const bundle = bundles?.find((b) => b.slug === sluggedName)
       return {
         name: speakingurl(sluggedName),
@@ -38,7 +38,11 @@ export async function getAllVersionsOfDocument(
   })
 }
 
-export function getVersionName(documentId: string): string {
+/**
+ * @internal
+ * @hidden
+ */
+export function getBundleSlug(documentId: string): string {
   if (documentId.indexOf('.') === -1) return 'Published'
   const version = documentId.slice(0, documentId.indexOf('.'))
   return version
diff --git a/packages/sanity/src/core/bundles/util/tests/createWrapper.tsx b/packages/sanity/src/core/bundles/util/tests/createWrapper.tsx
index 120caff9290b..f190aee7cb20 100644
--- a/packages/sanity/src/core/bundles/util/tests/createWrapper.tsx
+++ b/packages/sanity/src/core/bundles/util/tests/createWrapper.tsx
@@ -6,6 +6,10 @@ import {
   type TestProviderOptions,
 } from '../../../../../test/testUtils/TestProvider'
 
+/**
+ * @internal
+ * @hidden
+ */
 export const createWrapper = async (options?: TestProviderOptions) => {
   const TestProvider = await createTestProvider(options)
   return function Wrapper({children}: {children: ReactNode}): JSX.Element {
diff --git a/packages/sanity/src/core/index.ts b/packages/sanity/src/core/index.ts
index 341df7781cda..06cc369f1b08 100644
--- a/packages/sanity/src/core/index.ts
+++ b/packages/sanity/src/core/index.ts
@@ -2,7 +2,9 @@ export {
   BundleActions,
   BundleBadge,
   BundleMenu,
+  createWrapper,
   getAllVersionsOfDocument,
+  getBundleSlug,
   LATEST,
   usePerspective,
 } from './bundles'
diff --git a/packages/sanity/src/core/releases/plugin/index.ts b/packages/sanity/src/core/releases/plugin/index.ts
index 6fb23ab6b6c0..09b5fe5be986 100644
--- a/packages/sanity/src/core/releases/plugin/index.ts
+++ b/packages/sanity/src/core/releases/plugin/index.ts
@@ -25,6 +25,15 @@ export const releases = definePlugin({
       title: 'Releases',
       component: ReleasesTool,
       router: route.create('/', [route.create('/:bundleSlug')]),
+      canHandleIntent: (intent, params) => {
+        return Boolean(intent === 'release' && params.slug)
+      },
+      getIntentState(intent, params) {
+        if (intent === 'release') {
+          return {bundleSlug: params.slug}
+        }
+        return null
+      },
     },
   ],
 })
diff --git a/packages/sanity/src/structure/panes/document/documentPanel/header/DocumentHeaderTitle.test.tsx b/packages/sanity/src/structure/panes/document/documentPanel/header/DocumentHeaderTitle.test.tsx
index e6f489789d16..de78fa0d9d99 100644
--- a/packages/sanity/src/structure/panes/document/documentPanel/header/DocumentHeaderTitle.test.tsx
+++ b/packages/sanity/src/structure/panes/document/documentPanel/header/DocumentHeaderTitle.test.tsx
@@ -1,6 +1,11 @@
 import {afterEach, beforeEach, describe, expect, it, jest} from '@jest/globals'
 import {render, waitFor} from '@testing-library/react'
-import {defineConfig, type SanityClient, unstable_useValuePreview as useValuePreview} from 'sanity'
+import {
+  defineConfig,
+  type SanityClient,
+  unstable_useValuePreview as useValuePreview,
+  useBundles,
+} from 'sanity'
 import {useRouter} from 'sanity/router'
 
 import {createMockSanityClient} from '../../../../../../test/mocks/mockSanityClient'
@@ -31,6 +36,8 @@ jest.mock('sanity', () => {
   return {
     ...actual,
     unstable_useValuePreview: jest.fn(),
+    useBundles: jest.fn(),
+    getBundleSlug: jest.fn(() => ''),
   }
 })
 
@@ -39,6 +46,8 @@ jest.mock('../../../../../core/bundles/util/dummyGetters', () => ({
   getAllVersionsOfDocument: jest.fn(() => []),
 }))
 
+const mockUseBundles = useBundles as jest.Mock<typeof useBundles>
+
 describe('DocumentHeaderTitle', () => {
   const mockUseDocumentPane = useDocumentPane as jest.MockedFunction<typeof useDocumentPane>
   const mockUseValuePreview = useValuePreview as jest.MockedFunction<typeof useValuePreview>
@@ -59,6 +68,11 @@ describe('DocumentHeaderTitle', () => {
     // eslint-disable-next-line @typescript-eslint/ban-ts-comment
     // @ts-ignore
     mockUseRouter.mockReturnValue({stickyParams: {}, state: {}, navigate: jest.fn()})
+    mockUseBundles.mockReturnValue({
+      data: [],
+      loading: false,
+      dispatch: jest.fn(),
+    })
   })
 
   afterEach(() => {
diff --git a/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveMenu.test.tsx b/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveMenu.test.tsx
new file mode 100644
index 000000000000..875ab948b337
--- /dev/null
+++ b/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveMenu.test.tsx
@@ -0,0 +1,164 @@
+import {beforeEach, describe, expect, it, jest} from '@jest/globals'
+import {fireEvent, render, screen} from '@testing-library/react'
+import {
+  BundleBadge,
+  type BundleDocument,
+  createWrapper,
+  getAllVersionsOfDocument,
+  getBundleSlug,
+  type SanityClient,
+  useBundles,
+  useClient,
+  usePerspective,
+} from 'sanity'
+import {useRouter} from 'sanity/router'
+
+import {DocumentPerspectiveMenu} from './DocumentPerspectiveMenu'
+
+type getBundleSlugType = (documentId: string) => string
+type GetAllVersionsOfDocumentType = (
+  bundles: BundleDocument[] | null,
+  client: SanityClient,
+  documentId: string,
+) => Promise<Partial<BundleDocument>[]>
+
+jest.mock('sanity', () => ({
+  useClient: jest.fn(),
+  usePerspective: jest.fn().mockReturnValue({
+    currentGlobalBundle: {},
+    setPerspective: jest.fn(),
+  }),
+  getAllVersionsOfDocument: jest.fn(() =>
+    Promise.resolve([
+      {
+        name: 'spring-drop',
+        title: 'Spring Drop',
+        hue: 'magenta',
+        icon: 'heart-filled',
+      },
+    ]),
+  ),
+  BundleBadge: jest.fn(),
+  useBundles: jest.fn(),
+  getBundleSlug: jest.fn(() => ''),
+}))
+
+jest.mock('sanity/router', () => ({
+  useRouter: jest.fn().mockReturnValue({
+    navigateIntent: jest.fn(),
+  }),
+  route: {
+    create: jest.fn(),
+  },
+  IntentLink: jest.fn(),
+}))
+
+const mockUseClient = useClient as jest.Mock
+const mockUseRouter = useRouter as jest.MockedFunction<typeof useRouter>
+const navigateIntent = mockUseRouter().navigateIntent as jest.Mock
+
+const mockUseBundles = useBundles as jest.Mock<typeof useBundles>
+const mockUsePerspective = usePerspective as jest.Mock
+const mockGetBundleSlug = getBundleSlug as jest.MockedFunction<getBundleSlugType>
+const mockGetAllVersionsOfDocument =
+  getAllVersionsOfDocument as jest.MockedFunction<GetAllVersionsOfDocumentType>
+const mockBundleBadge = BundleBadge as jest.Mock
+
+describe('DocumentPerspectiveMenu', () => {
+  const mockCurrent: BundleDocument = {
+    description: 'What a spring drop, allergies galore 🌸',
+    _updatedAt: '2024-07-12T10:39:32Z',
+    _rev: 'HdJONGqRccLIid3oECLjYZ',
+    authorId: 'pzAhBTkNX',
+    title: 'Spring Drop',
+    icon: 'heart-filled',
+    _id: 'db76c50e-358b-445c-a57c-8344c588a5d5',
+    _type: 'bundle',
+    slug: 'spring-drop',
+    hue: 'magenta',
+    _createdAt: '2024-07-02T11:37:51Z',
+  }
+
+  beforeEach(() => {
+    jest.clearAllMocks()
+
+    mockUseClient.mockReturnValue({})
+
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-ignore
+
+    mockBundleBadge.mockImplementation(() => <div>"test"</div>)
+
+    // Mock the data returned by useBundles hook
+    const mockData: BundleDocument[] = [mockCurrent]
+
+    mockUseBundles.mockReturnValue({
+      data: mockData,
+      loading: false,
+      dispatch: jest.fn(),
+    })
+
+    mockUsePerspective.mockReturnValue({
+      currentGlobalBundle: mockCurrent,
+      setPerspective: jest.fn(),
+    })
+  })
+
+  it('should render the bundle badge if the document exists in the global bundle', async () => {
+    // Dummy Getters
+    mockGetBundleSlug.mockReturnValue('spring-drop')
+
+    mockGetAllVersionsOfDocument.mockImplementationOnce(
+      (): Promise<any> =>
+        Promise.resolve([
+          {
+            name: 'spring-drop',
+            title: 'Spring Drop',
+            hue: 'magenta',
+            icon: 'heart-filled',
+          },
+        ]),
+    )
+
+    const wrapper = await createWrapper()
+    render(<DocumentPerspectiveMenu documentId="spring-drop.document-id" />, {wrapper})
+
+    expect(screen.getByTestId('button-document-release')).toBeInTheDocument()
+  })
+
+  it('should not render the bundle badge if the document does not exist in the bundle', async () => {
+    // Dummy Getters
+    mockGetBundleSlug.mockReturnValue('no-bundle')
+
+    const wrapper = await createWrapper()
+    render(<DocumentPerspectiveMenu documentId="document-id" />, {wrapper})
+
+    expect(screen.queryByTestId('button-document-release')).toBeNull()
+  })
+
+  it('should navigate to the release intent when the bundle badge is clicked', async () => {
+    // Dummy Getters
+    mockGetBundleSlug.mockReturnValue('spring-drop')
+
+    mockGetAllVersionsOfDocument.mockImplementationOnce(
+      (): Promise<any> =>
+        Promise.resolve([
+          {
+            name: 'spring-drop',
+            title: 'Spring Drop',
+            hue: 'magenta',
+            icon: 'heart-filled',
+          },
+        ]),
+    )
+
+    const wrapper = await createWrapper()
+    render(<DocumentPerspectiveMenu documentId="spring-drop.document-1" />, {wrapper})
+
+    expect(screen.queryByTestId('button-document-release')).toBeInTheDocument()
+    fireEvent.click(screen.getByTestId('button-document-release'))
+
+    expect(navigateIntent).toHaveBeenCalledTimes(1)
+    expect(navigateIntent).toHaveBeenCalledWith('release', {slug: 'spring-drop'})
+  })
+})
diff --git a/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveMenu.tsx b/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveMenu.tsx
index 05cb4d571fd0..53bdee5527c3 100644
--- a/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveMenu.tsx
+++ b/packages/sanity/src/structure/panes/document/documentPanel/header/perspective/DocumentPerspectiveMenu.tsx
@@ -1,30 +1,35 @@
 import {ChevronDownIcon} from '@sanity/icons'
 import {Box, Button} from '@sanity/ui'
-import {useCallback, useEffect, useState} from 'react'
+import {useCallback, useEffect, useMemo, useState} from 'react'
 import {
   BundleBadge,
   type BundleDocument,
   BundleMenu,
   DEFAULT_STUDIO_CLIENT_OPTIONS,
   getAllVersionsOfDocument,
-  LATEST,
+  getBundleSlug,
+  useBundles,
   useClient,
   usePerspective,
 } from 'sanity'
+import {useRouter} from 'sanity/router'
+import {styled} from 'styled-components'
 
-// FIXME
-// eslint-disable-next-line boundaries/element-types
-import {useBundles} from '../../../../../../core/store/bundles/useBundles'
+const BadgeButton = styled(Button)({
+  cursor: 'pointer',
+})
 
 export function DocumentPerspectiveMenu(props: {documentId: string}): JSX.Element {
   const {documentId} = props
   const client = useClient(DEFAULT_STUDIO_CLIENT_OPTIONS)
-
+  const {data} = useBundles()
   const {currentGlobalBundle} = usePerspective()
+  const bundles = useMemo(() => data ?? [], [data])
 
-  const {title, hue, icon} = currentGlobalBundle
+  const existsInBundle = bundles.some((bundle) => bundle.slug === getBundleSlug(documentId))
+  const {title, hue, icon, slug} = currentGlobalBundle
 
-  const {data: bundles} = useBundles()
+  const router = useRouter()
 
   // TODO MAKE SURE THIS IS HOW WE WANT TO DO THIS
   const [documentVersions, setDocumentVersions] = useState<BundleDocument[]>([])
@@ -43,21 +48,33 @@ export function DocumentPerspectiveMenu(props: {documentId: string}): JSX.Elemen
     fetchVersionsInner()
   }, [fetchVersions])
 
+  const handleBundleClick = useCallback(() => {
+    router.navigateIntent('release', {slug})
+  }, [router, slug])
+
   return (
     <>
-      {/* FIXME Version Badge should only show when the current opened document is in a version, RIGHT
-      NOW IT'S USING THE GLOBAL */}
-      {currentGlobalBundle && currentGlobalBundle.slug === LATEST.slug && (
-        <BundleBadge hue={hue} title={title} icon={icon} padding={2} />
+      {currentGlobalBundle && existsInBundle && (
+        <BadgeButton
+          onClick={handleBundleClick}
+          mode="bleed"
+          padding={0}
+          radius="full"
+          data-testid="button-document-release"
+        >
+          <BundleBadge hue={hue} title={title} icon={icon} padding={2} />
+        </BadgeButton>
       )}
       {/** TODO IS THIS STILL NEEDED? VS THE PICKER IN STUDIO NAVBAR? */}
-      <Box flex="none">
-        <BundleMenu
-          button={<Button icon={ChevronDownIcon} mode="bleed" padding={2} space={2} />}
-          bundles={documentVersions}
-          loading={!documentVersions}
-        />
-      </Box>
+      {documentVersions.length > 0 && (
+        <Box flex="none">
+          <BundleMenu
+            button={<Button icon={ChevronDownIcon} mode="bleed" padding={2} space={2} />}
+            bundles={documentVersions}
+            loading={!documentVersions}
+          />
+        </Box>
+      )}
     </>
   )
 }