Lesson
6
Fetching Sanity content
Log in to mark your progress for each Lesson and Task
Your front-end is only telling half the story. Bring your products to life with extra content from your Sanity project.
In many Remix projects, you'll never interact with the server.ts
file. However in Hydrogen it comes preconfigured with the Storefront client with functions for fetching products and caching.
You'll extend this file with Sanity functions for data fetching.
The hydrogen-sanity
package contains a number of useful functions to simplify querying and displaying content from Sanity.
Install
hydrogen-sanity
and other packagesnpm install hydrogen-sanity @portabletext/react
- @portabletext/react is a React component for rendering block content which is authored in Sanity Studio
Sanity Client allows you to query (and mutate) content.
You’ll need a Sanity Client configured with your Project ID and dataset name available to any route.
Add your Sanity project details to the Hydrogen project's .env
file. You can find these either in sanity.io/manage or in the sanity.config.ts
file of your Studio.
.env
# Project IDSANITY_PROJECT_ID=""# Dataset nameSANITY_DATASET=""# (Optional) Sanity API versionSANITY_API_VERSION=""
Satisfy TypeScript by adding these variables to Remix's global types.
./env.d.ts
declare global { // ...other Types
interface Env { // ...other variables SANITY_PROJECT_ID: string SANITY_DATASET: string SANITY_API_VERSION: string SANITY_API_TOKEN: string }}
The code example below contains new lines to paste into your Hydrogen project’s server file.
Open
./server.ts
and update it to include Sanity Client./server.ts
// ...all other imports// Add imports for Sanity Loader and Preview Sessionimport {createSanityLoader} from 'hydrogen-sanity'
import { // ... all other @shopify/hydrogen imports createWithCache,} from '@shopify/hydrogen';
// Inside the default exportexport default () => { // ... Leave all other functions like the storefront client as-is // (Prerequisite) If not already initialized, create a `withCache` handler... const withCache = createWithCache({cache, waitUntil, request})
// 1. Configure the Sanity Loader and preview mode const sanity = createSanityLoader({ // Required: withCache, // Required: // Pass configuration options for Sanity client or an instantialized client client: { projectId: env.SANITY_PROJECT_ID, dataset: env.SANITY_DATASET, apiVersion: env.SANITY_API_VERSION || '2023-03-30', useCdn: process.env.NODE_ENV === 'production', }, })
// 2. Make Sanity available to all action and loader contexts const handleRequest = createRequestHandler({ // ...other settings getLoadContext: () => ({ // ...other providers withCache, sanity, }), })}
Now a configured Sanity React Loader is available inside the Hydrogen “context” as sanity
, just like the preconfigured storefront
.
You'll use loadQuery
to retrieve content from Sanity. It's configured in a way to make setting up Visual Editing simple. For now, you'll just use the initial data in the default export to render content.
Update the route for all product pages to query for Sanity content
./app/routes/products.$handle.tsx
import {json, type LoaderFunctionArgs} from '@shopify/remix-oxygen';import {Link, useLoaderData} from '@remix-run/react';import type {Product} from '@shopify/hydrogen/storefront-api-types';import {PortableText} from '@portabletext/react';import type {SanityDocument} from '@sanity/client';import {groq} from 'hydrogen-sanity/groq';
export async function loader({ params, context: {storefront, sanity},}: LoaderFunctionArgs) { const {product} = await storefront.query<{product: Product}>( `#graphql query Product($handle: String!) { product(handle: $handle) { id title } } `, {variables: params}, );
const query = groq`*[_type == "product" && store.slug.current == $handle][0]{ body, "image": store.previewImageUrl }`; const initial = await sanity.loadQuery<SanityDocument>(query, params);
return json({product, initial});}
export default function Page() { const {product, initial} = useLoaderData<typeof loader>(); const page = initial.data;
return ( <div className="mx-auto p-12 prose prose-a:text-blue-500"> <h1 className="text-3xl font-bold">{product.title}</h1> <img alt={product.title} src={page.image} className="size-32 not-prose mb-6 mr-6 object-cover float-left rounded-xl" /> {page?.body?.length > 0 ? <PortableText value={page.body} /> : null} <p> <Link to="/products">← Back to All Products</Link> </p> </div> );}
Read the documentation on GROQ for more on querying content from Sanity
Visit any product page now, and you should see both the product title from Shopify and the contents of the Portable Text field in the Sanity document for that same product.
If there's no extra text showing, edit the LULU Mini Pot product in your Studio and add the following text:
All of our products are made from 100% recycled materials and are finished with a waterproof sealant. We recommend cleaning your LULU Pot regularly with hot soapy water. Please do not leave the pot to soak. Alternatively our products are dishwasher safe.
Your page should now look like this.
If your CSS looks slightly off, try emptying the contents of reset.css
as it conflicts with some Tailwind Typography styles.
Your Hydrogen app now queries content from both Sanity and Shopify independently, displaying in a consistent front-end.
Sanity content is more than just a paragraph of text – let’s embellish this with some rich content blocks!
You have 4 uncompleted tasks in this lesson
0 of 4