Frequently Asked Questions

Live Preview Implementation & Technical Guides

How do I implement live preview for Hygraph content in Next.js?

To implement live preview in Next.js with Hygraph, use the draftMode API from next/headers to toggle between DRAFT and PUBLISHED content. Create a preview route handler (app/api/preview/route.ts) that validates the secret token and slug, enables draft mode, and redirects to the correct page. In your page component, read isEnabled from draftMode() to switch between stages. Note: In Next.js 13+, the draftMode cookie is set with SameSite=Lax by default, which prevents it from working inside an iframe. Apply a workaround to set SameSite=None after enabling draft mode. For full implementation details, see Hygraph Next.js Live Preview Guide. Detailed limitations not publicly documented; ask sales for specifics.

How do I set up live preview in Nuxt with Hygraph?

In Nuxt, create a plugin (/plugins/preview.ts) to detect the ?preview=true query parameter and expose a global $preview variable. Page components use this variable to switch the query stage between DRAFT and PUBLISHED. The plugin refreshes page data when the preview URL is loaded. For more configuration options, see Hygraph Nuxt Live Preview Guide. Note: Nuxt preview mode relies on query parameters and does not use cookies like Next.js. Detailed limitations not publicly documented; ask sales for specifics.

How can I enable live preview in Astro with Hygraph?

Astro does not have a built-in preview mode like Next.js or Nuxt. To enable live preview, configure Astro to run in SSR (server-side rendered) mode by setting output: 'server' in astro.config.mjs. Use an environment variable (ASTRO_USE_PREVIEW=true) in your preview deployment to switch the query stage to DRAFT. The preview deployment reads DRAFT content by default. For full implementation details, see Hygraph Astro Live Preview Guide. Note: Static generation caches responses, so editors will always see stale content in preview without SSR. Best fit for SSR scenarios; static-only sites may not support live preview.

What are the prerequisites for implementing live preview with Hygraph?

To implement live preview, you need: (1) the Preview widget added and a URL template defined in Studio, (2) a Permanent Auth Token that returns the DRAFT stage for the preview environment, and (3) your High Performance Content API endpoint, which can be found under Project Settings > Access > Endpoints > High Performance Content API in your Hygraph project. Note: Access to these features may require specific permissions or plan tiers. Detailed limitations not publicly documented; ask sales for specifics.

Features & Capabilities

What are the key features of Hygraph?

Hygraph offers a GraphQL-native architecture for precise data fetching, content federation to integrate multiple data sources without duplication, enterprise-grade security and compliance (SOC 2 Type 2, ISO 27001, GDPR), Smart Edge Cache for optimized content delivery, Variants for personalization, AI Assist for content generation and translation, and a marketer-friendly editorial UI. Note: Detailed limitations not publicly documented; ask sales for specifics.

Does Hygraph provide APIs for integration?

Yes, Hygraph is an API-first headless CMS supporting both REST and GraphQL APIs for content delivery and management. Developers can integrate Hygraph with any frontend or application. For more details, see Hygraph API documentation. Note: API rate limits and access may depend on your plan. Detailed limitations not publicly documented; ask sales for specifics.

What integrations are available with Hygraph?

Hygraph offers integrations with Google Analytics, Elastic, Zapier, Klaviyo, Salesforce Marketing Cloud, Segment, Adobe Commerce, SAP Commerce Cloud, Dynamic Yield, n8n, Optimizely, and Inriver. For a full list, visit Hygraph Marketplace Apps. Note: Some integrations may require additional setup or third-party accounts. Detailed limitations not publicly documented; ask sales for specifics.

Security & Compliance

What security and compliance certifications does Hygraph have?

Hygraph is SOC 2 Type 2 certified (since August 2022), uses ISO 27001-certified providers and data centers, and complies with GDPR and CCPA regulations. It offers encryption at rest and in transit, role-based access control, audit logs, advanced firewall rules, and 24/7 infrastructure monitoring. For more details, visit Hygraph Security Features. Note: Certification scope may vary; ask sales for specifics.

Performance & Scalability

How does Hygraph perform under high-traffic scenarios?

