Use Hygraph with Visual Editor
Visual Editor has first-class support for two-way syncing content between Hygraph and Visual Editor.
Example configuration
Section titled “Example configuration”Visual Editor has a tight integration to support Hygraph as one or more of your content sources. This guide covers how to configure Visual Editor to enable two-way data synchronization with your Hygraph projects.
Here is an example configuration that uses Next.js as the site framework, uses a Page model to represent pages, and creates a custom sitemap to override the default sitemap behavior:
// stackbit.config.tsimport { defineStackbitConfig, SiteMapEntry, DocumentStringLikeFieldNonLocalized} from '@stackbit/types';import { HygraphContentSource } from "@stackbit/cms-hygraph";
// Use defineStackbitConfig to allow Typescript checksexport default defineStackbitConfig({ stackbitVersion: "~0.6.0", ssgName: "nextjs", nodeVersion: "20",
// useESM: true is required for HygraphContentSource // as it has ESM only dependencies. useESM: true,
contentSources: [ new HygraphContentSource({ // Hygraph project ID. // Can be found in project settings screen in Hygraph Studio. projectId: process.env.HYGRAPH_PROJECT_ID!,
// Hygraph project region. // Can be found in project settings screen in Hygraph Studio. // Example: US-WEST-2 region: process.env.HYGRAPH_REGION!,
// Hygraph project environment. Default: master environment: process.env.HYGRAPH_ENVIRONMENT!,
// Hygraph content API endpoint URL. // Must match the configured region. // Example: // https://{REGION}.cdn.hygraph.com/content/{HASH}/{ENVIRONMENT} contentApi: process.env.HYGRAPH_ENDPOINT!,
// Hygraph management API endpoint URL. // Must match the configured region. // Example: // https://management-{REGION}.hygraph.com/graphql managementApi: process.env.HYGRAPH_MANAGEMENT_API!,
// The management token. managementToken: process.env.HYGRAPH_MANAGEMENT_TOKEN! }) ],
// This marks the Hygraph's "Page" model as a "page" models in the Visual-Editor modelExtensions: [ { name: 'Page', type: 'page' } ],
// The sitemap maps between the "Page" entries and their url paths // allowing easy navigation between site pages in the Visual-Editor. sitemap: ({ documents }): SiteMapEntry[] => { // The "documents" include all the entries from Hygraph. return documents.reduce( (sitemap: SiteMapEntry[], document): SiteMapEntry[] => { // Filter documents that match "Page" model name // This is the model ID in Hygraph. if (!['Page'].includes(document.modelName)) { return sitemap; } const slugField = document.fields.slug as DocumentStringLikeFieldNonLocalized; if (!slugField || !slugField.value) { return sitemap; } sitemap.push({ urlPath: `/${slugField.value.replace(/^\/|\/$/g, '')}`, document: document }); return sitemap; } ); }});Notice the following:
HygraphContentSourceis being loaded from the@stackbit/cms-hygraphwhich must be installed first as a dev-dependency. This package is not needed in your production site.- Hygraph is being configured using local environment variables. Visual Editor will automatically load a
.envfile in the root of your project. - The example assumes a model with an ID of
Pagethat is being used to store page data in Hygraph. That content type has a field with nameslugthat determines the URL path at which the page is made available.
Prerequisites
Section titled “Prerequisites”To be able to work with Hygraph, you must first have the following:
-
A Hygraph project with content.
-
The proper API keys that can access your content. For more info check out the options section below.
-
Installed
@stackbit/cms-hygraphpackage as a development dependency. (We also recommend@stackbit/typesto help with configuration.)Terminal window npm install -D @stackbit/types @stackbit/cms-hygraph
// stackbit.config.tsimport { defineStackbitConfig } from '@stackbit/types';import { HygraphContentSource } from "@stackbit/cms-hygraph";
export default defineStackbitConfig({ stackbitVersion: "~0.6.0", // ... other config options useESM: true, contentSources: [ new HygraphContentSource({ projectId: "...", region: "...", environment: "...", contentApi: "...", managementApi: "...", managementToken: "...", }) ]});Options
Section titled “Options”The following are all required options, unless noted:
-
projectId: The Hygraph project ID, found in the project settings screen in Hygraph Studio. -
region: The Hygraph project region, found in the project settings screen in Hygraph Studio. -
environment: The Hygraph project environment. (Default: master) -
contentApi: The Hygraph content API endpoint URL. Must match the configured region.Example:
https://{REGION}.cdn.hygraph.com/content/{HASH}/{ENVIRONMENT} -
managementApi: The Hygraph Management API endpoint URL. Must match the configured region.Example:
https://management-{REGION}.hygraph.com/graphql -
managementToken: The management token. The management token must have the following configuration:-
Content API section:
- Default stage for content delivery: Draft
- Content permissions enabled for all models, all stages, and all locales

-
Management API - The management API must include 21 permissions:
- Read existing environments
- Read existing models
- Read existing components
- Read existing fields
- Read existing enumerations
- Read existing entries
- Read remote sources
- Read stages
- Read locales
- Can see schema view
- Update existing non-published entries
- Update published entries
- Publish non-published entries
- Create new entries
- Delete existing entries
- Create new webhooks
- Read existing webhooks
- Update existing webhooks
- Delete an existing webhook
- Can see Role & Permissions Settings
- Can read content permissions
- (Optional for debugging) Can use the playground

-
-
componentQueryNestingLevel(Optional): Defines the nesting level in GraphQL queries for cyclic components. This helps reduce query complexity for large content schemas. (Default: 3) -
entriesFilter: Filters entries fetched byHygraphContentSource.The
entriesFilteris applied as the “where” argument in the GraphQL query used to fetch entries. Since each Hygraph model has different “where” properties,entriesFilteris an object mapping a model’s API ID to its filter value.
The entriesFilter applies only to the “where” clause, so it cannot be used to filter by locales or stages.
Example:
The following filter retrieves:
- Page entries where
enumFieldis “foo” andtitlecontains “homepage.” - Post entries where
author.nameis “john.”
entriesFilter: { Page: '{ enumField: foo, title_contains: "homepage" }', Post: '{ author: { name: "john" } }'}For more info visit Hygraph Filtering Documentation
-
debugGraphQLQueries(Optional): Logs GraphQL queries, including complexity details for entry queries.To enable “debug” level logs, run
stackbit devwith--log-level=debugflag:Terminal window stackbit dev --log-level=debug -
splitEntryRequestsPerModel(Optional): Splits GraphQL entry requests by model to reduce query complexity when the content schema is too complex for querying multiple models in a single request.When this flag is set to
false(the default), a single GraphQL query includes all models, and as pages of entries are fetched, the number of models will decrease:query {Pages(stage: DRAFT, first: 100, skip: 0) {...PageFragment}Posts(stage: DRAFT, first: 100, skip: 0) {...PostFragment}Authors(stage: DRAFT, first: 100, skip: 0) {...AuthorFragment}}When this flag is set to
true, each GraphQL query will contain a single model, and entries will be fetched serially, one model at a time:Request 1:
query {Pages(stage: DRAFT, first: 100, skip: 0) {...PageFragment}}Request 2:
query {Posts(stage: DRAFT, first: 100, skip: 0) {...PageFragment}}
Store sensitive values
Section titled “Store sensitive values”Sensitive values can be stored in a .env file, which will then be available when Visual Editor configuration file is loaded.
# .envHYGRAPH_PROJECT_ID=HYGRAPH_REGION=HYGRAPH_ENVIRONMENT=masterHYGRAPH_ENDPOINT=HYGRAPH_MANAGEMENT_API=HYGRAPH_MANAGEMENT_TOKEN=Local development
Section titled “Local development”Hygraph Content Source uses webhooks to synchronize content. For local development with Visual Editor, the easiest method is to use an ngrok tunnel and pass the tunnel URL when running stackbit dev.
Install ngrok
Section titled “Install ngrok”If you don’t have ngrok installed, please follow the ngrok quick start guide to install it.
Start ngrok agent
Section titled “Start ngrok agent”With your development server running in one terminal window, open a second terminal and start the ngrok agent on port 8090:
ngrok http 8090Once ngrok starts, it will print a publicly-accessible URL in the form of https://xyz.ngrok.app or https://xyz.ngrok.io, which can be used to access localhost:8090. Keep this terminal window open with ngrok running.
Example output:
Session Status online...Forwarding http://xyz.ngrok.app -> http://localhost:8090Forwarding https://xyz.ngrok.app -> http://localhost:8090Start stackbit dev
Section titled “Start stackbit dev”Open a third terminal window and install the Visual Editor CLI if you haven’t already:
npm i -g @stackbit/cliRun stackbit dev with the --csi-webhook-url argument set to your ngrok public URL, ending with the /_stackbit/onWebhook path:
stackbit dev --csi-webhook-url=https://<REPLACE>.ngrok.app/_stackbit/onWebhookOnce stackbit dev starts, open the http://localhost:8090/_stackbit link printed in the terminal to open the Visual Editor.
Content type inference
Section titled “Content type inference”The Hygraph Content Source infers all Hygraph models to be Visual Editor data models, unless otherwise specified.
Therefore, models that represent website pages must be extended to have type: 'page' using the modelExtensions property.
Use multiple projects or environments
Section titled “Use multiple projects or environments”The contentSources property is an array of content sources that are all pulled together with Visual Editor. You can add another content source by instantiating another class as another item in the array, while using separate environment variables for the options.
// stackbit.config.tsimport { HygraphContentSource } from "@stackbit/cms-hygraph";
export default { contentSources: [ new HygraphContentSource({ projectId: process.env.HYGRAPH_PROJECT_ID_01!, region: process.env.HYGRAPH_REGION_01!, environment: process.env.HYGRAPH_ENVIRONMENT_01!, contentApi: process.env.HYGRAPH_ENDPOINT_01!, managementApi: process.env.HYGRAPH_MANAGEMENT_API_01!, managementToken: process.env.HYGRAPH_MANAGEMENT_TOKEN_01! }), new HygraphContentSource({ projectId: process.env.HYGRAPH_PROJECT_ID_02!, region: process.env.HYGRAPH_REGION_02!, environment: process.env.HYGRAPH_ENVIRONMENT_02!, contentApi: process.env.HYGRAPH_ENDPOINT_02!, managementApi: process.env.HYGRAPH_MANAGEMENT_API_02!, managementToken: process.env.HYGRAPH_MANAGEMENT_TOKEN_02! }) ] // ...};Did you find this doc useful?
Your feedback helps us improve our docs.