Give feedback as an early user and get the docs plus a full website free. Code FRIEND: valid on one-time purchases only.

Ecommerce with Shopify

The Shopify branch instantly adds a shop to your site by simply supplying Storefront API credentials. At build time, fresh data from the Shopify backend is fetched and used to dynamically render pages with full cart and checkout functionality.

Before You Start

Make sure you've read the initial setup guide.

See Quick Setup

Option 1: Shopify Buy Button

The easiest way to sell, an embeddable button that works on any static site.

Shopify generates embeddable product buttons that drop into any page. Shopify handles the cart and checkout entirely, so there's no backend logic to wire up, you just paste a snippet where you want the button to appear.

Steps

  1. 1Create a Shopify store.
  2. 2Install the Buy Button sales channel.
  3. 3Create a Buy Button for a product.
  4. 4Copy the generated JavaScript snippet.
  5. 5Paste it into an Astro component.

Example Astro component

Paste the snippet Shopify generates into a component, then render it on any page. Swap in your store domain, Storefront access token, and product ID.

---
// src/components/Product.astro
---

<div id="product-component"></div>

<script>
  const client = ShopifyBuy.buildClient({
    domain: "your-store.myshopify.com",
    storefrontAccessToken: "YOUR_TOKEN",
  });

  ShopifyBuy.UI.onReady(client).then((ui) => {
    ui.createComponent("product", {
      id: "123456789",
      node: document.getElementById("product-component"),
    });
  });
</script>

Pros

  • Fastest setup
  • Shopify handles cart and checkout

Cons

  • Limited customization
  • Doesn't feel fully integrated
Recommended

Option 2: Storefront API

The most common headless Shopify + Astro setup. Astro stays static and excellent at performance, while Shopify still handles payments. Everything below covers this approach.

How the store works

  1. 1

    Connect

    Supply your Storefront API credentials

  2. 2

    Fetch

    Fresh product data is pulled at build time

  3. 3

    Render

    Listing & detail pages generate automatically

  4. 4

    Sell

    Cart API builds the cart, Shopify hosts checkout

Where to start

Add your credentials, install dependencies, and run the dev server.

1. Create your .env file

Copy .env.example to .env and add your Shopify store URL along with your public and private access tokens.

# .env ,  copy from .env.example, then fill in your values
PUBLIC_SHOPIFY_STORE_URL=your-store.myshopify.com
PUBLIC_SHOPIFY_STOREFRONT_TOKEN=your_public_access_token
PRIVATE_SHOPIFY_STOREFRONT_TOKEN=your_private_access_token

2. Review the config

The credentials are consumed inside src/utils/config.ts. You can bump the Storefront API version there whenever you need newer fields.

// src/utils/config.ts
// Credentials are read here from your .env file.
// Bump the Storefront API version whenever you need newer fields.
export const SHOPIFY_API_VERSION = "2024-10";

3. Install & run

Install dependencies with your package manager of choice, then start the dev server.

# Install dependencies
npm install        # or: yarn  /  pnpm install

# Start the dev server
npm run dev        # or: yarn dev  /  pnpm dev

Shopify Configuration Guide

Connect a Shopify store and grant the Storefront API the right scopes.

  1. 1

    Create or sign in to a Shopify account

    Use an existing store or create a new one at accounts.shopify.com.

  2. 2

    Add the Headless sales channel

    From your store admin, add the Shopify Headless channel, then click Add Storefront.

  3. 3

    Copy your access tokens

    Copy the public and private access tokens into your .env file.

  4. 4

    Set your Storefront API access scopes

    Check Storefront API access scopes. unauthenticated_read_product_listings and unauthenticated_read_product_inventory are enough to get started, add more scopes if you need additional permissions.

Minimum scopes to get started

unauthenticated_read_product_listings and unauthenticated_read_product_inventory cover product browsing and stock. Add more scopes only as your storefront needs them.

What's Included

A lightning-fast frontend that rivals Shopify's own themes.

This branch ships a generic product listing and product detail page setup that adapts based on the collections and products defined in your Shopify backend. The Storefront API query is pre-configured to fetch the extra product information you need, transformed into an easy-to-follow format before the site renders.

Generic, adaptive pages

A product listing and product detail setup that adapts to whatever collections and products are defined in the Shopify backend.

Preset Storefront query

A ready-made GraphQL Storefront API query fetches the most commonly required product fields out of the box.

Build-time transform

Data is reshaped at build time into an easy-to-follow format to streamline injection, while keeping the raw GraphQL data available.

The preset Storefront query

A single GraphQL query pulls the most commonly required product fields. Extend it with any fields your store needs from the Storefront API reference.

query Products {
  products(first: 50) {
    edges {
      node {
        id
        title
        handle
        description
        priceRange {
          minVariantPrice {
            amount
            currencyCode
          }
        }
        featuredImage {
          url
          altText
        }
        variants(first: 1) {
          edges {
            node { id }
          }
        }
      }
    }
  }
}

Cart & Checkout

Wiring up cart and checkout takes two lines.

Setting up button functionality is as simple as defining the variant ID on the page and specifying where you want the button to render. On click, the component creates a cart with the Storefront Cart API and redirects the customer to the checkoutUrl it returns, landing them on Shopify's hosted checkout.

---
// src/pages/products/[handle].astro
import BuyButton from "../../components/BuyButton.astro";

// Pass the variant's global ID; drop the button wherever you like.
const variantId = "gid://shopify/ProductVariant/1234567890";
---

<BuyButton variantId={variantId} quantity={1} />

Under the hood, the component runs a cartCreate mutation and follows the returned URL:

// On click, create a cart for the chosen variant…
const res = await storefront(`
  mutation CartCreate($lines: [CartLineInput!]!) {
    cartCreate(input: { lines: $lines }) {
      cart { checkoutUrl }
      userErrors { field message }
    }
  }
`, { lines: [{ merchandiseId: variantId, quantity }] });

// …then hand the buyer off to Shopify's hosted checkout.
window.location.href = res.data.cartCreate.cart.checkoutUrl;

Finding the variant ID

Grab the variant's global ID (gid://shopify/ProductVariant/…) from the variants field in the Storefront API response. The Cart API takes a merchandiseId (a variant), not a product ID.

Pros

  • Fully custom storefront
  • Excellent performance
  • Astro stays static
  • Shopify handles payments

Cons

  • More development work

Project Structure

Where everything lives inside the template.

/
├── public/
├── src/
│   ├── components/
│   │   └── Header.astro
│   ├── layouts/
│   │   └── BaseLayout.astro
│   ├── pages/
│   │   └── index.astro
│   ├── stores/
│   │   └── cart.ts
│   ├── styles/
│   │   └── global.css
│   └── utils/
│       └── shopify.ts
└── package.json
  • Astro looks for .astro or .md files in src/pages/. Each file is exposed as a route based on its name.
  • src/components/ is where Astro/React/Vue/Svelte/Preact components live, there's nothing special about it, it's just convention.
  • Static assets like images go in public/, and src/utils/shopify.ts holds the Storefront API helpers and cart logic.