/ astro-integrations / How to Use Hygraph with Astro: Complete Guide
astro-integrations 9 min read

How to Use Hygraph with Astro: Complete Guide

Step-by-step guide to integrating Hygraph with your Astro website.

How to Use Hygraph with Astro: Complete Guide

Hygraph (formerly GraphCMS) is a GraphQL-native headless CMS that stands out for its content federation feature, which lets you combine data from multiple sources into a single GraphQL API. If you are already comfortable with GraphQL or you need to pull content from different backends into one unified schema, Hygraph is worth a serious look. With Astro, you can query Hygraph at build time and generate blazing-fast static pages from your CMS content.

Since Hygraph uses GraphQL as its primary interface, the integration relies on standard GraphQL queries rather than a proprietary SDK. This keeps things flexible and portable. Both the official Astro CMS guide and Hygraph's own documentation cover this pairing, so you are working with a well supported path.

Prerequisites

  • Node.js 22.12.0 or later. Astro 6 dropped Node 18 and Node 20, so anything older will not run.
  • An Astro project. Create one with npm create astro@latest. This guide was checked against Astro 6.4.2.
  • A Hygraph account with a project created (free tier available, paid plans start at $199/mo)
  • Basic familiarity with GraphQL queries

A Note on Rendering Mode

Astro renders everything as static HTML at build time by default, which is exactly what you want for a content site backed by a CMS. There is no output setting to flip on. The old output: 'hybrid' value was removed back in Astro 5, and static has been the default ever since.

The integration in this guide queries Hygraph at build time and emits static pages, so no adapter is required. If you later want a single route to fetch fresh Hygraph content on each request (for example a live preview page), you add an adapter and put export const prerender = false at the top of that one page. Everything else stays static. You only reach for an adapter when you actually need on-demand rendering.

Installation

Hygraph recommends graphql-request because it is lightweight, has good TypeScript support, and works in both Node.js and the browser. You do not need Apollo or anything heavy for build-time fetching:

npm add graphql-request graphql

This installs graphql-request 7.4.0 and its graphql peer dependency (16.14.0 at the time of writing).

Configuration

Create a reusable Hygraph client:

// src/lib/hygraph.ts
import { GraphQLClient } from "graphql-request";

const hygraph = new GraphQLClient(import.meta.env.ASTRO_HYGRAPH_ENDPOINT, {
  headers: {
    Authorization: `Bearer ${import.meta.env.HYGRAPH_TOKEN}`,
  },
});

export default hygraph;

Add your Hygraph credentials to .env:

ASTRO_HYGRAPH_ENDPOINT=https://<region>.cdn.hygraph.com/content/<project-id>/master
HYGRAPH_TOKEN=your-permanent-auth-token

Hygraph's docs use the ASTRO_HYGRAPH_ENDPOINT name, and the endpoint follows the High Performance Content API shape shown above (your region and project id are baked into the URL). Find both values in your Hygraph project under Settings > API Access. Create a Permanent Auth Token with read access for your content stage.

Two things to keep in mind on Astro 6. First, only variables prefixed with PUBLIC_ are exposed to client-side code; the auth token here has no prefix, so it stays server-only and never ships to the browser, which is what you want. Second, Astro 6 always inlines import.meta.env values as-is and no longer coerces types, so a value like "true" stays a string. That does not affect this string endpoint, but it is worth knowing if you add boolean or numeric env vars elsewhere.

If your blog model is set to allow unauthenticated reads on the published stage, you can drop the Authorization header entirely. You must explicitly grant Content API permissions for that stage in your Hygraph project settings, otherwise queries return empty data with no error.

Set up your content model in Hygraph's dashboard. For a blog, create a "Post" model with fields: Title (Single line text), Slug (Single line text), Excerpt (Multi line text), Content (Rich text), Cover Image (Asset picker), and Published At (Date and time).

Basic Usage

Query posts from Hygraph and render them in Astro:

---
// src/pages/blog/index.astro
import hygraph from "../../lib/hygraph";
import { gql } from "graphql-request";
import BaseLayout from "../../layouts/BaseLayout.astro";

const { posts } = await hygraph.request(gql`
  query Posts {
    posts(orderBy: publishedAt_DESC) {
      id
      title
      slug
      excerpt
      publishedAt
      coverImage {
        url
      }
    }
  }
`);
---

<BaseLayout title="Blog">
  <h1>Blog</h1>
  {posts.map((post) => (
    <article>
      <a href={`/blog/${post.slug}`}>
        {post.coverImage && (
          <img src={post.coverImage.url} alt={post.title} loading="lazy" />
        )}
        <h2>{post.title}</h2>
        <p>{post.excerpt}</p>
        <time>{new Date(post.publishedAt).toLocaleDateString()}</time>
      </a>
    </article>
  ))}
