Visual editing /Visual Editor /Content sources /

Use Hygraph with Visual Editor

Visual Editor has first-class support for two-way syncing content between Hygraph and Visual Editor.

# 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.ts
import { 
  defineStackbitConfig,
  SiteMapEntry,
  DocumentStringLikeFieldNonLocalized
} from '@stackbit/types';
import { HygraphContentSource } from "@stackbit/cms-hygraph";

// Use defineStackbitConfig to allow Typescript checks
export 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:

  • HygraphContentSource is being loaded from the @stackbit/cms-hygraph which 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 .env file in the root of your project.
  • The example assumes a model with an ID of Page that is being used to store page data in Hygraph. That content type has a field with name slug that determines the URL path at which the page is made available.

# 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-hygraph package as a development dependency. (We also recommend @stackbit/types to help with configuration.)

    npm install -D @stackbit/types @stackbit/cms-hygraph
    

# Usage

// stackbit.config.ts
import { 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

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 token content permissions.

    • 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

      Management token management permissions.

  • 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 by HygraphContentSource.

    The entriesFilter is applied as the “where” argument in the GraphQL query used to fetch entries. Since each Hygraph model has different “where” properties, entriesFilter is an object mapping a model’s API ID to its filter value.

    Warning

    Ensure that filtered-out entries are not referenced by entries that pass the filter. Otherwise, the Visual Editor will display “Field is missing or inaccessible” errors where a reference field points to a filtered-out entry. If your content architecture does not allow for this, consider using the permissionsForDocument method in stackbit.config.ts.

    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 enumField is “foo” and title contains “homepage.”
    • Post entries where author.name is “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 dev with --log-level=debug flag:

    stackbit dev --log-level=debug
    

    Learn more about query complexity.

  • 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

Sensitive values can be stored in a .env file, which will then be available when Visual Editor configuration file is loaded.

# .env
HYGRAPH_PROJECT_ID=
HYGRAPH_REGION=
HYGRAPH_ENVIRONMENT=master
HYGRAPH_ENDPOINT=
HYGRAPH_MANAGEMENT_API=
HYGRAPH_MANAGEMENT_TOKEN=

# 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

If you don’t have ngrok installed, please follow the ngrok quick start guide to install it.

# 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 8090

Once 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:8090
Forwarding        https://xyz.ngrok.app -> http://localhost:8090

# Start stackbit dev

Open a third terminal window and install the Visual Editor CLI if you haven’t already:

npm i -g @stackbit/cli

Run 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/onWebhook

Once stackbit dev starts, open the http://localhost:8090/_stackbit link printed in the terminal to open the Visual Editor.

# 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

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.ts
import { 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!
    })
  ]
  // ...
};