Storefront API
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.
Usage
Once configured, you can use the Storefront API in your Nuxt application via the useStorefront
and useAsyncStorefront
composables.
Depending on where you want to use the API (server or client), you can choose between the two composables.
Client-side
useStorefront
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) {
...ProductFields
}
}
${PRODUCT_FRAGMENT}
`, {
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.
useAsyncStorefront
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 useAsyncStorefront
that automatically does this for us:
<script setup lang="ts">
const handle = 'high-top-sneakers'
const { data: product } = await useAsyncStorefront(`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>
Server-side
useStorefront
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) {
...ProductFields
}
}
${PRODUCT_FRAGMENT}
`, {
variables: {
handle,
}
})
})
Using validation
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.