Contentstack Bridge

CI Status Quality Gate Status Go Report Card

The Contentstack Bridge adds a layer between your application and Contentstack, to provide some much-needed conveniences.

Getting Started

Information on building and configuring the Contentstack Bridge

CLI

Information on the subcommands and CLI flags in the Contentstack Bridge CLI

API Server

Information on the built-in API server and endpoints

Subsections of Contentstack Bridge

Getting Started

It’s pretty easy to set up the Contentstack Bridge. Let’s walk through the steps that are needed to set it up.

Installation steps

Getting the program binary

There’s two ways to get the application binary. One way is to build it locally. Instructions on how to do this can be found on Building.

Alternatively, pre-built binaries can be found on the releases page on GitHub. Once you have a csb binary, you can verify that it works by running ./csb --help. If this command outputs a help menu, you can move on to the next step.

Configuring the .env file

For the application to be able to communicate with Contentstack and access its own database, a .env file is required. An example .env file can be found in the GitHub repository. Once the .env file has been configured, you can validate it by running ./csb check:health.

For more information about the possible configuration options, please see the Configuration options page.

Populating the database

Now that the application is configured, we can create the necessary database tables. This can very easily be done by running ./csb migrate:db.

Once this is done, all of the database tables will be set up and ready to go.

Synchronising the Contentstack data

Now that we have a database and tables, we need to populate the data. We can do this by running ./csb remote:sync. This will synchronise the remote data into the database. This is needed for the built-in API to work, among other things.

This command should also be ran periodically, to keep the data up-to-date. When run again, the sync will continue where it left off, so only the initial synchronisation will be a heavy operation.

Subpages

Building

Building instructions for the application

Configuration

Configuring the Contentstack Bridge

Configuration options

An overview of all possible configuration options

Subsections of Getting Started

Building

To build the application, simply run go build.

This will create a new file, called csb. Running it now will throw an error, since there is no configuration yet.

Instructions on how to configure the application can be found on the Configuration page.

Configuration

Setting up the .env file

Configuration is done with a .env file. To start, copy the .env.example:

cp .env.example .env

An example .env file can also be found in the GitHub repository.

Contentstack credentials

The Contentstack credentials can be obtained from the Contentstack settings. To reach the settings, go to your stack and click on the settings icon from the left sidebar. The API Key (CS_API_KEY) can be found on this page.

For the delivery token (CS_DELIVERY_TOKEN), click on “Tokens” in the settings page. If no delivery token exists, please create one by clicking on the top right button first. Once you have a delivery token, you can click on it, and find it in the field “Delivery Token”.

The region (CS_REGION) can be found directly in the URL. It should look like <REGION>-app.contentstack.com. The <REGION> here is the region you need to use. if the URL is app.contentstack.io, the region will be us.

Database credentials

When testing the application locally, the DB_* variables can be left as-is. This will create a file called db.sqlite3. This can be handy for local testing.

For production use, databases like MySQL and Postgres are supported as well. For testing, alternative databases can quickly be spun up locally:

docker compose up -d

Configuration options

KeyExample valueDescription
CS_API_KEY-The API key for the Contentstack stack
CS_DELIVERY_TOKEN-The Contentstack delivery token, used to fetch content
CS_MANAGEMENT_TOKEN-The Contentstack management token, mainly used when creating content types in the CLI
CS_BRANCHmainThe branch of the Contentstack stack to use
CS_REGIONus / eu / azure-na / azure-euThe region your Contentstack is located in. Visit Configuration for more information
DB_CONNfile:db.sqlite3The database connection string
DB_TYPEsqlite3 / mysql / postgresThe type of the database to connect to
DEBUG_AUTH_BYPASStrue / 1DEBUG: Disable authentication checks in the API server

Command Line Interface

The Contentstack Bridge has a powerful CLI. It will allow you to:

  • Index all Contentstack entries for easier querying
  • Spin up an API server
  • Set up necessary configuration in Contentstack
  • Run actions in Contentstack (Coming soon!)
  • And much more

Subpages

Options

An overview of all CLI options

Subsections of CLI

