npm package: @nuxtjs/shopify
Description: Easily integrate Shopify with Nuxt 3 and 4 🚀
Latest version: 0.5.0

![Nuxt Shopify Logo](https://raw.githubusercontent.com/nuxt-modules/shopify/refs/heads/main/docs/public/logo-readme.jpg)

# Nuxt Shopify Module

[![Github Actions][github-actions-src]][github-actions-href]
[![NPM version][npm-version-src]][npm-version-href]
[![Nuxt Module Health][nuxt-health-src]][nuxt-health-href]
[![NPM last update][npm-last-update-src]][npm-last-update-href]
[![License][license-src]][license-href]

Fully typed fetch client for the [Shopify Storefront API](https://shopify.dev/docs/api/storefront), [Shopify Admin API](https://shopify.dev/docs/api/admin-graphql) and [Shopify Customer Account API](https://shopify.dev/docs/api/customer).
You can use it on the server and client side, with built-in support for [mock.shop](https://mock.shop) and automatic,
hot-reloaded type generation from your GraphQL queries.

- 📚 [Documentation](https://shopify.nuxtjs.org)
- 🛍️ [Store Template](https://github.com/nuxt-modules/shopify/tree/main/template)
- ✨ [Release Notes](https://github.com/nuxt-modules/shopify/tree/main/CHANGELOG.md)

## Features

- 🔗 Fully typed fetch client from GraphQL schemas
- 🔥 Hot-reloads types automatically when your GraphQL changes
- 🔐 Secure access token handling
- 🛒 Storefront, Customer Account and Admin API support
- 🌐 Server & client side support
- 🛠️ Automatic mock.shop integration
- 🚩 Error handling optimized for Nuxt
- 📡 Server-side proxy for API requests
- 🧩 GraphQL fragments support
- 🏎️ Caching for client and server-side requests
- ⚙️ Customizable GraphQL code generation
- 📦 Auto-imports for GraphQL queries and generated types
- 🪝 Webhook subscription support
- 🏖️ Sandbox integrated with GraphiQL Explorer
- 🔄 Hooks for customizing the module behavior
- 🧪 Tested with Nuxt 3 & 4

### Roadmap

Upcoming features and developments for the 1.0.0 release:

- 🔍 Shopify Analytics support

## 📦 Setup

> To get started immediately, you can use the [store template](https://github.com/nuxt-modules/shopify/tree/main/template) with a pre-configured Shopify store and module setup.

Run the following command to install the module in your project:

```bash
npx nuxi@latest module add shopify
```

<details>
<summary>Or use the manual installation</summary>

1. Install the module via npm:

   ```bash
   npm install @nuxtjs/shopify
   ```

2. Add the module to your `nuxt.config.ts`:

   ```ts
   export default defineNuxtConfig({
     modules: [
       '@nuxtjs/shopify',
     ],
   })
   ```
</details>

Add your Shopify configuration to the `nuxt.config.ts`:

```ts
export default defineNuxtConfig({
  shopify: {
    name: "my-shopify-store",

    clients: {
      storefront: {
        apiVersion: "2026-01",
        publicAccessToken: "YOUR_ACCESS_TOKEN",
      },

      admin: {
        apiVersion: "2026-01",
        clientId: "YOUR_APP_CLIENT_ID",
        clientSecret: "YOUR_APP_CLIENT_SECRET",
      },

      customerAccount: {
        apiVersion: "2026-01",
        clientId: "YOUR_CLIENT_ID",
      },
    },
  },
})
```

> To find the configuration values for your store, check out the [setup guide](https://shopify.nuxtjs.org/essentials/setup-shopify).

## Usage

### Access Storefront API on the client side

There are multiple ways of communicating with the Shopify APIs.
The easiest way is with the `useStorefront` composable, directly inside of your vue component or page.

> To access the `useStorefront` composable on the client side, make sure you have added a public access token. You can add it in the module config: `clients > storefront > publicAccessToken`

```html
<!-- ~/pages/your-page.vue -->

<script setup lang="ts">
const storefront = useStorefront()

const { data } = await storefront.request(`#graphql
  query FetchProducts($first: Int) {
    products(first: $first) {
      nodes {
        id
        title
        description
      }
    }
  }
`, {
  variables: {
    first: 3,
  },
})
</script>

<template>
  <pre>{{ data?.products }}</pre>
</template>
```

This will fetch the first three products from your Shopify store and display them in a `<pre>` tag.

The `data` variable will be typed as `FetchProductsQuery`, which is auto-generated by the module to enable autocompletion and full type checking.

You can use this generated `FetchProductsQuery` type anywhere in your code to ensure type safety when working with the query response within components.

### Use the Storefront API with useAsyncData

You can also use the `useStorefrontData` composable to fetch data from the Storefront API while leveraging Nuxt's built-in async data fetching under the hood.

```html
<!-- ~/pages/your-page.vue -->

<script setup lang="ts">
const { data: products, error } = await useStorefrontData("products", `#graphql
  query FetchProducts($first: Int) {
    products(first: $first) {
      nodes {
        id
        title
        description
      }
    }
  }
`, {
  variables: {
    first: 3,
  },
 
  // Use features from useAsyncData, e.g. transform, pick, etc.
  transform: (data) => flattenConnection(data.products),
})
</script>

<template>
  <pre>{{ products }}</pre>
</template>
```

Note that `useStorefrontData` automatically extracts the `data` property from the response in order to be able to reliably
stringify.
When using it together with the setting `errors: { throw: false }` you will need to check for errors manually within the response instead of using the `error` object returned by the `useStorefrontData` composable.

### Access APIs via Nitro endpoints

The module exposes utilities to access each API via Nitro endpoints.

#### Storefront API example

You can use the `useStorefront` utility to access the storefront API:

```ts
// ~/server/api/products.ts

export default defineEventHandler(async () => {
  const storefront = useStorefront()

  return await storefront.request(`#graphql
    query FetchProducts($first: Int) {
      products(first: $first) {
        nodes {
          id
          title
          description
        }
      }
    }
  `, {
    variables: {
      first: 3,
    },
  })
})
```

Notice how we can use the `graphql` directive inside the event handler, this is possible because in
the standard module configuration all `.ts` and `.gql` files are automatically processed for the
storefront API, as long as the don't end with `.admin.ts` or `.admin.gql`.
Read more about the [codegen configuration](https://shopify.nuxtjs.org/essentials/codegen).

Now we can call the API at `/api/products` to obtain the first three products:

```html
<!-- ~/pages/your-page.vue -->

<script setup lang="ts">
const { data } = await useFetch("/api/products")
</script>

<template>
  <pre>{{ data }}</pre>
</template>
```

The `data` variable will be typed as `Ref<ClientResponse<FetchProductsQuery>>`, which enables autocompletion and full
type checking.

#### Admin API example

Files ending with `.admin.ts` or `.admin.gql` will automatically be processed for the admin API.
We can use the `useAdmin` utility to access the admin API in a nitro event handler:

```ts
// ~/server/api/your-admin-api-handler.ts

export default defineEventHandler(async () => {
  const admin = useAdmin()

  return await admin.request(...)
})
```

For a full example, see [Admin API examples](https://shopify.nuxtjs.org/essentials/admin).

### Mock the Storefront API

To mock the Storefront API, you can use the `mock` option in the module config:

```ts
export default defineNuxtConfig({
  shopify: {
    name: "my-mocked-shopify-store",

    clients: {
      storefront: {
        mock: true,

        apiVersion: "2026-01",
      },
    },
  },
})
```

All requests to the Storefront API will now return data from [mock.shop](https://mock.shop) instead of hitting the actual Shopify API.

### Proxying client requests

All requests going out from the client side are proxied through the Nitro server by default.
To disable proxying, you can set the `proxy` option in the module config.
Proxying is only available in SSR mode.

```ts
export default defineNuxtConfig({
  shopify: {
    clients: {
      storefront: {
        proxy: true,
      },
    },
  },
})
```

### Type generation

Once installed, the module automatically generates your GraphQL types and saves them in:

- .nuxt/types — Type definitions
- .nuxt/schema — GraphQL schema files

To enable IDE support, you can add a GraphQL configuration file:

```yaml
# ~/graphql.config.yml

schema:
  - ./.nuxt/schema/storefront.schema.json
  - ./.nuxt/schema/admin.schema.json
```

### Handling GraphQL fragments

You can define reusable fragments in your GraphQL queries to avoid duplication and make your queries more maintainable. The module supports fragment usage out of the box.

Here's an example of how to define and use a fragment:

```graphql
#graphql
fragment ProductFields on Product {
  id
  title
  description
}

query FetchProducts($first: Int) {
  products(first: $first) {
    nodes {
      ...ProductFields
    }
  }
}
```

You can place this query in a `.gql`, `.ts` or `.vue` file and use it in your requests. The module will be able to import the fragment and allow you to use it directly within your GraphQL operation.

Files placed in the `~/graphql` directory will be automatically imported by the module, so it is recommended to organize your fragments there.

### Handling errors

By default, the module will throw an error if the storefront or admin client encounters an error instead of returning the errors object in the response.
This is done so that Nuxt can take over the error handling.

You can customize this behavior by setting the `errors.throw` option in the module config.

```ts
export default defineNuxtConfig({
  shopify: {
    errors: {
      throw: false,
    },
  },
})
```

This will prevent the module from throwing an error and instead return the error response.

The module also provides hooks to handle errors.

```ts
// ~/server/plugins/your-plugin.ts

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook("storefront:client:errors", ({ errors }) => {
    // Do something with the errors
    console.log("Storefront client errors:", errors)
  })
})
```

Read more about all available hooks in our [hooks documentation](https://shopify.nuxtjs.org/going-further/hooks).

### Caching API Requests

The module provides caching solutions for both client and server-side requests.
Client side caching is enabled globally by default and can be configured in the module options.
For each client side request, caching is opt-in by setting the `cache` option in the request options.

```html
<script setup lang="ts">
const storefront = useStorefront()

const { data } = await storefront.request(`#graphql
  query FetchProducts($first: Int) {
    products(first: $first) {
      nodes {
        ...ProductFields
      }
    }
  }
  ${PRODUCT_FRAGMENT}
`, {
  variables: {
    first: 5,
  },

  // Cache settings for this request, client and server side (proxy)
  cache: "short",

  // Or set client and server side cache separately
  cache: {
    client: "short",
    proxy: "long",
  },
})
</script>
```

This also applies to the `useStorefrontData` composable.

On the server side you can use nitro's built-in caching utilities within your API routes or plugins to cache requests
to both the storefront and admin API.

See the [caching documentation](https://shopify.nuxtjs.org/essentials/caching) for more details and examples.

### Subscribing / Unsubscribing webhooks

To subscribe or unsubscribe a webhook, you can either do so manually within the Shopify Admin UI or via Shopify's CLI.
The module also introduces a CLI command to easily add Webhooks from your local dev environment.

First, configure your webhooks:

```ts
export default defineNuxtConfig({
  modules: ["@nuxtjs/shopify"],

  shopify: {
    webhooks: {
      secret: "my-shopify-app-client-secret",

      hooks: {
        topic: "ORDERS_CREATE",
        uri: "https://shopify.nuxtjs.org/api/webhooks/orders-create",
      },
    },
  },
})
```

Then subscribe with the CLI command:

```sh
npx @nuxtjs/shopify@latest webhooks subscribe
```

To receive webhooks with Shopify's HMAC validation the module introduces `defineWebhookEventHandler`, which automatically
validates any incoming request against the app client secret.

Read more about webhooks in our [webhooks documentation](https://shopify.nuxtjs.org/going-further/webhooks).

## Maintainers

- Frederik Bußmann ([@freb97](https://github.com/freb97))
- Zoltan Lukacs ([@konkonam](https://github.com/konkonam))

## Contributing

1. Clone this repository
2. Create a `.env` file (see [`.env.example`](https://github.com/nuxt-modules/shopify/tree/main/.env.example))
3. Install dependencies using:
   ```bash
   bun install
   ```
4. Run `bun run prepare:dev` to generate type stubs.
5. Start the default [playground](https://github.com/nuxt-modules/shopify/tree/main/playgrounds/playground) with:
   ```bash
   bun run dev
   ```

## License

Published under the [MIT License](https://github.com/nuxt-modules/shopify/tree/main/LICENSE).

[github-actions-src]: https://github.com/nuxt-modules/shopify/actions/workflows/test.yml/badge.svg
[github-actions-href]: https://github.com/nuxt-modules/shopify/actions
[npm-version-src]: https://img.shields.io/npm/v/@nuxtjs/shopify/latest.svg?style=flat&colorA=18181B&colorB=31C553
[npm-version-href]: https://npmx.dev/package/@nuxtjs/shopify
[nuxt-health-src]: https://img.shields.io/endpoint?url=https://nuxt.care/api/v1/badge?module=shopify
[nuxt-health-href]: https://nuxt.care/?search=shopify
[npm-last-update-src]: https://img.shields.io/npm/last-update/%40nuxtjs%2Fshopify.svg?style=flat&colorA=18181B&colorB=31C553
[npm-last-update-href]: https://npmx.dev/package/@nuxtjs/shopify
[license-src]: https://img.shields.io/github/license/nuxt-modules/shopify.svg?style=flat&colorA=18181B&colorB=31C553
[license-href]: https://github.com/nuxt-modules/shopify/tree/main/LICENSE