Skip to content
Back to skills

2554 Hydrogen 083eca7c

ASecurity

Hydrogen is Shopify's framework for building custom headless storefronts, powered by React Router 7 (since Hydrogen 2025.5.0, replacing Remix).

  • 4 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 31, 2026
developmentjavascripttypescriptjavabashreactnodeapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned May 31, 2026

npx -y skills add tools-only/X-Skills --skill 2554-hydrogen_083eca7c --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2554 Hydrogen 083eca7c?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2554 Hydrogen 083eca7c
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2554-hydrogen-083eca7c/badge)](https://www.skillsdirectory.com/skills/tools-only-2554-hydrogen-083eca7c)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Hydrogen Reference

Hydrogen is Shopify's framework for building custom headless storefronts, powered by React Router 7 (since Hydrogen 2025.5.0, replacing Remix).

## Overview

| Item | Value |
|------|-------|
| Framework | React Router 7 (formerly Remix) |
| React version | React 19 |
| API | Storefront API (GraphQL) |
| Hosting | Shopify Oxygen (default) or any Node.js host |
| CLI | `npx shopify hydrogen` |
| Docs | [hydrogen.shopify.dev](https://hydrogen.shopify.dev) |

## Getting Started

### Create a Hydrogen project

```bash
# Create new project
npx shopify hydrogen init

# Options:
# - Template: skeleton, demo-store
# - Language: TypeScript (recommended), JavaScript
# - Styling: Tailwind CSS, vanilla CSS

# Project structure:
my-store/
├── app/
│   ├── components/          # Shared components
│   ├── lib/                 # Utilities and helpers
│   ├── routes/              # File-based routing
│   │   ├── _index.tsx       # Homepage
│   │   ├── products.$handle.tsx  # Product page
│   │   ├── collections.$handle.tsx
│   │   └── cart.tsx
│   ├── entry.client.tsx     # Client entry
│   ├── entry.server.tsx     # Server entry
│   └── root.tsx             # Root layout
├── public/                  # Static assets
├── .env                     # Environment variables
├── hydrogen.config.ts       # Hydrogen config
├── react-router.config.ts   # Route config
├── package.json
└── vite.config.ts
```

### Environment variables

```bash
# .env
SESSION_SECRET=your-secret
PUBLIC_STOREFRONT_API_TOKEN=your-public-token
PUBLIC_STORE_DOMAIN=your-store.myshopify.com

# Optional: for authenticated Storefront API
PRIVATE_STOREFRONT_API_TOKEN=your-private-token
```

## Routing

Hydrogen uses React Router 7 file-based routing:

| File | URL | Description |
|------|-----|-------------|
| `routes/_index.tsx` | `/` | Homepage |
| `routes/products.$handle.tsx` | `/products/snowboard` | Product page |
| `routes/collections.$handle.tsx` | `/collections/winter` | Collection page |
| `routes/collections._index.tsx` | `/collections` | Collections list |
| `routes/cart.tsx` | `/cart` | Cart page |
| `routes/search.tsx` | `/search` | Search results |
| `routes/pages.$handle.tsx` | `/pages/about` | CMS pages |
| `routes/account.tsx` | `/account` | Customer account (layout) |
| `routes/account.orders.$id.tsx` | `/account/orders/123` | Order detail |

## Data Loading

### Loader pattern (server-side data fetching)

```tsx
import { useLoaderData, type LoaderFunctionArgs } from 'react-router';

export async function loader({ params, context }: LoaderFunctionArgs) {
  const { storefront } = context;

  const { product } = await storefront.query(PRODUCT_QUERY, {
    variables: { handle: params.handle },
  });

  if (!product) {
    throw new Response('Product not found', { status: 404 });
  }

  return { product };
}

export default function ProductPage() {
  const { product } = useLoaderData<typeof loader>();

  return (
    <div>
      <h1>{product.title}</h1>
      <p>{product.description}</p>
      <ProductPrice price={product.priceRange.minVariantPrice} />
    </div>
  );
}

const PRODUCT_QUERY = `#graphql
  query Product($handle: String!) {
    product(handle: $handle) {
      id
      title
      handle
      description
      priceRange {
        minVariantPrice {
          amount
          currencyCode
        }
      }
      images(first: 10) {
        nodes {
          url
          altText
          width
          height
        }
      }
      variants(first: 100) {
        nodes {
          id
          title
          availableForSale
          price {
            amount
            currencyCode
          }
          selectedOptions {
            name
            value
          }
        }
      }
    }
  }
`;
```

### Action pattern (form submissions)

```tsx
import { type ActionFunctionArgs } from 'react-router';

export async function action({ request, context }: ActionFunctionArgs) {
  const formData = await request.formData();
  const variantId = formData.get('variantId') as string;
  const quantity = parseInt(formData.get('quantity') as string) || 1;

  const { cart } = context;

  const result = await cart.addLines([
    { merchandiseId: variantId, quantity },
  ]);

  return { cart: result.cart };
}
```

## Storefront API Client

Hydrogen provides a typed Storefront API client:

```tsx
// app/lib/storefront.ts - automatically configured

// Usage in loaders:
export async function loader({ context }: LoaderFunctionArgs) {
  const { storefront } = context;

  // Simple query
  const { products } = await storefront.query(PRODUCTS_QUERY, {
    variables: { first: 10 },
  });

  // With cache control
  const { collection } = await storefront.query(COLLECTION_QUERY, {
    variables: { handle: 'winter' },
    cache: storefront.CacheLong(),  // Cache for 1 hour
  });

  return { products, collection };
}
```

### Cache strategies

```tsx
// Built-in cache strategies
storefront.CacheNone()     // No caching (default for mutations)
storefront.CacheShort()    // 1 second stale, 60 seconds max
storefront.CacheLong()     // 1 hour stale, 1 day max
storefront.CacheCustom({
  mode: 'public',
  maxAge: 60,              // seconds
  staleWhileRevalidate: 300,
})
```

## Cart Operations

Hydrogen provides a cart API abstraction:

```tsx
// In loaders/actions, use context.cart
export async function action({ request, context }: ActionFunctionArgs) {
  const { cart } = context;
  const formData = await request.formData();

  switch (formData.get('action')) {
    case 'add':
      return cart.addLines([{
        merchandiseId: formData.get('variantId') as string,
        quantity: 1,
      }]);

    case 'update':
      return cart.updateLines([{
        id: formData.get('lineId') as string,
        quantity: parseInt(formData.get('quantity') as string),
      }]);

    case 'remove':
      return cart.removeLines([
        formData.get('lineId') as string,
      ]);

    case 'updateNote':
      return cart.updateNote(
        formData.get('note') as string,
      );

    default:
      throw new Error('Unknown cart action');
  }
}
```

### Cart component

```tsx
import { useFetcher } from 'react-router';
import { CartLineQuantity, CartLinePrice, Money } from '@shopify/hydrogen';

function AddToCartButton({ variantId }: { variantId: string }) {
  const fetcher = useFetcher();
  const isAdding = fetcher.state !== 'idle';

  return (
    <fetcher.Form method="post" action="/cart">
      <input type="hidden" name="action" value="add" />
      <input type="hidden" name="variantId" value={variantId} />
      <button type="submit" disabled={isAdding}>
        {isAdding ? 'Adding...' : 'Add to Cart'}
      </button>
    </fetcher.Form>
  );
}
```

## Hydrogen Components

Built-in components for common e-commerce patterns:

```tsx
import {
  Image,
  Money,
  ShopPayButton,
  Video,
  ExternalVideo,
  ModelViewer,
  MediaFile,
  CartLineQuantity,
  CartLinePrice,
} from '@shopify/hydrogen';

// Optimised image with CDN sizing
<Image
  data={product.images.nodes[0]}
  sizes="(min-width: 768px) 50vw, 100vw"
  aspectRatio="1/1"
/>

// Formatted price
<Money data={product.priceRange.minVariantPrice} />

// Shop Pay button
<ShopPayButton
  variantIds={[selectedVariant.id]}
  storeDomain={shop.primaryDomain.url}
/>
```

## SEO

```tsx
// In root.tsx or individual routes
import { getSeoMeta } from '@shopify/hydrogen';

export const meta = ({ data }) => {
  return getSeoMeta({
    title: data.product.title,
    description: data.product.description,
    url: `https://store.com/products/${data.product.handle}`,
    image: data.product.images.nodes[0]?.url,
  });
};
```

## Deployment

### Shopify Oxygen (recommended)

```bash
# Deploy to Oxygen
npx shopify hydrogen deploy

