From shopify-commerce
Build headless Shopify storefronts with Hydrogen: Remix SSR patterns, Oxygen deployment, Storefront API queries, caching strategies, cart, customer accounts, SEO, analytics.
npx claudepluginhub orcaqubits/agentic-commerce-skills-plugins --plugin shopify-commerceThis skill is limited to using the following tools:
**Fetch live docs**:
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides MCP server integration in Claude Code plugins via .mcp.json or plugin.json configs for stdio, SSE, HTTP types, enabling external services as tools.
Fetch live docs:
https://shopify.dev/docs/storefronts/headless/hydrogen for Hydrogen documentationsite:shopify.dev hydrogen remix loader action for data fetching patternssite:github.com shopify hydrogen for source, examples, and demo storesite:shopify.dev hydrogen cart for current cart handler APIsite:shopify.dev hydrogen customer accounts for authentication flowHydrogen is Shopify's React-based framework for headless commerce:
DEPRECATION: The JS Buy SDK (EOL July 2025) should NOT be used. Use Hydrogen or the Storefront API directly.
npm create @shopify/hydrogen@latest -- --template demo-store
# or
shopify hydrogen init
app/
├── components/ # Shared React components
├── lib/
│ └── context.ts # Storefront client setup
├── routes/
│ ├── _index.tsx # Homepage
│ ├── products.$handle.tsx # Product detail (dynamic route)
│ ├── collections.$handle.tsx
│ ├── cart.tsx # Cart page
│ └── account.tsx # Customer account
├── entry.server.tsx # Server entry point
└── root.tsx # Root layout
The storefront client is created in your app context and used in loaders:
// Pattern: create storefront client in context
// Fetch live docs for current createStorefrontClient options
const { storefront } = createStorefrontClient({
storeDomain: env.PUBLIC_STORE_DOMAIN,
storefrontApiVersion: env.PUBLIC_STOREFRONT_API_VERSION,
publicStorefrontToken: env.PUBLIC_STOREFRONT_API_TOKEN,
});
// Pattern: loader fetches data via storefront.query with caching
// Fetch live docs for current Storefront API fields and query syntax
export async function loader({ params, context }: LoaderFunctionArgs) {
const { storefront } = context;
const { product } = await storefront.query(PRODUCT_QUERY, {
variables: { handle: params.handle },
cache: CacheLong(), // apply caching strategy
});
if (!product) throw new Response("Not found", { status: 404 });
return json({ product });
}
export default function ProductPage() {
const { product } = useLoaderData<typeof loader>();
return <div><h1>{product.title}</h1></div>;
}
Fetch live docs for the current Storefront API product query fields — the schema expands quarterly.
// Pattern: action handles form submissions (e.g., cart mutations)
export async function action({ request, context }: ActionFunctionArgs) {
const { cart } = context;
const formData = await request.formData();
// Fetch live docs for current cart handler methods
const result = await cart.addLines([
{ merchandiseId: formData.get("variantId"), quantity: 1 },
]);
return json(result);
}
| Strategy | Behavior | Use For |
|---|---|---|
CacheLong() | Long TTL + long SWR | Products, collections, pages |
CacheShort() | Short TTL + short SWR | Cart, dynamic content |
CacheNone() | No caching | Customer-specific data |
CacheCustom({...}) | Custom maxAge + SWR | Fine-tuned scenarios |
Applied as second argument to storefront.query().
Fetch live docs for exact TTL values —
CacheLongandCacheShortdefault durations may change across Hydrogen versions.
// Pattern: defer non-critical data for progressive rendering
export async function loader({ context }: LoaderFunctionArgs) {
// Critical — awaited before render
const collection = await context.storefront.query(COLLECTION_QUERY);
// Non-critical — streamed after initial render
const recommendations = context.storefront.query(RECS_QUERY);
return defer({ collection, recommendations });
}
export default function Page() {
const { collection, recommendations } = useLoaderData<typeof loader>();
return (
<div>
<h1>{collection.title}</h1>
<Suspense fallback={<p>Loading...</p>}>
<Await resolve={recommendations}>
{(data) => <RecommendedProducts data={data} />}
</Await>
</Suspense>
</div>
);
}
// Pattern: route-level error handling
import { isRouteErrorResponse, useRouteError } from "@remix-run/react";
export function ErrorBoundary() {
const error = useRouteError();
if (isRouteErrorResponse(error)) {
return <div><h1>{error.status === 404 ? "Not Found" : "Error"}</h1></div>;
}
return <div><h1>Something went wrong</h1></div>;
}
Built-in cart management:
createCartHandler() — server-side cart APIuseFetcher for cart mutations (avoids full page navigation)Fetch live docs: Web-search
site:shopify.dev hydrogen createCartHandlerfor current cart handler methods and return types.
New Customer Account API (OAuth-based):
/account/login → redirects to Shopify-hosted login (passwordless)/account/authorize → callback with tokensFetch live docs: Web-search
site:shopify.dev hydrogen customer accountsfor current OAuth flow, Customer Account API queries, and route setup.
Built-in SEO utilities:
getSeoMeta() — generates meta tags from Storefront API dataFetch live docs: Web-search
site:shopify.dev hydrogen seofor currentgetSeoMetaAPI and structured data helpers.
Shopify's edge hosting:
Alternative hosts: Vercel, Cloudflare Workers, Node.js servers (any platform that runs Remix).
CacheLong for stable data, CacheShort for dynamic)defer() for non-critical data to avoid blocking render<Await> component for deferred data rendering?width=, ?crop=)useFetcher for cart mutations (avoids full page navigation)<Link prefetch="intent">Fetch the Hydrogen docs, Remix documentation, and Hydrogen GitHub source for exact loader/action patterns, caching APIs, cart handler methods, and deployment configuration before implementing.