--- title: createStorefrontClient description: This function extends createStorefrontClient from Hydrogen React. api_version: 2026-04 api_name: hydrogen source_url: html: https://shopify.dev/docs/api/hydrogen/2025-01/utilities/createstorefrontclient md: https://shopify.dev/docs/api/hydrogen/2025-01/utilities/createstorefrontclient.md --- # createStorefrontClient This function extends `createStorefrontClient` from [Hydrogen React](https://shopify.dev/docs/api/hydrogen-react/utilities/createstorefrontclient). The additional arguments enable internationalization (i18n), caching, and other features particular to React Router and Oxygen. The returned storefront client includes methods for proxying requests (`forward`, `isStorefrontApiUrl`) and collecting tracking information (`setCollectedSubrequestHeaders`). Learn more about [data fetching in Hydrogen](https://shopify.dev/docs/custom-storefronts/hydrogen/data-fetching/fetch-data). #### Parameters **`HydrogenClientProps & StorefrontClientProps`** ### HydrogenClientProps * **cache** **Cache** An instance that implements the [Cache API](https://developer.mozilla.org/en-US/docs/Web/API/Cache) * **i18n** **TI18n** An object containing a country code and language code * **logErrors** **boolean | ((error?: Error) => boolean)** Whether it should print GraphQL errors automatically. Defaults to true * **storefrontHeaders** **StorefrontHeaders** Storefront API headers. If on Oxygen, use `getStorefrontHeaders()` * **storefrontId** **string** The globally unique identifier for the Shop * **waitUntil** **WaitUntil** The `waitUntil` function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform. ### StorefrontClientProps * **contentType** **'json' | 'graphql'** Customizes which `"content-type"` header is added when using `getPrivateTokenHeaders()` and `getPublicTokenHeaders()`. When fetching with a `JSON.stringify()`-ed `body`, use `"json"`. When fetching with a `body` that is a plain string, use `"graphql"`. Defaults to `"json"` Can also be customized on a call-by-call basis by passing in `'contentType'` to both `getPrivateTokenHeaders({...})` and `getPublicTokenHeaders({...})`, for example: `getPublicTokenHeaders({contentType: 'graphql'})` * **privateStorefrontToken** **string** The Storefront API delegate access token. Refer to the [authentication](https://shopify.dev/api/storefront#authentication) and [delegate access token](https://shopify.dev/apps/auth/oauth/delegate-access-tokens) documentation for more details. * **publicStorefrontToken** **string** The Storefront API access token. Refer to the [authentication](https://shopify.dev/api/storefront#authentication) documentation for more details. * **storeDomain** **string** The host name of the domain (eg: `{shop}.myshopify.com`). * **storefrontApiVersion** **string** The Storefront API version. This should almost always be the same as the version Hydrogen React was built for. Learn more about Shopify [API versioning](https://shopify.dev/api/usage/versioning) for more details. ### HydrogenClientProps * cache An instance that implements the \[Cache API]\(https://developer.mozilla.org/en-US/docs/Web/API/Cache) ```ts Cache ``` * i18n An object containing a country code and language code ```ts TI18n ``` * logErrors Whether it should print GraphQL errors automatically. Defaults to true ```ts boolean | ((error?: Error) => boolean) ``` * storefrontHeaders Storefront API headers. If on Oxygen, use \`getStorefrontHeaders()\` ```ts StorefrontHeaders ``` * storefrontId The globally unique identifier for the Shop ```ts string ``` * waitUntil The \`waitUntil\` function is used to keep the current request/response lifecycle alive even after a response has been sent. It should be provided by your platform. ```ts WaitUntil ``` ### StorefrontClientProps * contentType Customizes which \`"content-type"\` header is added when using \`getPrivateTokenHeaders()\` and \`getPublicTokenHeaders()\`. When fetching with a \`JSON.stringify()\`-ed \`body\`, use \`"json"\`. When fetching with a \`body\` that is a plain string, use \`"graphql"\`. Defaults to \`"json"\` Can also be customized on a call-by-call basis by passing in \`'contentType'\` to both \`getPrivateTokenHeaders({...})\` and \`getPublicTokenHeaders({...})\`, for example: \`getPublicTokenHeaders({contentType: 'graphql'})\` ```ts 'json' | 'graphql' ``` * privateStorefrontToken The Storefront API delegate access token. Refer to the \[authentication]\(https://shopify.dev/api/storefront#authentication) and \[delegate access token]\(https://shopify.dev/apps/auth/oauth/delegate-access-tokens) documentation for more details. ```ts string ``` * publicStorefrontToken The Storefront API access token. Refer to the \[authentication]\(https://shopify.dev/api/storefront#authentication) documentation for more details. ```ts string ``` * storeDomain The host name of the domain (eg: \`{shop}.myshopify.com\`). ```ts string ``` * storefrontApiVersion The Storefront API version. This should almost always be the same as the version Hydrogen React was built for. Learn more about Shopify \[API versioning]\(https://shopify.dev/api/usage/versioning) for more details. ```ts string ``` #### Returns * **storefront** **StorefrontForDoc\** ### StorefrontForDoc * cache The cache instance passed in from the \`createStorefrontClient\` argument. ```ts Cache ``` * CacheCustom Re-export of \[\`CacheCustom\`]\(/docs/api/hydrogen/utilities/cachecustom). ```ts (overrideOptions: AllCacheOptions) => AllCacheOptions ``` * CacheLong Re-export of \[\`CacheLong\`]\(/docs/api/hydrogen/utilities/cachelong). ```ts (overrideOptions?: AllCacheOptions) => AllCacheOptions ``` * CacheNone Re-export of \[\`CacheNone\`]\(/docs/api/hydrogen/utilities/cachenone). ```ts () => NoStoreStrategy ``` * CacheShort Re-export of \[\`CacheShort\`]\(/docs/api/hydrogen/utilities/cacheshort). ```ts (overrideOptions?: AllCacheOptions) => AllCacheOptions ``` * generateCacheControlHeader Re-export of \[\`generateCacheControlHeader\`]\(/docs/api/hydrogen/utilities/generatecachecontrolheader). ```ts (cacheOptions: AllCacheOptions) => string ``` * getApiUrl Creates the fully-qualified URL to your store's GraphQL endpoint. See \[\`getStorefrontApiUrl\` in Hydrogen React]\(/docs/api/hydrogen-react/2026-04/utilities/createstorefrontclient#:\~:text=storeDomain-,getStorefrontApiUrl,-(props%3F%3A) for more details. ```ts (props?: Partial>) => string ``` * getPrivateTokenHeaders Returns an object that contains headers that are needed for each query to Storefront API GraphQL endpoint for API calls made from a server. See \[\`getPrivateTokenHeaders\` in Hydrogen React]\(/docs/api/hydrogen-react/2026-04/utilities/createstorefrontclient#:\~:text=storefrontApiVersion-,getPrivateTokenHeaders,-(props%3F%3A) for more details. ```ts (props?: Partial> & Pick & { buyerIp?: string; }) => Record ``` * getPublicTokenHeaders Returns an object that contains headers that are needed for each query to Storefront API GraphQL endpoint. See \[\`getPublicTokenHeaders\` in Hydrogen React]\(/docs/api/hydrogen-react/2026-04/utilities/createstorefrontclient#:\~:text=%27graphql%27.-,getPublicTokenHeaders,-(props%3F%3A) for more details. ```ts (props?: Partial> & Pick) => Record ``` * getShopifyDomain Creates the fully-qualified URL to your myshopify.com domain. See \[\`getShopifyDomain\` in Hydrogen React]\(/docs/api/hydrogen-react/2026-04/utilities/createstorefrontclient#:\~:text=StorefrontClientReturn-,getShopifyDomain,-(props%3F%3A) for more details. ```ts (props?: Partial>) => string ``` * i18n The \`i18n\` object passed in from the \`createStorefrontClient\` argument. ```ts TI18n ``` * mutate The function to run a mutation on Storefront API. ```ts (mutation: string, options: StorefrontMutationOptionsForDocs) => Promise ``` * query The function to run a query on Storefront API. ```ts (query: string, options: StorefrontQueryOptionsForDocs) => Promise ``` ### AllCacheOptions Override options for a cache strategy. * maxAge The maximum amount of time in seconds that a resource will be considered fresh. See \`max-age\` in the \[MDN docs]\(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#:\~:text=Response%20Directives-,max%2Dage,-The%20max%2Dage). ```ts number ``` * mode The caching mode, generally \`public\`, \`private\`, or \`no-store\`. ```ts string ``` * sMaxAge Similar to \`maxAge\` but specific to shared caches. See \`s-maxage\` in the \[MDN docs]\(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#s-maxage). ```ts number ``` * staleIfError Indicate that the cache should serve the stale response if an error occurs while revalidating the cache. See \`stale-if-error\` in the \[MDN docs]\(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error). ```ts number ``` * staleWhileRevalidate Indicate that the cache should serve the stale response in the background while revalidating the cache. See \`stale-while-revalidate\` in the \[MDN docs]\(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-while-revalidate). ```ts number ``` ### NoStoreStrategy * mode ```ts string ``` ### StorefrontMutationOptionsForDocs * displayName The name of the query for debugging in the Subrequest Profiler. ```ts string ``` * headers Additional headers for this query. ```ts HeadersInit ``` * storefrontApiVersion Override the Storefront API version for this query. ```ts string ``` * variables The variables for the GraphQL mutation statement. ```ts Record ``` ### StorefrontError * errors ```ts StorefrontApiErrors ``` ### StorefrontApiErrors ```ts JsonGraphQLError[] | undefined ``` ### JsonGraphQLError * extensions Reserved for implementors to extend the protocol however they see fit, and hence there are no additional restrictions on its contents. ```ts { [key: string]: unknown; } ``` * locations If an error can be associated to a particular point in the requested GraphQL document, it should contain a list of locations. ```ts { line: number; column: number; }[] ``` * message ```ts string ``` * name ```ts string ``` * path If an error can be associated to a particular field in the GraphQL result, it \_must\_ contain an entry with the key \`path\` that details the path of the response field which experienced the error. This allows clients to identify whether a null result is intentional or caused by a runtime error. ```ts (string | number)[] ``` * stack ```ts string ``` ### StorefrontQueryOptionsForDocs * cache The cache strategy for this query. Default to max-age=1, stale-while-revalidate=86399. ```ts CachingStrategy ``` * displayName The name of the query for debugging in the Subrequest Profiler. ```ts string ``` * headers Additional headers for this query. ```ts HeadersInit ``` * storefrontApiVersion Override the Storefront API version for this query. ```ts string ``` * variables The variables for the GraphQL query statement. ```ts Record ``` ### CachingStrategy Use the \`CachingStrategy\` to define a custom caching mechanism for your data. Or use one of the pre-defined caching strategies: CacheNone, CacheShort, CacheLong. * maxAge The maximum amount of time in seconds that a resource will be considered fresh. See \`max-age\` in the \[MDN docs]\(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#:\~:text=Response%20Directives-,max%2Dage,-The%20max%2Dage). ```ts number ``` * mode The caching mode, generally \`public\`, \`private\`, or \`no-store\`. ```ts string ``` * sMaxAge Similar to \`maxAge\` but specific to shared caches. See \`s-maxage\` in the \[MDN docs]\(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#s-maxage). ```ts number ``` * staleIfError Indicate that the cache should serve the stale response if an error occurs while revalidating the cache. See \`stale-if-error\` in the \[MDN docs]\(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-if-error). ```ts number ``` * staleWhileRevalidate Indicate that the cache should serve the stale response in the background while revalidating the cache. See \`stale-while-revalidate\` in the \[MDN docs]\(https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#stale-while-revalidate). ```ts number ``` Examples ### Examples * #### Example code ##### JavaScript ```js import {createStorefrontClient} from '@shopify/hydrogen'; import { createRequestHandler, getStorefrontHeaders, } from '@shopify/hydrogen/oxygen'; export default { async fetch(request, env, executionContext) { /* Create a Storefront client with your credentials and options */ const {storefront} = createStorefrontClient({ /* Cache API instance */ cache: await caches.open('hydrogen'), /* Runtime utility in serverless environments */ waitUntil: (p) => executionContext.waitUntil(p), /* Private Storefront API token for your store */ privateStorefrontToken: env.PRIVATE_STOREFRONT_API_TOKEN, /* Public Storefront API token for your store */ publicStorefrontToken: env.PUBLIC_STOREFRONT_API_TOKEN, /* Your store domain: "{shop}.myshopify.com" */ storeDomain: env.PUBLIC_STORE_DOMAIN, /** * Storefront API headers containing: * - buyerIp: The IP address of the customer. * - requestGroupId: A unique ID to group all the logs for this request. * - cookie: The 'cookie' header from the request. */ storefrontHeaders: getStorefrontHeaders(request), }); const handleRequest = createRequestHandler({ build: remixBuild, mode: process.env.NODE_ENV, /* Inject the Storefront client in the Remix context */ getLoadContext: () => ({storefront}), }); return handleRequest(request); }, }; ``` ##### TypeScript ```ts import {createStorefrontClient} from '@shopify/hydrogen'; import * as serverBuild from 'virtual:react-router/server-build'; import { createRequestHandler, getStorefrontHeaders, } from '@shopify/hydrogen/oxygen'; export default { async fetch( request: Request, env: Record, executionContext: ExecutionContext, ) { /* Create a Storefront client with your credentials and options */ const {storefront} = createStorefrontClient({ /* Cache API instance */ cache: await caches.open('hydrogen'), /* Runtime utility in serverless environments */ waitUntil: (p: Promise) => executionContext.waitUntil(p), /* Private Storefront API token for your store */ privateStorefrontToken: env.PRIVATE_STOREFRONT_API_TOKEN, /* Public Storefront API token for your store */ publicStorefrontToken: env.PUBLIC_STOREFRONT_API_TOKEN, /* Your store domain: "{shop}.myshopify.com" */ storeDomain: env.PUBLIC_STORE_DOMAIN, /** * Storefront API headers containing: * - buyerIp: The IP address of the customer. * - requestGroupId: A unique ID to group all the logs for this request. * - cookie: The 'cookie' header from the request. */ storefrontHeaders: getStorefrontHeaders(request), }); const handleRequest = createRequestHandler({ build: serverBuild, mode: process.env.NODE_ENV, /* Inject the Storefront client in the Remix context */ getLoadContext: () => ({storefront}), }); return handleRequest(request); }, }; ``` *** ## Related [- CacheNone](https://shopify.dev/docs/api/hydrogen/2026-04/utilities/caching/cachenone) [- CacheShort](https://shopify.dev/docs/api/hydrogen/2026-04/utilities/caching/cacheshort) [- CacheLong](https://shopify.dev/docs/api/hydrogen/2026-04/utilities/caching/cachelong) [- CacheCustom](https://shopify.dev/docs/api/hydrogen/2026-04/utilities/caching/cachecustom) [- InMemoryCache](https://shopify.dev/docs/api/hydrogen/2026-04/utilities/caching/inmemorycache) ***