# Environment variables managed in Shopify admin:
# Settings > Hydrogen > Environment variables
```

### Self-hosted (Cloudflare Workers, Vercel, etc.)

```bash
# Build for production
npm run build

# Cloudflare Workers
npx wrangler deploy

# Node.js server
npm start
```

### Vite configuration

```typescript
// vite.config.ts
import { defineConfig } from 'vite';
import { hydrogen } from '@shopify/hydrogen/vite';
import { reactRouter } from '@react-router/dev/vite';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  plugins: [
    tailwindcss(),
    hydrogen(),
    reactRouter(),
  ],
});
```

## Best Practices

1. **Use cache strategies** - `CacheLong()` for collections, `CacheShort()` for cart
2. **Minimise Storefront API queries** - request only needed fields
3. **Use `defer`** for non-critical data to improve time-to-first-byte
4. **Implement SEO** with `getSeoMeta` on all public routes
5. **Use Hydrogen components** (Image, Money) for built-in optimisations
6. **Handle loading states** with `useFetcher` for cart operations
7. **Set up analytics** with Hydrogen's built-in analytics utilities
8. **Test with Oxygen** before deploying to production
9. **Use TypeScript** for type safety with Storefront API responses
10. **Keep queries colocated** with route files for maintainability

Files in this skill

  • README.md1 KB
  • skill.md9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…