</BaseLayout>

For individual post pages with dynamic routes:

---
// src/pages/blog/[slug].astro
import hygraph from "../../lib/hygraph";
import { gql } from "graphql-request";
import BaseLayout from "../../layouts/BaseLayout.astro";

export async function getStaticPaths() {
  const { posts } = await hygraph.request(gql`
    query PostSlugs {
      posts {
        slug
      }
    }
  `);

  return posts.map((post) => ({
    params: { slug: post.slug },
  }));
}

const { slug } = Astro.params;

const { post } = await hygraph.request(gql`
  query Post($slug: String!) {
    post(where: { slug: $slug }) {
      title
      content {
        html
      }
      coverImage {
        url
      }
      publishedAt
    }
  }
`, { slug });
---

<BaseLayout title={post.title}>
  <article>
    <h1>{post.title}</h1>
    <time>{new Date(post.publishedAt).toLocaleDateString()}</time>
    {post.coverImage && (
      <img src={post.coverImage.url} alt={post.title} />
    )}
    <div set:html={post.content.html} />
  </article>
</BaseLayout>

Production Tips

  1. Use Hygraph's image transformations, or Astro's image module. Append transformation parameters to asset URLs for automatic resizing and format conversion. For example, add ?width=800&height=400&fit=crop to any asset URL for on-the-fly optimization without a separate image service. If you would rather feed Hygraph assets through Astro's own <Image /> component, add the asset host to image.remotePatterns in astro.config.mjs:
// astro.config.mjs
import { defineConfig } from "astro/config";

export default defineConfig({
  image: {
    remotePatterns: [{ protocol: "https", hostname: "**.graphassets.com" }],
  },
});

Note that Astro 6 changed image defaults: cropping is now applied without an explicit fit option, and images are never upscaled by the default service.

  1. Leverage content stages. Hygraph supports Draft and Published stages. Query the Draft stage for preview environments and Published for production. Use different auth tokens for each stage to keep things secure.

  2. Set up webhooks for rebuilds. Under project settings, configure webhooks to trigger a rebuild on your hosting platform whenever content is published. This keeps your static site in sync without manual deploys.

  • Use content federation wisely. Hygraph's killer feature is federating external REST or GraphQL APIs into your schema. If you need product data from Shopify alongside blog content, you can query both through a single Hygraph endpoint.

  • Type your GraphQL responses. Generate TypeScript types from your Hygraph schema using GraphQL Code Generator (@graphql-codegen/cli, currently 7.1.0). This gives you autocomplete and compile-time safety for all your queries.

  • Alternatives to Consider

    • Contentful if you want a REST API option alongside GraphQL and a larger ecosystem of integrations.
    • Sanity if you need real-time collaboration features and a more flexible schema builder with GROQ queries.
    • DatoCMS if you prefer a similar GraphQL-first CMS with built-in image optimization and a simpler pricing model.

    Common Errors and Fixes

    Queries return empty data and no error. This almost always means the content stage is not readable by your request. Hygraph requires you to explicitly initialize Content API permissions for unauthenticated requests, or to query with a Permanent Auth Token that has read access to the stage you are targeting. Check Settings > API Access and confirm the published stage is allowed for the role your request uses.

    Images do not optimize or throw a remote-image error. Astro will refuse to process a remote image whose host is not allowlisted. Add **.graphassets.com to image.remotePatterns in astro.config.mjs as shown above. If you only ever use raw asset URLs with Hygraph transformation query parameters, you can skip Astro's image module entirely.

    New posts do not show up after publishing in Hygraph. Astro builds every route at build time, so getStaticPaths is evaluated once during the build and not on each request. Fresh content only appears after a rebuild. Wire a Hygraph webhook to your host's deploy hook so publishing triggers a new build, or move a single preview route to on-demand rendering with export const prerender = false plus an adapter.

    import.meta.env.ASTRO_HYGRAPH_ENDPOINT is undefined. Confirm the variable name matches exactly, including the ASTRO_ prefix, and that the .env file sits at the project root. Restart the dev server after editing .env since Astro reads it at startup. Remember that on Astro 6 only PUBLIC_-prefixed variables are available in client-side code; build-time frontmatter access works for any name.

    Build fails right after upgrading. Astro 6 requires Node 22.12.0 or later. If your CI or local runtime is on Node 18 or 20, the build will not run. Bump your runtime first.

    Official Docs and Examples

    Wrapping Up

    Hygraph and Astro work well together for content-driven sites, especially when you need GraphQL flexibility or content federation. The free tier covers small projects, and the GraphQL API means you query exactly the data you need with no over-fetching. If your project involves pulling content from multiple sources or you prefer GraphQL over REST, Hygraph is a solid foundation for your Astro site.

    Sources

    All versions and facts below were checked on 2026-05-29.