Options

Global flags

  • --env-file
    • Specify a different location of the .env file. Defaults to the location of the executable
  • --quiet
    • Only log output with a level of warning or above
  • --verbose
    • Log all ouput, including the most verbose messages

Subcommands

check:health

Check the health of the application and the configuration. Useful when configuring or updating the application.

Flags

migrate:db

Perform database migrations. This will be needed during the initial setup, as well as during future updates.

Flags

  • --reset
    • Revert any previously done database migrations before applying the migrations. WARNING: This will delete any existing data in affected database tables.

remote:setup

Set up or update necessary config in Contentstack. This command is idempotent, so running it multiple times will not break anything.

Flags

  • --reset
    • Revert any previously done database migrations before applying the migrations. WARNING: This will delete any existing data in affected database tables.

remote:sync

Synchronise all Contentstack entries into the database. By default, this will be incremental, meaning that every synchronisation action will continue where the last one left off.

Flags

  • --reset
    • Synchronise all data, instead of starting from the last sync token

server

Run a webserver with a REST API. More information about the webserver can be found on the API Server page.

Flags

  • --port
    • The port to run the server on. Defaults to 4000

create:content-type

Create a new content type, with some standard fields.

Flags

  • --name
    • The title of the content type to create
  • --machine-name
    • The machine name of the content type to create
  • --dry-run
    • Log the actions instead of actually running them

API Server

The API server allows the Contentstack Bridge to be used as an alternative to the Contentstack API. This has a couple of advantages:

  • Querying arguably becomes a lot easier, since the content type is no longer required in a URL query
  • Data can be transformed locally, since it’s stored in a local database
  • Full URLs can be saved, using a parenting system within the content types of entries

All requests require a header Authorization. The value should be equal to the Contentstack delivery token.

Subpages

Endpoints

An overview of all the API endpoints

Response types

A list of possible response types

Subsections of API Server

Endpoints

Get entry by URL

/api/v1/get-entry-by-url

Methods

  • GET

Parameters

  • url (required)
    • The full URL of the entry. This includes the path parts from the parent pages
  • locale (required)
    • The locale of the entry to fetch

Response type

RoutableEntryResponse

Get entry by UID

/api/v1/get-entry-by-uid

Methods

  • GET

Parameters

  • uid (required)
    • The UID of the entry
  • locale (required)
    • The locale of the entry to fetch

Response type

RoutableEntryResponse

Get all content types

/api/v1/content-types

Methods

  • GET

Parameters

Response type

ContentTypesResponse

Get single content type

/api/v1/content-type

Methods

  • GET

Parameters

  • content_type (required)
    • The UID of the content type

Response type

ContentTypeResponse

Get all global fields

/api/v1/global-fields

Methods

  • GET

Parameters

Response type

GlobalFieldsResponse

Get all locales

/api/v1/locales

Methods

  • GET

Parameters

Response type

LocalesResponse

Sync Contentstack data

/api/v1/sync

Methods

  • POST

Parameters

Response type

SyncResponse

Get all translations

/api/v1/translations

Methods

  • GET

Parameters

  • locale (required)
    • The locale of the entry to fetch

Response type

TranslationsResponse

Response types

RoutableEntryResponse

{
  data: { // Will be null if there's an error
    // An array of alternative locales.
    alt_locales: {
      uid: string
      content_type: string
      locale: string
      slug: string
      url: string
    }[]

    // An array of parent entries, to be used when constructing breadcrumbs.
    breadcrumbs: {
        id: string
        uid: string
        title: string
        content_type: string
        locale: string
        slug: string
        url: string
        parent: string // UID of the parent. Will be empty if there's no parent.
        exclude_sitemap: boolean
        published: boolean // Will always be true, since unpublished entries are excluded in the API.
    }[]

    // The entry is directly queried from Contentstack.
    entry: {
      ACL: unknown
      _in_progress: boolean
      _version: number
      content_type: string
      created_at: string // Timestamp string
      created_by: string // UID of the creator
      locale: string
      parent: {
        _content_type_uid: string
        uid: string
      }[]
      publish_details: {
        environment: string // The environment UID
        locale: string
        time: string // Timestamp string
        user: string // The user UID
      }
      tags: string[]
      title: string
      uid: string
      updated_at: string // Timestamp string
      updated_by: string // The user UID
      url: string
      seo?: {
        description?: string
        og_description?: string
        og_title?: string
        title?: string
      }
      // additional options for any other fields
      [key: string]: unknown
    }
  } | null
  error: string | null // Will be null unless there's an error
}