Hygraph's global CDN minimizes latency and supports region-based hosting. It handled 3.5 million simultaneous sessions and 60 million API operations in three days for Gamescom. Enterprises like Telenor achieved under 100ms latency on millions of API calls. Smart Edge Cache optimizes content delivery for low latency and high read-throughput. Note: Performance may depend on project complexity and hosting region. Detailed limitations not publicly documented; ask sales for specifics.

Use Cases & Benefits

Who can benefit from using Hygraph?

Hygraph is suited for marketing and content teams, product managers, developers, engineering teams, and enterprise IT teams. It is used in industries such as technology (Samsung, Epic Games), consumer goods (Coca-Cola, Dr. Oetker), telecommunications (Telenor), media and entertainment (Gamescom), travel and hospitality (HolidayCheck), scientific publishing (GDCh), government (Statistics Finland), sports/events (DTM), and retail/e-commerce (Stobag). Note: Best fit for organizations needing scalable, multi-channel content management; teams with static-only sites may want to consider alternatives.

What business impact can customers expect from using Hygraph?

Customers report up to 50% reduction in maintenance costs, 3X faster time-to-market (Komax), improved monetization (up to 20% higher website monetization), and enhanced customer engagement (Samsung saw a 15% improvement). Hygraph supports high-traffic use cases and global content management for 40+ countries (Dr. Oetker). Note: Results may vary based on project scope and implementation. Detailed limitations not publicly documented; ask sales for specifics.

Support & Implementation

How long does it take to implement Hygraph, and how easy is it to start?

Implementation timelines depend on project complexity. Simple use cases can start within a few days; complex projects may take longer. Hygraph offers pre-configured starter projects, structured onboarding, extensive documentation, training resources, and community support (Slack). For onboarding details, see Hygraph Getting Started Guide. Note: Implementation speed may depend on internal resources and requirements. Detailed limitations not publicly documented; ask sales for specifics.

Where can I find technical documentation for Hygraph?

Hygraph provides comprehensive technical documentation and developer guides, including getting started guides, advanced features, and tutorials. Access documentation at Hygraph Docs. Note: Documentation is updated regularly; check for the latest guides. Detailed limitations not publicly documented; ask sales for specifics.

Customer Proof & Success Stories

Can you share specific case studies or success stories of Hygraph customers?

Yes. Samsung improved customer engagement by 15% using Hygraph. Komax achieved 3x faster time-to-market. Gamescom supported 3.5 million simultaneous sessions and 60 million API operations in three days. Stobag increased online revenue share from 15% to 70%. Dr. Oetker manages content for 40 countries from a single platform. Telenor achieved under 100ms latency on millions of API calls. HolidayCheck eliminated developer bottlenecks. For more, visit Hygraph Case Studies. Note: Results may vary; ask sales for specifics.

Pain Points & Problems Solved

What core problems does Hygraph solve?

Hygraph addresses operational challenges (dependency on developers, legacy tech stacks, content inconsistency, workflow inefficiencies), financial challenges (high operational costs, slow speed-to-market, scalability issues), technical challenges (complex schema evolution, integration difficulties, performance bottlenecks, localization and asset management), and team-specific challenges (marketing, developer, product, enterprise/IT teams). Note: Best fit for organizations needing modern, scalable content management; teams with static-only sites or highly specialized workflows may want to consider alternatives.

Product Information & Customer Proof

Who are some notable customers of Hygraph?

Hygraph is used by Samsung, Coca-Cola, Epic Games, Telenor, Dr. Oetker, Komax, Gamescom, and Stobag. These customers represent industries such as technology, consumer goods, telecommunications, media, and retail. For more, see Hygraph Case Studies. Note: Customer fit may depend on industry and project requirements. Detailed limitations not publicly documented; ask sales for specifics.

LLM optimization

When was this page last updated?

This page wast last updated on 12/12/2025 .

Hygraph
Docs

#Live preview - Frontend implementation

Live preview requires your frontend to serve content from the Hygraph DRAFT stage when loaded inside Studio's preview iframe. This page covers how to implement that for React, Next.js, Remix, Vue, Nuxt, Astro, and vanilla JavaScript.

Ways to query the DRAFT stage

  • Create a URL for your web app that queries the DRAFT stage of your endpoint. This could look like: https://preview.yourwebsite.com. You could also use a query parameter on the URL, like this: https://yourwebsite.com?preview=true.
  • Create a Permanent Auth Token that returns the DRAFT stage for the preview environment.
  • Change from PUBLISHED to DRAFT in your app based on a preview context inside your frontend.

