Overview

Eleventy (11ty) is a powerful static site generator that can fetch data from GraphQL APIs at build time. This approach combines the performance benefits of static sites with the flexibility of dynamic data sources, making it ideal for e-commerce catalogs, product listings, and content-heavy applications.

Key Benefits

  • โ–ช Build-time Data Fetching: Query GraphQL APIs during the build process, generating static HTML pages with fresh data
  • โ–ช Parallel Processing: Generate multiple pages concurrently for improved build performance
  • โ–ช Type Safety: Leverage GraphQL's type system for predictable data structures
  • โ–ช SEO Optimization: All content is pre-rendered, ensuring excellent search engine visibility

Project Setup

Install the required dependencies for your 11ty project with GraphQL support.

bash
# Create new 11ty project
mkdir my-11ty-site && cd my-11ty-site
npm init -y

# Install dependencies
npm install @11ty/eleventy dotenv node-fetch@2

# Create directory structure
mkdir -p src/_data src/_includes src/css

GraphQL Client Configuration

Create a GraphQL client module to handle API requests to Shopify or other GraphQL endpoints.

src/_data/graphqlClient.js
const fetch = require('node-fetch');
require('dotenv').config();

class GraphQLClient {
  constructor(endpoint, headers = {}) {
    this.endpoint = endpoint;
    this.headers = {
      'Content-Type': 'application/json',
      ...headers
    };
  }

  async query(query, variables = {}) {
    try {
      const response = await fetch(this.endpoint, {
        method: 'POST',
        headers: this.headers,
        body: JSON.stringify({ query, variables })
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const result = await response.json();
      
      if (result.errors) {
        console.error('GraphQL errors:', result.errors);
        throw new Error(result.errors[0].message);
      }

      return result.data;
    } catch (error) {
      console.error('GraphQL query failed:', error);
      throw error;
    }
  }
}

module.exports = GraphQLClient;

11ty Data Files

Create data files that fetch from GraphQL APIs at build time. These files export async functions that return data to your templates.

Fetch Products from Shopify

src/_data/products.js
const GraphQLClient = require('./graphqlClient');

module.exports = async function() {
  const client = new GraphQLClient(
    process.env.SHOPIFY_STOREFRONT_URL,
    {
      'X-Shopify-Storefront-Access-Token': process.env.SHOPIFY_ACCESS_TOKEN
    }
  );

  const query = `
    query GetProducts($first: Int!) {
      products(first: $first) {
        edges {
          node {
            id
            title
            handle
            description
            priceRange {
              minVariantPrice {
                amount
                currencyCode
              }
            }
            images(first: 1) {
              edges {
                node {
                  url
                  altText
                }
              }
            }
          }
        }
      }
    }
  `;

  try {
    const data = await client.query(query, { first: 100 });
    return data.products.edges.map(edge => edge.node);
  } catch (error) {
    console.error('Failed to fetch products:', error);
    return [];
  }
};

Parallel Page Generation

Use 11ty's pagination feature to generate individual pages for each product or collection item in parallel.

src/products.njk
---
pagination:
  data: products
  size: 1
  alias: product
permalink: "/products//"
---

<h1></h1>
<div class="product-detail">
  <img src="" alt="">
  <p></p>
  <p class="price">
     
    
  </p>
</div>

Build Process

How It Works

  1. 01. 11ty runs all data files in the _data directory
  2. 02. GraphQL queries are executed, fetching data from APIs
  3. 03. Data is cached and made available to all templates
  4. 04. Templates are processed in parallel, generating static HTML files
  5. 05. Static site is output to the _site directory

Best Practices

Caching Strategy

Implement caching for GraphQL responses to reduce API calls during development. Use environment variables to control cache behavior in production vs. development.

Error Handling

Always implement robust error handling in data files. Return fallback data or empty arrays to prevent build failures when APIs are unavailable.

Incremental Builds

For large catalogs, consider implementing incremental builds that only regenerate pages for changed products. This significantly reduces build times.

Rate Limiting

Respect API rate limits by implementing request throttling and batching. Use GraphQL's ability to fetch multiple resources in a single query.