Guides

App Bridge

Use Shopify App Bridge and authenticated fetch in your embedded app.

Overview

The module uses Shopify's CDN-based App Bridge (not the deprecated npm package). The CDN script and API key meta tag are automatically injected via SSR head — no manual setup required.

Do not install the @shopify/app-bridge npm package — it is deprecated. The module uses the CDN approach exclusively.

useAppBridge()

Access the App Bridge instance (typed as ShopifyGlobal) in your Vue components:

<script setup>
// Access the App Bridge instance
const shopify = useAppBridge()

// Get the current shop
const shop = shopify.config.shop
</script>

useAppBridge() is safe to call anywhere — it returns a lazy proxy that only throws when a property is accessed in an unavailable context (e.g., server-side or outside the Shopify admin iframe).

Common App Bridge APIs

<script setup>
const shopify = useAppBridge()

// Show a toast notification
shopify.toast.show('Product saved!')

// Open a resource picker
const selection = await shopify.resourcePicker({ type: 'product' })

// Get a session token
const token = await shopify.idToken()
</script>

useShopifyFetch()

Use useShopifyFetch() for API calls that automatically include the Shopify session token:

  • Client: Fetches a session token via App Bridge and sets the Authorization header
  • Server: Forwards the Authorization header from the incoming request (when one is already present)
Session tokens are only available on the client via App Bridge. When using useShopifyFetch() inside useAsyncData, you must pass { server: false } so the fetch runs in the browser where App Bridge can provide a token.

Basic usage

<script setup>
const { data: shop } = await useAsyncData(
  'shop',
  () => useShopifyFetch('/api/shop'),
  { server: false }
)
</script>

With TypeScript generics

<script setup lang="ts">
interface ShopData {
  shop: { name: string; currencyCode: string }
}

const { data } = await useAsyncData(
  'shop',
  () => useShopifyFetch<ShopData>('/api/shop'),
  { server: false }
)
// data.value.shop.name is fully typed
</script>

With query parameters

<script setup>
const { data } = await useAsyncData(
  'products',
  () =>
    useShopifyFetch('/api/products', {
      query: { limit: 10, status: 'active' }
    }),
  { server: false }
)
</script>

With mutations

<script setup>
async function createProduct() {
  const result = await useShopifyFetch('/api/products', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ title: 'New Product' })
  })
}
</script>

Loading Indicator

<ShLoadingIndicator> hooks into Nuxt's useLoadingIndicator() and calls shopify.loading() to show/hide the Shopify Admin's native top loading bar during page navigations:

app.vue
<template>
  <ShLoadingIndicator />
  <NuxtPage />
</template>

This replaces <NuxtLoadingIndicator> with the native Shopify loading bar for a more integrated experience.

© 2026 KiriminAja. Polaris and Shopify are trademarks of Shopify Inc.

KiriminAja not affiliated with Shopify.