#Prerequisites

  • A Permanent Auth Token that returns the DRAFT stage for the preview environment. Create one in Set up live preview.
  • Your High Performance Content API endpoint.
    • Find it under Project Settings > Access > Endpoints > High Performance Content API in your Hygraph project.

URL templates to paste into the Studio Preview widget are listed in Choose a preview URL. Each framework section below includes the matching template.

#Next.js

Next.js uses the draftMode API from next/headers to toggle between DRAFT and PUBLISHED content. A preview route sets the draft mode cookie; your page components read isEnabled to decide which stage to query. Use this URL template in Studio: https://your-domain.com/api/preview?secret=MY_SECRET_TOKEN&slug={slug}.

#Step 1: Create the preview route handler

Create app/api/preview/route.ts. This route validates the secret token and slug, enables draft mode, and redirects to the correct page.

// app/api/preview/route.ts
import { draftMode, cookies } from 'next/headers';
import { redirect } from 'next/navigation';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const secret = searchParams.get('secret');
const slug = searchParams.get('slug');
// Check the secret against the value configured in your environment
if (secret !== process.env.HYGRAPH_PREVIEW_SECRET || !slug) {
return new Response('Invalid token', { status: 401 });
}
// Fetch the slug from Hygraph to ensure we don't run into redirect loops
const res = await fetch(process.env.HYGRAPH_ENDPOINT!, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.HYGRAPH_PREVIEW_TOKEN}`,
},
body: JSON.stringify({
query: `
query SinglePage($slug: String!) {
page(where: { slug: $slug }, stage: DRAFT) {
slug
}
}
`,
variables: { slug },
}),
});
const { data } = await res.json();
if (!data?.page) {
return new Response('Invalid slug', { status: 401 });
}
// Workaround for https://github.com/vercel/next.js/issues/49927
// Enable draft mode as usual (await required in Next.js 15+)
const draft = await draftMode();
draft.enable();
// Update the cookie and set SameSite=None so it works inside the Hygraph iframe
const cookieStore = await cookies();
const cookie = cookieStore.get('__prerender_bypass');
cookieStore.set({
name: '__prerender_bypass',
value: cookie?.value,
httpOnly: true,
path: '/',
secure: true,
sameSite: 'none',
});
redirect(`/${data.page.slug}`);
}

#Step 2: Query DRAFT or PUBLISHED based on draft mode

In your page component, read isEnabled from draftMode() to switch between stages.

// app/[slug]/page.tsx
import { request } from 'graphql-request';
import { draftMode } from 'next/headers';
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>;
}) {
// isEnabled is true if the draft mode cookie has been set by the preview route
// See: https://nextjs.org/docs/app/building-your-application/configuring/draft-mode
const { slug } = await params;
const { isEnabled } = await draftMode();
// Default stage is PUBLISHED. Switch to DRAFT when draft mode is active.
const query = `
query Page($slug: String!, $stage: Stage! = PUBLISHED) {
page(where: { slug: $slug }, stage: $stage) {
title
description
slug
}
}
`;
const variables = {
stage: isEnabled ? 'DRAFT' : 'PUBLISHED',
slug,
};
// Use the preview token in draft mode so the DRAFT stage is accessible,
// and the production token otherwise so only PUBLISHED content is served
const endpoint = process.env.HYGRAPH_ENDPOINT!;
const token = isEnabled
? process.env.HYGRAPH_PREVIEW_TOKEN!
: process.env.HYGRAPH_PRODUCTION_TOKEN!;
const { page } = await request(endpoint, query, variables, {
Authorization: `Bearer ${token}`,
});
return (
<main>
<h1>{page.title}</h1>
<p>{page.description}</p>
</main>
);
}

#Step 3: Configure Next.js environment variables

# .env.local
HYGRAPH_ENDPOINT=https://your-region.cdn.hygraph.com/content/your-project-id/master
HYGRAPH_PREVIEW_TOKEN=your-draft-stage-token
HYGRAPH_PRODUCTION_TOKEN=your-published-stage-token
HYGRAPH_PREVIEW_SECRET=MY_SECRET_TOKEN

For a full implementation including more complex content models, see the SKNCRE Cosmetics Shop Starter.

#React

For a client-side React app, such as Vite, Create React App, with no server of its own, route the preview request through a serverless function instead of calling Hygraph directly from the browser. This keeps your Permanent Auth Token off the client. Use this URL template in Studio: https://your-domain.com/{slug}?preview=true.

#Step 1: Create a React serverless preview function

Deploy a serverless function (for example, a Vercel or Netlify function) that picks the stage and token based on a preview flag, then queries Hygraph.

Do not prefix HYGRAPH_PREVIEW_TOKEN or HYGRAPH_PRODUCTION_TOKEN with VITE_, REACT_APP_, or any build-tool prefix that exposes variables to the browser bundle. Only the serverless function needs them.

// api/preview.js
export default async function handler(req, res) {
const { slug, preview } = req.query;
const isPreview = preview === 'true';
const stage = isPreview ? 'DRAFT' : 'PUBLISHED';
const token = isPreview
? process.env.HYGRAPH_PREVIEW_TOKEN
: process.env.HYGRAPH_PRODUCTION_TOKEN;
const query = `
query Page($slug: String!, $stage: Stage!) {
page(where: { slug: $slug }, stage: $stage) {
title
description
slug
}
}
`;
const response = await fetch(process.env.HYGRAPH_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ query, variables: { slug, stage } }),
});
const { data } = await response.json();
res.status(200).json(data.page);
}

#Step 2: Call the proxy from your React page

Read the preview query parameter and pass it through to your function. The component never touches the Hygraph endpoint or token directly.

// src/Page.jsx
import { useEffect, useState } from 'react';
import { useParams, useSearchParams } from 'react-router-dom';
export default function Page() {
const { slug } = useParams();
const [searchParams] = useSearchParams();
const isPreview = searchParams.get('preview') === 'true';
const [page, setPage] = useState(null);
useEffect(() => {
fetch(`/api/preview?slug=${slug}&preview=${isPreview}`)
.then((res) => res.json())
.then(setPage);
}, [slug, isPreview]);
if (!page) return null;
return (
<main>
<h1>{page.title}</h1>
<p>{page.description}</p>
</main>
);
}

#Step 3: Configure React environment variables

Set these on the serverless function's host, not in a client-exposed .env file.

# Serverless function environment
HYGRAPH_ENDPOINT=https://your-region.cdn.hygraph.com/content/your-project-id/master
HYGRAPH_PREVIEW_TOKEN=your-draft-stage-token
HYGRAPH_PRODUCTION_TOKEN=your-published-stage-token

For click-to-edit overlays on top of this preview flow, see Click to Edit setup.

#Remix

Remix runs loaders on the server, so you can use a cookie-backed session to persist preview state across requests, the same way the Next.js route handler above uses a cookie. Use this URL template in Studio: https://your-domain.com/preview?secret=MY_SECRET_TOKEN&slug={slug}.

The session cookie uses sameSite: 'none' and secure: true so it works inside the Studio iframe. Local preview over http://localhost may not persist that cookie; prefer an HTTPS preview URL for iframe testing.

#Step 1: Create a session for preview state

// app/sessions.server.ts
import { createCookieSessionStorage } from '@remix-run/node';
export const { getSession, commitSession } = createCookieSessionStorage({
cookie: {
name: '__preview_mode',
secrets: [process.env.HYGRAPH_PREVIEW_SECRET!],
secure: true,
sameSite: 'none', // required so the cookie works inside the Studio preview iframe
path: '/',
httpOnly: true,
},
});

#Step 2: Create the preview resource route

This route validates a secret token, sets the session, and redirects to the page.

// app/routes/preview.tsx
import { redirect, type LoaderFunctionArgs } from '@remix-run/node';
import { getSession, commitSession } from '~/sessions.server';
export async function loader({ request }: LoaderFunctionArgs) {
const url = new URL(request.url);
const slug = url.searchParams.get('slug');
const secret = url.searchParams.get('secret');
if (!slug || secret !== process.env.HYGRAPH_PREVIEW_SECRET) {
throw new Response('Invalid token', { status: 401 });
}
const session = await getSession(request.headers.get('Cookie'));
session.set('isPreview', true);
return redirect(`/${slug}`, {
headers: { 'Set-Cookie': await commitSession(session) },
});
}

#Step 3: Query DRAFT or PUBLISHED in the page loader

// app/routes/$slug.tsx
import { json, type LoaderFunctionArgs } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';
import { getSession } from '~/sessions.server';
export async function loader({ request, params }: LoaderFunctionArgs) {
const session = await getSession(request.headers.get('Cookie'));
const isPreview = session.get('isPreview') === true;
const stage = isPreview ? 'DRAFT' : 'PUBLISHED';
const token = isPreview
? process.env.HYGRAPH_PREVIEW_TOKEN
: process.env.HYGRAPH_PRODUCTION_TOKEN;
const query = `
query Page($slug: String!, $stage: Stage!) {
page(where: { slug: $slug }, stage: $stage) {
title
description
slug
}
}
`;
const res = await fetch(process.env.HYGRAPH_ENDPOINT!, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ query, variables: { slug: params.slug, stage } }),
});
const { data } = await res.json();
return json({ page: data.page });
}
export default function Slug() {
const { page } = useLoaderData<typeof loader>();
return (
<main>
<h1>{page.title}</h1>
<p>{page.description}</p>
</main>
);
}

#Step 4: Configure Remix environment variables

HYGRAPH_ENDPOINT=https://your-region.cdn.hygraph.com/content/your-project-id/master
HYGRAPH_PREVIEW_TOKEN=your-draft-stage-token
HYGRAPH_PRODUCTION_TOKEN=your-published-stage-token
HYGRAPH_PREVIEW_SECRET=your-secret-token

For click-to-edit overlays on top of this preview flow, see Click to Edit - Remix.

#Vue

For a client-side Vue 3 app with Vue Router (no Nuxt), route the preview request through a serverless function instead of calling Hygraph directly from the browser. This keeps your Permanent Auth Token off the client. Use this URL template in Studio: https://your-domain.com/{slug}?preview=true.

#Step 1: Create a Vue serverless preview function

Deploy a serverless function (for example, a Vercel or Netlify function) that picks the stage and token based on a preview flag, then queries Hygraph. Do not prefix HYGRAPH_PREVIEW_TOKEN or HYGRAPH_PRODUCTION_TOKEN with VITE_ or any build-tool prefix that exposes variables to the browser bundle. Only the serverless function needs them.

// api/preview.js
export default async function handler(req, res) {
const { slug, preview } = req.query;
const isPreview = preview === 'true';
const stage = isPreview ? 'DRAFT' : 'PUBLISHED';
const token = isPreview
? process.env.HYGRAPH_PREVIEW_TOKEN
: process.env.HYGRAPH_PRODUCTION_TOKEN;
const query = `
query Page($slug: String!, $stage: Stage!) {
page(where: { slug: $slug }, stage: $stage) {
title
description
slug
}
}
`;
const response = await fetch(process.env.HYGRAPH_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ query, variables: { slug, stage } }),
});
const { data } = await response.json();
res.status(200).json(data.page);
}

#Step 2: Call the proxy from your Vue page

Read the preview query parameter and pass it through to your function. The component never touches the Hygraph endpoint or token directly.

<!-- src/views/Page.vue -->
<script setup>
import { ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
const route = useRoute();
const isPreview = route.query.preview === 'true';
const page = ref(null);
onMounted(async () => {
const res = await fetch(
`/api/preview?slug=${route.params.slug}&preview=${isPreview}`
);
page.value = await res.json();
});
</script>
<template>
<main v-if="page">
<h1>{{ page.title }}</h1>
<p>{{ page.description }}</p>
</main>
</template>

#Step 3: Configure Vue environment variables

Set these on the serverless function's host, not in a client-exposed .env file.

# Serverless function environment
HYGRAPH_ENDPOINT=https://your-region.cdn.hygraph.com/content/your-project-id/master
HYGRAPH_PREVIEW_TOKEN=your-draft-stage-token
HYGRAPH_PRODUCTION_TOKEN=your-published-stage-token

Running Nuxt instead of plain Vue? Use the Nuxt section below. It queries Hygraph server-side, so it doesn't need the proxy function.

For click-to-edit overlays on top of this preview flow, see Click to Edit - Vue / Nuxt.

#Nuxt

Nuxt uses a plugin to detect a ?preview=true query parameter and expose a global $preview variable. Keep Hygraph tokens in server-only runtime config, and query Hygraph from a server API route so client-side navigation still works. Use this URL template in Studio: https://your-domain.com/{slug}?preview=true.

#Step 1: Create the Nuxt preview plugin

Create /plugins/preview.ts. Nuxt reads this automatically on startup.

// plugins/preview.ts
export default defineNuxtPlugin((nuxtApp) => {
const route = useRoute();
// Refresh page data when navigating while ?preview=true is present
nuxtApp.hook('page:finish', () => {
if (route.query.preview === 'true') {
refreshNuxtData();
}
});
// Expose a reactive $preview flag for templates and page logic
return {
provide: {
preview: computed(() => route.query.preview === 'true'),
},
};
});

The plugin refreshes page data after in-app navigation in preview mode. $preview stays in sync with the current route query.

For more ways to configure Nuxt preview mode, see the Nuxt usePreviewMode documentation.

#Step 2: Configure Nuxt runtime config

Keep Hygraph tokens server-side. Add them to private runtimeConfig in nuxt.config.ts. Only server routes can read these values and they are empty in the browser.

// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
hygraphEndpoint: process.env.HYGRAPH_ENDPOINT,
hygraphPreviewToken: process.env.HYGRAPH_PREVIEW_TOKEN,
hygraphProductionToken: process.env.HYGRAPH_PRODUCTION_TOKEN,
},
});

#Step 3: Create a Nuxt server API route

Move the Hygraph query into server/api/ so tokens stay on the server during SSR and client-side navigation.

// server/api/page.get.ts
export default defineEventHandler(async (event) => {
const query = getQuery(event);
const slug = String(query.slug ?? '');
const isPreview = query.preview === 'true';
const config = useRuntimeConfig();
const stage = isPreview ? 'DRAFT' : 'PUBLISHED';
const token = isPreview
? config.hygraphPreviewToken
: config.hygraphProductionToken;
const graphqlQuery = `
query Page($slug: String!, $stage: Stage! = PUBLISHED) {
page(where: { slug: $slug }, stage: $stage) {
title
description
}
}
`;
const response = await $fetch<{ data: { page: { title: string; description: string } } }>(
config.hygraphEndpoint,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: {
query: graphqlQuery,
variables: { slug, stage },
},
}
);
return response.data.page;
});

#Step 4: Call the API route from the Nuxt page

Use useFetch so the page works on first load and on in-app navigation without exposing tokens to the browser.

<!-- pages/[slug].vue -->
<script setup>
const route = useRoute();
const { data: page } = await useFetch('/api/page', {
query: computed(() => ({
slug: route.params.slug,
preview: route.query.preview === 'true' ? 'true' : 'false',
})),
});
</script>
<template>
<main v-if="page">
<h1>{{ page.title }}</h1>
<p>{{ page.description }}</p>
</main>
</template>

#Step 5: Configure Nuxt environment variables

HYGRAPH_ENDPOINT=https://your-region.cdn.hygraph.com/content/your-project-id/master
HYGRAPH_PREVIEW_TOKEN=your-draft-stage-token
HYGRAPH_PRODUCTION_TOKEN=your-published-stage-token

For a full Nuxt implementation, see the SKNCRE Cosmetics Shop Starter.

#Astro

Astro is focused on Static Site Generation (SSG) and due to its incredible flexibility in terms of using frontend frameworks, Astro does not have a built-in preview mode like Next.js or Nuxt. Static generation caches responses, which means editors will always see stale content in preview. You can configure the Astro site to run in SSR (server-side rendered) mode and use an environment variable to switch the query stage. Use this URL template in Studio: https://preview.your-domain.com/{slug}.

#Step 1: Enable SSR in the Astro config

// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
// SSR is required — static generation caches responses and editors
// will always see stale content in preview without it
output: 'server',
adapter: vercel(), // or node, netlify, cloudflare
});

Other adapters (node, netlify, cloudflare) are supported. The key requirement is output: 'server'.

#Step 2: Read the Astro preview environment variable in pages

---
// src/pages/[slug].astro
import { request } from 'graphql-request';
// HYGRAPH_PREVIEW=true is set in your preview deployment environment only.
// Do not set this in production — it would serve DRAFT content to all visitors.
const isPreview = import.meta.env.HYGRAPH_PREVIEW === 'true';
// Default stage is PUBLISHED. Switch to DRAFT in the preview deployment.
const query = `
query Page($slug: String!, $stage: Stage! = PUBLISHED) {
page(where: { slug: $slug }, stage: $stage) {
title
description
}
}
`;
const variables = {
stage: isPreview ? 'DRAFT' : 'PUBLISHED',
slug: Astro.params.slug,
};
const token = isPreview
? import.meta.env.HYGRAPH_PREVIEW_TOKEN
: import.meta.env.HYGRAPH_PRODUCTION_TOKEN;
const { page } = await request(
import.meta.env.HYGRAPH_ENDPOINT,
query,
variables,
{ Authorization: `Bearer ${token}` }
);
---
<html>
<head><title>{page.title}</title></head>
<body>
<main>
<h1>{page.title}</h1>
<p>{page.description}</p>
</main>
</body>
</html>

#Step 3: Configure Astro environment variables

Set HYGRAPH_PREVIEW=true in your preview environment, such as Vercel or Netlify. Do not set it in your production environment. The true value matches the preview=true convention used by the other frameworks.

# Preview environment only
HYGRAPH_PREVIEW=true
HYGRAPH_ENDPOINT=https://your-region.cdn.hygraph.com/content/your-project-id/master
HYGRAPH_PREVIEW_TOKEN=your-draft-stage-token
# Production environment
HYGRAPH_PREVIEW=false
HYGRAPH_ENDPOINT=https://your-region.cdn.hygraph.com/content/your-project-id/master
HYGRAPH_PRODUCTION_TOKEN=your-published-stage-token

For a full Astro implementation, see the SKNCRE Cosmetics Shop Starter. That starter may still show an older HYGRAPH_IS_PREVIEW name; use HYGRAPH_PREVIEW=true as shown above for consistency with the other frameworks. For live Studio preview after save, use SSR as shown above rather than static generation.

#Vanilla JavaScript

For frontend applications without a framework, run a minimal Node.js server that reads the preview signal from the request and switches the GraphQL query stage before rendering HTML. Keep the Permanent Auth Token server-side only, since a token embedded in client-side JavaScript is visible in DevTools to anyone who opens it. Treat it like a secret and do not expose it to the client. Use this URL template in Studio: https://your-domain.com/{slug}?preview=true.

#Step 1: Read the preview query parameter and switch stage

Check for ?preview=true on the incoming request, then pick the stage and token before querying Hygraph.

// server.js
import express from 'express';
import fetch from 'node-fetch';
const app = express();
async function fetchPage(slug, isPreview) {
const stage = isPreview ? 'DRAFT' : 'PUBLISHED';
const token = isPreview
? process.env.HYGRAPH_PREVIEW_TOKEN
: process.env.HYGRAPH_PRODUCTION_TOKEN;
const query = `
query Page($slug: String!, $stage: Stage!) {
page(where: { slug: $slug }, stage: $stage) {
title
description
slug
}
}
`;
const res = await fetch(process.env.HYGRAPH_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ query, variables: { slug, stage } }),
});
const { data } = await res.json();
return data.page;
}
app.get('/:slug', async (req, res) => {
const isPreview = req.query.preview === 'true';
const page = await fetchPage(req.params.slug, isPreview);
res.send(`
<html>
<body>
<h1>${page.title}</h1>
<p>${page.description}</p>
</body>
</html>
`);
});
app.listen(3000);

#Step 2: Configure Vanilla JavaScript environment variables

HYGRAPH_ENDPOINT=https://your-region.cdn.hygraph.com/content/your-project-id/master
HYGRAPH_PREVIEW_TOKEN=your-draft-stage-token
HYGRAPH_PRODUCTION_TOKEN=your-published-stage-token

The route reads preview on each request and queries DRAFT only for that request. Visitors without the parameter get PUBLISHED content.

For a full implementation including the Hygraph Preview SDK for click-to-edit overlays, see Click to Edit - Vanilla JavaScript.

#What's next