Visual Editor /Content sources /

Use Git CMS with Visual Editor

Visual Editor supports using files to store content (Git CMS). This guide covers what you need to know about configuring Visual Editor for a two-way data sync between Visual Editor and file-based content.

# Example configuration

Here is a simplified example that defines the following:

  • A page model with a required title field.
  • Pages are stored in the content directory as JSON files.
  • Assets are stored in the public/images directory.
// stackbit.config.ts
import { defineStackbitConfig } from "@stackbit/types";
import { GitContentSource } from "@stackbit/cms-git";

export default defineStackbitConfig({
  stackbitVersion: "~0.6.0",
  contentSources: [
    new GitContentSource({
      rootPath: __dirname,
      contentDirs: ["content"],
      models: [
        {
          name: "Page",
          type: "page",
          urlPath: "/{slug}",
          filePath: "content/pages/{slug}.json",
          fields: [{ name: "title", type: "string", required: true }]
        }
      ],
      assetsConfig: {
        referenceType: "static",
        staticDir: "public",
        uploadDir: "images",
        publicPath: "/"
      }
    })
  ]
});

# Prerequisites

The only thing required to work with Git CMS is to install the development dependencies.

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

# Options

Git CMS is unique in that all content modeling must be done within content source configuration. The options to define the schema are documented below.

# assetsConfig

Defines where local site assets are stored in your project and how other content references these assets.

  • Required? No.
  • Options:
    • referenceType: (required) specifies how content files reference asset files. Options: static, relative.
    • uploadDir: (required) path inside assetsDir in which to store uploaded assets, relative to either staticDir (for static assets) or assetsDir (for relative assets).
    • Additional properties for static assets:
      • staticDir: directory path relative to the project root in which the site framework copies files to the directory that get deployed.
      • publicPath: URL from which the static files are publicly available.
    • Additional properties for relative assets:
      • assetsDir: path to the directory containing all the assets to your project, relative to the project root.

# Static assets

Here's an example configuration for this object using static assets from a public/images directory.

// stackbit.config.ts
export default defineStackbitConfig({
  contentSources: [
    new GitContentSource({
      assetsConfig: {
        referenceType: "static",
        staticDir: "public",
        uploadDir: "images",
        publicPath: "/"
      }
      // ...
    })
  ]
});
  • All assets must be placed under the directory set in staticDir, either directly or in subdirectories. They cannot be colocated with page content or source code. The value is always relative to the root of the project.
  • When the build is run, assets are served from the URL path set by publicPath. The full URLs are constructed as {publicPath}/{file path under staticDir}.
  • With the example configuration above, an image file named public/images/image.png in your repository will be served from the URL /images/image.png.
  • Images uploaded by editors would be saved in {staticDir}/{uploadDir}, or in the above case: {root}/public/images.

# Relative assets

When asset files are colocated with content, use relative references.

// stackbit.config.ts
export default defineStackbitConfig({
  contentSources: [
    new GitContentSource({
      assetsConfig: {
        referenceType: "relative",
        assetsDir: "src",
        uploadDir: "images"
      }
      // ...
    })
  ]
});
  • assetsDir can include files of different types. However, only files with specific extensions will be treated as assets (png, jpg, jpeg, gif, svg, ico, etc.).
  • Images uploaded by editors would be saved in {assetsDir}/{uploadDir}, or in the above case: {root}/src/images.

# contentDirs

Defines directories in which to look for content. Each document is mapped to a model using the value of the type property.

  • Required? Yes.
  • Allowed values: a string representing a directory path, relative to the root of the project.
// stackbit.config.ts
export default defineStackbitConfig({
  contentSources: [
    new GitContentSource({
      contentDirs: ["content"]
      // ...
    })
  ]
});

# models

This is your schema definition for all file-based content.

// stackbit.config.ts
export default defineStackbitConfig({
  contentSources: [
    new GitContentSource({
      models: [
        {
          name: "Page",
          type: "page",
          urlPath: "/{slug}",
          filePath: "content/pages/{slug}.json",
          fields: [{ name: "title", type: "string", required: true }]
        }
        // ...
      ]
      // ...
    })
  ]
});

# repoBranch

The Git branch used to read and write content.

This property is not used in local development, as content changes are written to disk and not committed or pushed to the remote repository.

  • Required? Yes.
  • Allowed values: a string representing the Git branch used for content changes. This branch must be available in the remote repository.
// stackbit.config.ts
export default defineStackbitConfig({
  contentSources: [
    new GitContentSource({
      repoBranch: "preview"
      // ...
    })
  ]
});

# repoUrl

URL to the remote Git repository used to read and write content.

This property is not used in local development, as content changes are written to disk and not committed or pushed to the remote repository.

  • Required? Yes.
  • Allowed values: a string representing the URL to the Git repository used for storing content.
// stackbit.config.ts
export default defineStackbitConfig({
  contentSources: [
    new GitContentSource({
      repoUrl: "https://github.com/{user}/{repo}"
      // ...
    })
  ]
});

# rootPath

Absolute path to the root of your project. This is used to build relative paths for other configuration properties.

  • Required? Yes.
  • Allowed values: a string representing the absolute path to the project root.
// stackbit.config.ts
export default defineStackbitConfig({
  contentSources: [
    new GitContentSource({
      rootPath: __dirname
      // ...
    })
  ]
});

# Annotations

When specifying object ID for annotations, most content sources will have an obvious ID value.

For Git CMS, this value is the path to the source file, relative to the root of the project, and including the file extension. For example, say a home page is located at content/pages/index.json.

.
└── content/
    └── pages/
        └── index.json

The ID value would be content/pages/index.json.

<div data-sb-object-id="content/pages/index.json">...</div>