@sanity/routes
    Preparing search index...

    Interface RouteResolver

    Unified route resolver with all URL resolution methods.

    Created via createRouteResolver. Combines realtime GROQ evaluation (for resolveUrlById, pathProjection, listen, etc.) with static shard lookups (for preload, resolveDocumentByUrl, rebuildType).

    import { createRouteResolver } from '@sanity/routes'

    const resolver = createRouteResolver(client, 'web')

    // Realtime — evaluates GROQ live
    const url = await resolver.resolveUrlById('article-123')

    // Static — reads from pre-computed shards
    const urlMap = await resolver.preload()
    urlMap['article-123']

    createRouteResolver to create a resolver instance

    interface RouteResolver {
        diagnose(id: string, options?: LocaleOptions): Promise<DiagnosisResult>;
        getRoutableTypes(): Promise<string[]>;
        groqField(type: string): Promise<string>;
        groqFunctions(): Promise<string>;
        listen(): () => void;
        pathProjection(type: string): Promise<string>;
        preload(options?: LocaleOptions): Promise<Record<string, string>>;
        rebuildType(type: string, options?: LocaleOptions): Promise<void>;
        resolveDocumentByUrl(
            url: string,
        ): Promise<{ id: string; type: string } | null>;
        resolvePathById(
            id: string,
            options?: LocaleOptions,
        ): Promise<string | null>;
        resolvePathByIds(
            ids: string[],
            options?: LocaleOptions,
        ): Promise<Record<string, string>>;
        resolveUrlById(id: string, options?: LocaleOptions): Promise<string | null>;
        resolveUrlByIds(
            ids: string[],
            options?: LocaleOptions,
        ): Promise<Record<string, string>>;
    }
    Index

    Methods

    • Experimental

      Diagnose why a document ID fails (or succeeds) to resolve to a URL.

      Uses realtime GROQ evaluation to check each step of the resolution pipeline. Returns a detailed result with a status code and human-readable message. Use this for debugging when resolveUrlById returns null.

      Parameters

      • id: string

        Published document ID to diagnose

      • Optionaloptions: LocaleOptions

        Locale options for i18n routes

      Returns Promise<DiagnosisResult>

      Diagnosis result with status, message, and contextual data

      const result = await resolver.diagnose('my-doc')
      if (result.status === 'no_route_entry') {
      console.log(result.availableRoutes) // ['blogPost', 'page']
      }

      The 6-status contract may evolve.

      DiagnosisResult for the full result shape

    • List all document types that have route entries in the config.

      Returns Promise<string[]>

      Array of document type names (e.g., ['blogPost', 'article', 'product'])

    • Experimental

      Generate GROQ custom function declarations for all routable types.

      Each declaration creates a routes::{type}Path($id) function that looks up the path from the route map shard. Useful for embedding route resolution in GROQ queries without client-side processing.

      Returns Promise<string>

      Newline-separated function declarations

      const fns = await resolver.groqFunctions()
      // → 'fn routes::blogPostPath($id) = *[_id == "routes-web-blogPost"][0].entries[doc._ref == $id][0].path;'

      GROQ custom functions may not be supported in all environments.

    • Subscribe to route config changes and invalidate the internal cache.

      Call this in long-running processes (e.g., dev servers) to keep the resolver's cached config fresh when route configuration changes in Studio.

      Returns () => void

      Unsubscribe function. Call it to stop listening.

      // In a React component or layout
      useEffect(() => {
      const unsubscribe = resolver.listen()
      return () => unsubscribe() // cleanup on unmount
      }, [resolver])
    • Returns a GROQ projection expression for the path portion of a route.

      The returned expression resolves to the relative path only — it does NOT include baseUrl or basePath. Use this to embed URL resolution directly in GROQ queries.

      Parameters

      • type: string

        Document type name (e.g., 'blogPost')

      Returns Promise<string>

      A GROQ projection string like "path": slug.current

      If no route entry exists for the given type

      const pathExpr = await resolver.pathProjection('blogPost')
      const posts = await client.fetch(
      `*[_type == "blogPost"]{ _id, title, ${pathExpr} }`
      )
      // → [{ _id: "blog-1", title: "Hello", path: "hello-world" }]
    • Load all route map shards into a Map for synchronous URL lookups.

      Requires route map shards built by buildRouteMap() or the sync Function. Returns a Record of document ID → full URL for every document in the route map. Ideal for Portable Text rendering where you need synchronous access to URLs for internal link marks.

      Parameters

      • Optionaloptions: LocaleOptions

        Locale options. When set, loads locale-specific shards.

      Returns Promise<Record<string, string>>

      Record of document ID → full URL. Empty record if no shards exist.

      // Preload in parallel with content fetch
      const [post, urlMap] = await Promise.all([
      client.fetch(`*[_type == "blogPost" && slug.current == $slug][0]`, { slug }),
      resolver.preload(),
      ])

      // Synchronous lookup in Portable Text renderer — no async, no waterfall
      const components = {
      marks: {
      internalLink: ({ value, children }) => (
      <a href={urlMap[value.reference._ref] ?? '#'}>{children}</a>
      ),
      },
      }
    • Rebuild the route map shard for a specific document type.

      Requires route map shards infrastructure (the sync Function or buildRouteMap()). Fetches all documents of the given type, evaluates their pathExpression, and writes the shard to Content Lake via createOrReplace. When the route has locales configured and no specific locale is passed, rebuilds all locale-specific shards.

      Parameters

      • type: string

        Document type name to rebuild (e.g., 'blogPost')

      • Optionaloptions: LocaleOptions

        Locale options. Pass a specific locale to rebuild only that shard.

      Returns Promise<void>

      If no route entry exists for the given type

      await resolver.rebuildType('blogPost')
      // Rebuilds routes-web-blogPost shard

      await resolver.rebuildType('product', { locale: 'fr' })
      // Rebuilds routes-web-product-fr shard only
    • Reverse-resolve a URL to the document that produces it.

      Requires route map shards built by buildRouteMap() or the sync Function. Scans all shards to find the document whose assembled URL matches the input. Accepts full URLs or path-only input. Normalizes trailing slashes, query parameters, and fragments before comparison.

      Parameters

      • url: string

        Full URL or path to resolve (e.g., 'https://example.com/blog/hello' or '/blog/hello')

      Returns Promise<{ id: string; type: string } | null>

      The document ID and type, or null if no match is found

      const doc = await resolver.resolveDocumentByUrl('/blog/hello-world')
      // → { id: 'blog-hello', type: 'blogPost' }

      const doc2 = await resolver.resolveDocumentByUrl('https://example.com/blog/hello-world/')
      // → { id: 'blog-hello', type: 'blogPost' } (trailing slash normalized)
    • Resolve a document ID to just the URL pathname (no origin).

      Uses realtime GROQ evaluation. Convenience wrapper around resolveUrlById that extracts the pathname. Use this for Next.js <Link href>, internal routing, and redirect().

      Parameters

      • id: string

        Published document ID

      • Optionaloptions: LocaleOptions

        Locale options for i18n routes

      Returns Promise<string | null>

      The pathname (e.g., /docs/ai/agent-context), or null if unresolvable.

      const path = await resolver.resolvePathById('article-123')
      // → "/docs/ai/agent-context"
    • Resolve multiple document IDs to their pathnames in a single batch.

      Uses realtime GROQ evaluation.

      Parameters

      • ids: string[]

        Array of published document IDs

      • Optionaloptions: LocaleOptions

        Locale options for i18n routes

      Returns Promise<Record<string, string>>

      Record of document ID → pathname. Unresolvable IDs are omitted.

      const paths = await resolver.resolvePathByIds(['blog-1', 'article-1'])
      paths['blog-1'] // → "/blog/hello-world"
      paths['article-1'] // → "/docs/setup"
    • Resolve a single document ID to its full URL.

      Uses realtime GROQ evaluation — always returns the freshest result.

      Parameters

      • id: string

        Published document ID to resolve. Use @sanity/id-utils to normalize draft/version IDs.

      • Optionaloptions: LocaleOptions

        Locale options for i18n routes

      Returns Promise<string | null>

      The full URL including base URL and basePath, or null if the document can't be resolved (missing document, no route entry, or empty path). Use diagnose to determine the specific failure reason.

      const url = await resolver.resolveUrlById('article-123')
      // → 'https://example.com/docs/getting-started'
    • Resolve multiple document IDs to their full URLs in a single batch.

      Uses realtime GROQ evaluation. More efficient than calling resolveUrlById in a loop — groups documents by route entry for batch GROQ evaluation.

      Parameters

      • ids: string[]

        Array of published document IDs to resolve

      • Optionaloptions: LocaleOptions

        Locale options for i18n routes

      Returns Promise<Record<string, string>>

      Record of document ID → full URL. IDs that can't be resolved are omitted (not null).

      const urls = await resolver.resolveUrlByIds(['blog-1', 'blog-2', 'article-1'])
      urls['blog-1'] // → 'https://example.com/blog/hello-world'
      urls['article-1'] // → 'https://example.com/docs/setup'
      urls['missing'] // → undefined