Skip to content


Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

AKVA - An example storefront powered by Sanity + Hydrogen

This demo is compatible with @shopify/hydrogen ~= 1.0.0

Demo | Sanity Studio | Sanity Connect for Shopify


AKVA is our customized Hydrogen starter that presents a real-world example of how Sanity and Structured Content can elevate your custom Shopify storefronts.

It's designed to be used alongside our pre-configured Studio and Sanity Connect for Shopify, which syncs products and collections from your Shopify storefront to your Sanity dataset.

This starter showcases a few patterns you can adopt when creating your own custom storefronts. Use Sanity and Hydrogen to delight customers with rich, shoppable editorial experiences that best tell your story.


View the feature gallery

This TypeScript demo adopts many of Hydrogen's framework conventions and third-party libraries. If you've used Hydrogen then you should hopefully feel at home here.

Account management is currently absent from this demo but will be introduced at a later date.

Fetching Sanity data

This demo comes with a custom useSanityQuery hook that allows you to query your Sanity dataset directly from server components.

// MyServerComponent.server.jsx
import useSanityQuery from './hooks/useSanityQuery';

const QUERY = `*[_type == 'page' && slug.current == $slug]`;
const PARAMS = {slug: 'about'};

export default function MyServerComponent() {
  const {data, error} = useSanityQuery({
    // Required
    query: QUERY,
    // Optional
    params: PARAMS,
    // Optional: pass through any useQuery options
    hydrogenQueryOptions: {
      preload: false,
  return <div>{JSON.stringify(data)}</div>;

The hook itself is super lightweight - it uses our official @sanity/client library wrapped in a Hydrogen useQuery hook to make it suspense-friendly. That's it!

What happened to hydrogen-plugin-sanity?

We've deprecated this plugin as it promoted conducting larger fetches (at the page level) and using shared context.

In practice, this was very difficult to reason about and worked against the benefits of using React Server Components.

We recommend that you keep fetching logic scoped to the specific components that need them, even if they are deeply nested in Portable Text.

Whilst this will may mean more queries, you'll have much better control over exactly how much you're fetching from the Storefront API as well as being able to define component-specific caching / prefetching logic.


We've taken the following opinions on how we've approached this demo.

Shopify is the source of truth for non-editorial content
  • For products, this includes titles, handles, variant images and product options.
  • For collections, this includes titles and collection images.
Shopify data stored in our Sanity dataset is used to improve the editor experience
  • This allows us to display things like product status, prices and even inventory levels right in our Sanity Studio.
  • Our application always fetches from Shopify's Storefront API at runtime to ensure we have the freshest data possible, especially important when dealing with fast-moving inventory.
Collections are managed entirely by Shopify
  • Shopify is used to handle collection rules and sort orders.
Product options are customized in Sanity
  • Data added to specific product options (for example, associating a hex value with the color 'Red', or a string value with the Poster size 'A2') is done in Sanity.
  • We treat this quite simply and manage these in a dedicated field within the Settings section of our studio. We also make sure to query this field whenever querying products in our Sanity dataset.
  • This could alternatively be managed with Shopify's metatags.
We don't surface Shopify HTML descriptions and metatags
  • For this demo, Shopify tags are used purely as a non-visual organizational tool (to drive automated collections) and we use Portable Text over Shopify's description HTML field. However, Hydrogen makes it very easy to surface these in your application if needed.
Non-product (regular) pages are managed entirely by Sanity
  • Shopify pages and blog posts (associated with the Online Store) channel aren't used in this demo. A dedicated page document type in Sanity has been created for this purpose.
We query our Sanity dataset when building sitemap.xml entries
  • We use Sanity as the source of truth when determining whether a product or collection page is visible.
  • This gives us the flexibility to add custom logic to control whether certain pages should be visible or not. For example, if you wanted to hide product pages within a specific date range, or hide collections that didn't have any editorial modules assigned to them.

Getting started


  • Node.js version 16.5.0 or higher
  • Yarn


  1. Update the following configuration files (optional)

    • sanity.config.ts: point to your Sanity project's dataset and projectId
    • hydrogen.config.ts: point to your Shopify storefront's storeDomain and storefrontToken

    You can skip this step if you'd like to run the starter with our test data.

    Remember to update your shop's domain and Storefront API token!

  2. Install dependencies and start the development server

    yarn dev
  3. Visit the development environment running at http://localhost:3000.

Previewing a production build

To run a local preview of your Hydrogen app in an environment similar to Oxygen, build your Hydrogen app and then run yarn preview:

yarn build
yarn preview

Building for production

yarn build

Then, you can run a local server.js using the production build with:

yarn serve


See Hydrogen's documentation on deployment


This repository is published under the MIT license.


A starter for Hydrogen + Sanity projects