The Storefront API is a public API that allows you to access your Shopify store's data, such as products, collections, and customer information. It is designed to be used in client-side applications, such as a Nuxt frontend. To use the Storefront API, you need to obtain a public or private access token.
Once configured, you can use the Storefront API in your Nuxt application via the useStorefront and useStorefrontData composables.
Depending on where you want to use the API (server or client), you can choose between the two composables.
When setting the publicAccessToken for the storefront client in the module configuration, you can use the useStorefront composable
in your client-side code. For example, in a page component:
<script setup lang="ts">
const storefront = useStorefront()
const { data: product } = await storefront.request(`#graphql
query GetProduct($handle: String!) {
product(handle: $handle) {
id
title
description
}
}
`, {
variables: {
handle: 'high-top-sneakers',
}
})
</script>
<template>
<div v-if="product">
<h1>{{ product.data.title }}</h1>
<p>{{ product.data.description }}</p>
</div>
</template>
You can also wrap use the useStorefront composable in another composable, to build an abstracted data fetching method:
export const useProduct = (handle: string) => {
const storefront = useStorefront()
return storefront.request(`#graphql
query GetProduct($handle: String!) {
product(handle: $handle) {
id
title
description
}
}
`, {
variables: {
handle,
}
})
}
This way, you can reuse the useProduct composable in multiple places in your application.
By default, each request from the client side is proxied through the Nitro server.
This behaviour can be customized by setting proxy: false in the storefront client config.
You can wrap the useStorefront call with Nuxt's useAsyncData composable to integrate into the hybrid rendering model.
To shorten the syntax, the module provides a composable called useStorefrontData that automatically does this for us:
<script setup lang="ts">
const handle = 'high-top-sneakers'
const { data: product } = await useStorefrontData(`product-${handle}`, `#graphql
query GetProduct($handle: String!) {
product(handle: $handle) {
id
title
description
}
}
`, {
variables: {
handle,
}
})
</script>
<template>
<div v-if="product">
<h1>{{ product.title }}</h1>
<p>{{ product.description }}</p>
</div>
</template>
When setting either the publicAccessToken or privateAccessToken for the storefront client in the module configuration,
you can use the useStorefront composable in your server-side code.
For example, in a server route:
export default defineEventHandler((event) => {
const handle = getRouterParam(event, 'handle')
const storefront = useStorefront()
return storefront.request(`#graphql
query GetProduct($handle: String!) {
product(handle: $handle) {
id
title
description
}
}
`, {
variables: {
handle,
}
})
})
Using Nitro's built-in input validation, you can match the variables of your GraphQL queries before sending them to the API.
For this example we'll use the Zod library, but you can use any validation library you like.
First, install the validation library:
npm install zod
Then, import it and create a schema:
import { z } from 'zod'
const schema = z.object({
first: z.number({ coerce: true }).min(1),
})
coerce option is used to convert the string value of the first variable to a number and then match it
against the Zod schema. In Nitro, the query variables are always strings, so we convert to a number here before we
pass it to the API.Next, we can use Nitro's built-in getValidatedQuery utility to validate the query variables:
import { z } from 'zod'
const schema = z.object({
first: z.number({ coerce: true }).min(1),
})
export default defineEventHandler(async () => {
const storefront = useStorefront()
const variables = await getValidatedQuery(event, schema.parse)
const query = `#graphql
query FetchProducts($first: Int) {
products(first: $first) {
nodes {
id
title
description
}
}
}
`
return storefront.request(query, { variables })
})
Now we can call the API at /api/products with the following variables:
// Requests /api/products?first=1
const response = await useFetch('/api/products', {
query: {
first: 1,
},
})
With the validation, requests will fail before reaching Shopify if the variable first is not a number.