diff --git a/dev/test-studio/plugins/router-debug/RouterDebug.tsx b/dev/test-studio/plugins/router-debug/RouterDebug.tsx
new file mode 100644
index 000000000000..5569c536b91e
--- /dev/null
+++ b/dev/test-studio/plugins/router-debug/RouterDebug.tsx
@@ -0,0 +1,90 @@
+import React from 'react'
+import {Button, Card, Code, Flex, Stack, Text} from '@sanity/ui'
+import {IntentLink, RouteScope, StateLink, useRouter, useStateLink} from 'sanity/router'
+
+export function RouterDebug() {
+ const {navigate} = useRouter()
+
+ const link = useStateLink({
+ state: {
+ section: 'abc',
+ _searchParams: [['viewParam', 'from link']],
+ },
+ })
+
+ return (
+
+
+
+ Tool home
+
+ Go to section "abc", with search params
+
+
+
+ Resolve intent
+
+
+
+
+ )
+}
+
+function InspectRouterState() {
+ const {state} = useRouter()
+ return (
+
+ Decoded router state
+
+ {JSON.stringify(state, null, 2)}
+
+
+ )
+}
diff --git a/dev/test-studio/plugins/router-debug/index.ts b/dev/test-studio/plugins/router-debug/index.ts
new file mode 100644
index 000000000000..a0ed13843f9e
--- /dev/null
+++ b/dev/test-studio/plugins/router-debug/index.ts
@@ -0,0 +1 @@
+export * from './plugin'
diff --git a/dev/test-studio/plugins/router-debug/plugin.tsx b/dev/test-studio/plugins/router-debug/plugin.tsx
new file mode 100644
index 000000000000..7fbc707927ee
--- /dev/null
+++ b/dev/test-studio/plugins/router-debug/plugin.tsx
@@ -0,0 +1,40 @@
+import {definePlugin} from 'sanity'
+import {PinIcon} from '@sanity/icons'
+import {route} from 'sanity/router'
+import {RouterDebugConfig} from './types'
+import {RouterDebug} from './RouterDebug'
+
+/**
+ * Router playground/debug plugin
+ */
+export const routerDebugTool = definePlugin((options) => {
+ const {name, title, icon} = options || {}
+
+ return {
+ name: 'router-debug',
+ tools: [
+ {
+ name: name || 'router-debug',
+ title: title || 'Router debug',
+ icon: icon || PinIcon,
+ component: RouterDebug,
+ canHandleIntent: (intent, params) => {
+ return intent === 'router-debug-please'
+ },
+ getIntentState: (intent, params) => {
+ return {
+ section: 'from-intent',
+ _searchParams: [
+ ['intentResolved', 'yes'],
+ ['paramFromIntent', params.favorite],
+ ],
+ }
+ },
+ router: route.create('/', [
+ route.create('/section/:section'),
+ route.scope('some-plugin', '/', [route.create('/', route.create('/:pluginParam'))]),
+ ]),
+ },
+ ],
+ }
+})
diff --git a/dev/test-studio/plugins/router-debug/types.ts b/dev/test-studio/plugins/router-debug/types.ts
new file mode 100644
index 000000000000..540cd133cbea
--- /dev/null
+++ b/dev/test-studio/plugins/router-debug/types.ts
@@ -0,0 +1,7 @@
+import type {ComponentType} from 'react'
+
+export interface RouterDebugConfig {
+ name?: string
+ title?: string
+ icon?: ComponentType
+}
diff --git a/dev/test-studio/sanity.config.ts b/dev/test-studio/sanity.config.ts
index 2cc25ef766ff..ac450e5b0437 100644
--- a/dev/test-studio/sanity.config.ts
+++ b/dev/test-studio/sanity.config.ts
@@ -40,6 +40,8 @@ import {copyAction} from './fieldActions/copyAction'
import {assistFieldActionGroup} from './fieldActions/assistFieldActionGroup'
import {customInspector} from './inspectors/custom'
import {pasteAction} from './fieldActions/pasteAction'
+import routerDebug from './plugins/router-debug/RouterDebug'
+import {routerDebugTool} from './plugins/router-debug'
const sharedSettings = definePlugin({
name: 'sharedSettings',
@@ -121,6 +123,7 @@ const sharedSettings = definePlugin({
// eslint-disable-next-line camelcase
muxInput({mp4_support: 'standard'}),
presenceTool(),
+ routerDebugTool(),
tsdoc(),
],
})