ContentTypesResponse

{
  data: { // Will be null if there's an error
    content_types: {
      DEFAULT_ACL: unknown
      SYS_ACL: unknown
      _version: number
      abilities: {
        create_object: boolean
        delete_all_objects: boolean
        delete_object: boolean
        get_all_objects: boolean
        get_one_object: boolean
        update_object: boolean
      }
      created_at: string // Timestamp string
      description: string
      inbuilt_class: boolean
      last_activity: unknown
      maintain_revisions: boolean
      options: {
        is_page: boolean
        publishable: boolean
        singleton: boolean // Whether or not the content type supports multiple entries
        sub_title: string[]
        title: string
        url_pattern: string
        url_prefix: string
        // additional options for any other fields
        [key: string]: unknown
      }
      schema: {
        data_type: string
        display_name: string
        field_metadata: {
          _default: boolean
          version: number
        }
        mandatory: boolean
        multiple: boolean
        non_localizable: boolean
        uid: string
        unique: boolean
      }[]
      title: string
      uid: string
      updated_at: string // Timestamp string
    }[]
  } | null
  error: string | null // Will be null unless there's an error
}

ContentTypeResponse

{
  data: { // Will be null if there's an error
    content_type: {
      DEFAULT_ACL: unknown
      SYS_ACL: unknown
      _version: number
      abilities: {
        create_object: boolean
        delete_all_objects: boolean
        delete_object: boolean
        get_all_objects: boolean
        get_one_object: boolean
        update_object: boolean
      }
      created_at: string // Timestamp string
      description: string
      inbuilt_class: boolean
      last_activity: unknown
      maintain_revisions: boolean
      options: {
        is_page: boolean
        publishable: boolean
        singleton: boolean // Whether or not the content type supports multiple entries
        sub_title: string[]
        title: string
        url_pattern: string
        url_prefix: string
        // additional options for any other fields
        [key: string]: unknown
      }
      schema: {
        data_type: string
        display_name: string
        field_metadata: {
          _default: boolean
          version: number
        }
        mandatory: boolean
        multiple: boolean
        non_localizable: boolean
        uid: string
        unique: boolean
      }[]
      title: string
      uid: string
      updated_at: string // Timestamp string
    }
  } | null
  error: string | null // Will be null unless there's an error
}

GlobalFieldsResponse

{
  data: { // Will be null if there's an error
    global_fields: {
      _version: number
      created_at: string // Timestamp string
      description: string
      inbuilt_class: boolean
      last_activity: unknown
      maintain_revisions: boolean
      schema: {
        data_type: string
        display_name: string
        error_messages: {
          format: string
        }
        field_metadata: {
          default_value: string
          description: string
          version: number
        }
        format: string
        mandatory: boolean
        multiple: boolean
        non_localizable: boolean
        uid: string
        unique: boolean
      }[]
      title: string
      uid: string
      updated_at: string // Timestamp string
    }[]
  } | null
  error: string | null // Will be null unless there's an error
}

LocalesResponse

{
  data: { // Will be null if there's an error
    locales: {
      ACL: unknown[]
      _version: number
      code: string
      created_at: string // Timestamp string
      created_by: string // UID of the creator
      fallback_locale: string
      name: string
      uid: string
      updated_at: string // Timestamp string
      updated_by: string // UID of the creator
    }[]
  } | null
  error: string | null // Will be null unless there's an error
}

SyncResponse

{
  error: string | null; // Will be null unless there's an error
}

TranslationsResponse

{
  data: Record<string, string> | null; // Will be null if there's an error
  error: string | null; // Will be null unless there's an error
}