PHPackages                             amazeelabs/silverback\_gatsby - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. amazeelabs/silverback\_gatsby

ActiveDrupal-module

amazeelabs/silverback\_gatsby
=============================

Bridge module between Gatsby and Drupal.

3.7.12(1y ago)049.8k↓41.9%[1 PRs](https://github.com/AmazeeLabs/silverback_gatsby/pulls)GPL-2.0+PHP

Since May 31Pushed 1y ago3 watchersCompare

[ Source](https://github.com/AmazeeLabs/silverback_gatsby)[ Packagist](https://packagist.org/packages/amazeelabs/silverback_gatsby)[ Docs](https://silverback.netlify.app)[ RSS](/packages/amazeelabs-silverback-gatsby/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (125)Used By (0)

Silverback Gatsby
=================

[](#silverback-gatsby)

A Drupal module that provides integration endpoints for the [`@amazeelabs/gatsby-source-silverback`](https://www.npmjs.com/package/@amazeelabs/gatsby-source-silverback) Gatsby plugin. Allows writing custom GraphQL schema definitions based on GraphQL V4 and automatically send incremental updates to Gatsby.

BREAKING CHANGES
----------------

[](#breaking-changes)

In version 2, a couple of breaking changes have been introduced due to the new dependency on the `graphql_directives` module.

- `@resolveEntityReference` and `@resolveEntityReferenceRevisions` do not support the `single` parameter any more. They can be chained with `@seek`instead.
- Gutenberg directives moved to the `silverback_gutenberg` module and changed in naming and parameters. Refer to the generated directives for more information.
- New default value handling requires either nullable custom type invocations, or `@default` directives on them. Refer to the `graphql_directives` module for more information.

Getting started
---------------

[](#getting-started)

First, simply install and enable the module.

```
composer require amazeelabs/silverback_gatsby
drush en -y silverback_gatsby
```

Create a GraphQL folder at the root of your project. This will contain all the schema definitions. To improve IDE support, you can export all the schema definitions in a single file:

```
drush graphql:directives > graphql/directives.graphqls
```

It is advised to ignore this file in version control and rather re-create it when needed.

Now you can start to create the project schema defintion and fill in resolvers by using the directives provided.

```
schema {
  query: Query
}

type Query {
  page(id: String!): Page @loadEntity(type: "node", id: "$id")
}

type Page @entity(type: "node", bundle: "page") {
  path: String! @resolveEntityPath
  title: String! @resolveEntityLabel
  body: String @resolveProperty(path: "body.value")
}
```

Now create a new GraphQL server configuration, use the `Directable` schema plugin and make sure to enable the "Silverback Gatsby" extension. The *Explorer*or *Voyager* screens should show root level fields for loading and querying our type (`loadPage`, `queryPages`) that you should be able to test now.

Automatic creation of Gatsby pages
----------------------------------

[](#automatic-creation-of-gatsby-pages)

Available using `@isPath` and `@isTemplate` field directives. See [`@amazeelabs/gatsby-source-silverback`](../../../npm/@amazeelabs/gatsby-source-silverback)plugin README for details.

Automatic resolvers
-------------------

[](#automatic-resolvers)

There are directives which create GraphQL resolvers automatically.

### @resolveProperty

[](#resolveproperty)

This field directive is a shortcut for `property_path` data producer.

For example, this schema

```
type Page @entity(type: "node", bundle: "page") {
  body: String @resolveProperty(path: "field_body.0.processed")
}
```

Will create the following resolver for `Page.body` field

```
$builder->produce('property_path', [
  'path' => $builder->fromValue('field_body.0.processed'),
  'value' => $builder->fromParent(),
  'type' => $builder->fromValue('entity:node:page'),
])
```

### @resolveEntityPath

[](#resolveentitypath)

Resolves the relative path to an entity. A shortcut for `entity_url`+`url_path`data producers.

Example:

```
type Page @entity(type: "node", bundle: "page") {
  path: String! @resolveEntityPath
}
```

### @resolveEntityReference

[](#resolveentityreference)

Resolves the references entities. A shortcut for `entity_reference` data producer.

Example:

```
type Page @entity(type: "node", bundle: "page") {
  relatedArticles: [Article]! @resolveEntityReference(field: "field_related_articles", single: false)
  parentPage: Page @resolveEntityReference(field: "field_related_articles", single: true)
}
```

### @resolveEntityReferenceRevisions

[](#resolveentityreferencerevisions)

Resolves the entity reference revisions fields, e.g. Paragraphs. A shortcut for `entity_reference_revisions` data producer.

Example:

```
type Page @entity(type: "node", bundle: "page") {
  paragraphs: [PageParagraphs!]! @resolveEntityReferenceRevisions(field: "field_paragraphs", single: false)
  singleParagraph: ParagraphText @resolveEntityReferenceRevisions(field: "field_single_paragraph", single: true)
}
```

Menus
-----

[](#menus)

To expose Drupal menus to Gatsby, one can use the `@menu` directive.

```
type MainMenu @menu(menu_id: "main") {
  items: [MenuItem!]! @resolveMenuItems
}

type MenuItem {
  id: String! @resolveMenuItemId
  parent: String! @resolveMenuItemId
  label: String! @resolveMenuItemLabel
  url: String! @resolveMenuItemUrl
}
```

GraphQL does not allow recursive fragments, so something like this would not be possible:

```
query Menu {
  drupalMainMenu {
    items {
      ...MenuItem
    }
  }
}
fragment MenuItem on MenuItem {
  label
  url
  children {
    # Fragment recursion, not allowed in GraphQL!
    ...MenuItem
  }
}
```

That's why the menu tree is automatically flattened, and `id` and `parent`properties are added to each item, so the tree can easily be reconstructed in the consuming application.

```
query MainMenu {
  drupalMainMenu(langcode: { eq: "en" }) {
    items {
      id
      parent
      label
      url
    }
  }
}
```

The `@menu` directive also takes an optional `max_level` argument. It can be used to restrict the number of levels a type will include, which in turn can optimize caching and Gatsby build times. In many cases, the main page layout only displays the first level of menu items. When a new page is created and attached to the third level, Gatsby will still re-render all pages, because the menu that is used in the header changed. By separating this into two levels, we can make sure the outer layout really only changes when menu levels are changed that are displayed.

```
type MainMenu @menu(menu_id: "main") {...}
# Will only include the first level and trigger updates when a first level item
# changes.
type LayoutMainMenu @menu(menu_id: "main", max_level: 1) {...}
```

### Menu negotiation

[](#menu-negotiation)

In some cases, the same GraphQL field might have to return different menus, based on the current context. A prominent use case would be a multi-site setup where different menus should be displayed based on the current account Gatsby is using to fetch data with.

In this case, multiple menu id's can be passed to the `@menu` directive, and the resolver will pick **the first one** that is accessible to the user account.

```
type MainMenu
  @menu(menu_ids: ["site_a_main", "site_b_main"], item_type: "MenuItem")
```

It checks access for the `view label` operation on the `Menu` entity, which is allowed for everybody by default. The consuming project has to implement other mechanisms to restrict access therefore control which menus are used for which site.

Configuring update notifications
--------------------------------

[](#configuring-update-notifications)

The last thing to do is to tell Gatsby whenever something noteworthy changes. By using the `@entity` directive in our schema, we already told Drupal to keep track of all changes related to the entity types we care about. All there is missing is a Gatsby webhook url to trigger a refresh. We provide this via an environment variable that is named after our configured GraphQL server.

```
GATSBY_BUILD_HOOK_[uppercased-server-id]=https://...
```

So if the server was called `My Server` and the automatically generated machine name is `my_server`, then the environment variable would look like this:

```
GATSBY_BUILD_HOOK_MY_SERVER=https://...
```

The value is a semicolon-separated list of urls that will be called in case of an update. This can be `http://localhost:8000/__refresh`, for local testing a Gatsby environment with `ENABLE_GATSBY_REFRESH_ENDPOINT=true`, or the build and preview webhooks provided by Gatsby Cloud.

The Gatsby site has to contain the [`@amazeelabs/gatsby-source-silverback`](https://www.npmjs.com/package/@amazeelabs/gatsby-source-silverback) plugin for this to work.

Access control
--------------

[](#access-control)

By default, [`@amazeelabs/gatsby-source-silverback`](https://www.npmjs.com/package/@amazeelabs/gatsby-source-silverback)behaves like an anonymous user. To change that, simply create a user account with the required permissions and pass the credentials to the `auth_user` and `auth_pass` configuration options of the plugin.

A very common use case would be to create a "preview" user that bypasses content access control and use it for the "Preview" environment on Gatsby cloud, so unpublished content can be previewed. Another sensible case would be to create a "build" user that has access to published content and block anonymous access to Drupal entirely.

Trigger a build
---------------

[](#trigger-a-build)

There are multiple ways to trigger a Gatsby build:

- on entity save
- via the Drupal UI or Drush.

### On entity save

[](#on-entity-save)

On the *Build* tab of the schema configuration, check the *Trigger a build on entity save* checkbox.

### Drupal UI

[](#drupal-ui)

On the same *Build* tab, click the *Gatsby Build* button.

### Drush

[](#drush)

This command can be configured in the system cron. `drush silverback-gatsby:build [server_id]`

###  Health Score

43

—

FairBetter than 91% of packages

Maintenance49

Moderate activity, may be stable

Popularity28

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity69

Established project with proven stability

 Bus Factor1

Top contributor holds 66.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~11 days

Recently: every ~4 days

Total

122

Last Release

372d ago

Major Versions

1.28.1 → 2.0.02023-01-06

2.4.3 → 3.0.02023-11-08

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/501415?v=4)[Philipp Melab](/maintainers/pmelab)[@pmelab](https://github.com/pmelab)

---

Top Contributors

[![nbaosullivan](https://avatars.githubusercontent.com/u/157913?v=4)](https://github.com/nbaosullivan "nbaosullivan (2 commits)")[![pmelab](https://avatars.githubusercontent.com/u/501415?v=4)](https://github.com/pmelab "pmelab (1 commits)")

### Embed Badge

![Health badge](/badges/amazeelabs-silverback-gatsby/health.svg)

```
[![Health](https://phpackages.com/badges/amazeelabs-silverback-gatsby/health.svg)](https://phpackages.com/packages/amazeelabs-silverback-gatsby)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
