diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 000000000..9e9897278
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,69 @@
+name: Deploy
+on:
+ push:
+ branches:
+ - prod
+ - dev
+
+jobs:
+ test:
+ name: Deploy
+ runs-on: ubuntu-20.04
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: Setup
+ uses: ./.github/actions/setup
+
+ - run: pwd
+ working-directory: ${{ runner.home }}
+
+ - name: Extract branch name
+ shell: bash
+ run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
+ id: extract_branch
+
+ - name: Prepare deployment package
+ run: pnpm turbo:prep && pnpm deploy --filter "@custom/website" ../deploy --prod
+ env:
+ VITE_DECAP_REPO: ${{ github.repository }}
+ VITE_DECAP_BRANCH: ${{ steps.extract_branch.outputs.branch }}
+
+ - name: Build
+ run: pnpm run --filter @custom/website build
+ working-directory: ../deploy
+ env:
+ CLOUDINARY_API_KEY: ${{ vars.CLOUDINARY_API_KEY }}
+ CLOUDINARY_API_SECRET: ${{ secrets.CLOUDINARY_API_SECRET }}
+ CLOUDINARY_CLOUDNAME: ${{ secrets.CLOUDINARY_CLOUDNAME }}
+ GATSBY_PUBLIC_URL: ${{ vars.GATSBY_PUBLIC_URL }}
+
+ - name: Check for Netlify auth token
+ id: netlify-check
+ shell: bash
+ run: |
+ if [ "${{ secrets.NETLIFY_AUTH_TOKEN }}" != '' ]; then
+ echo "available=true" >> $GITHUB_OUTPUT;
+ else
+ echo "available=false" >> $GITHUB_OUTPUT;
+ fi
+
+ - name: Deploy to dev
+ run: pnpm netlify deploy --prod --filter "@custom/website"
+ working-directory: ../deploy
+ if: github.ref == 'refs/heads/dev' && steps.netlify-check.outputs.available == 'true' && vars.NETLIFY_DEV_ID != ''
+ env:
+ NETLIFY_SITE_ID: ${{ vars.NETLIFY_DEV_ID }}
+ NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
+
+ - name: Deploy to prod
+ run: pnpm netlify deploy --prod --filter "@custom/website"
+ working-directory: ../deploy
+ if: github.ref == 'refs/heads/prod' && steps.netlify-check.outputs.available == 'true' && vars.NETLIFY_PROD_ID != ''
+ env:
+ NETLIFY_SITE_ID: ${{ vars.NETLIFY_PROD_ID }}
+ NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
+
diff --git a/.github/workflows/high_content_volume.yml b/.github/workflows/high_content_volume.yml
new file mode 100644
index 000000000..02edab017
--- /dev/null
+++ b/.github/workflows/high_content_volume.yml
@@ -0,0 +1,50 @@
+name: High Content Volume
+on:
+ workflow_dispatch:
+
+jobs:
+ test:
+ name: Test
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 1
+
+ - name: Setup
+ uses: ./.github/actions/setup
+
+ - name: TurboRepo local server
+ uses: felixmosh/turborepo-gh-artifacts@v2
+ with:
+ server-token: 'local'
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Prepare
+ run: pnpm turbo:prep
+ env:
+ TURBO_API: 'http://127.0.0.1:9080'
+ TURBO_TOKEN: 'local'
+ TURBO_TEAM: 'local'
+
+ - name: 'Drupal: Start'
+ run: pnpm --filter "@custom/cms" start &
+
+ - name: 'Gatsby: Clean'
+ run: pnpm --filter "@custom/website" clean
+
+ - name: 'Drupal: Create content'
+ run: pnpm --filter "@custom/cms" drush php:script scripts/create-lots-of-content/run.php
+
+ - name: 'Gatsby: Full build'
+ run: pnpm --filter "@custom/website" build:gatsby
+
+ - name: 'Gatsby: Incremental build without new content'
+ run: pnpm --filter "@custom/website" build:gatsby
+
+ - name: 'Drupal: Create more content'
+ run: pnpm --filter "@custom/cms" drush php:script scripts/create-lots-of-content/create-100-pages.php
+
+ - name: 'Gatsby: Incremental build with new content'
+ run: pnpm --filter "@custom/website" build:gatsby
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 41f768f27..a8f39a873 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -40,6 +40,16 @@ jobs:
path: tests/e2e/playwright-report/
retention-days: 3
+ - name: Check for Chromatic project token
+ id: chromatic-check
+ shell: bash
+ run: |
+ if [ "${{ secrets.CHROMATIC_PROJECT_TOKEN }}" != '' ]; then
+ echo "available=true" >> $GITHUB_OUTPUT;
+ else
+ echo "available=false" >> $GITHUB_OUTPUT;
+ fi
+
- name: Publish to Chromatic
uses: chromaui/action@v1
with:
@@ -49,6 +59,7 @@ jobs:
storybookBaseDir: packages/ui
onlyChanged: true
exitOnceUploaded: true
+ if: ${{ steps.chromatic-check.outputs.available == 'true' }}
- name: Deploy storybook to netlify
run:
diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile
index b4a9db06c..913f8189c 100644
--- a/.gitpod.Dockerfile
+++ b/.gitpod.Dockerfile
@@ -1,4 +1,11 @@
FROM gitpod/workspace-full
+
+RUN bash -c 'VERSION="18.19.0" \
+ && source $HOME/.nvm/nvm.sh && nvm install $VERSION \
+ && nvm use $VERSION && nvm alias default $VERSION'
+
+RUN echo "nvm use default &>/dev/null" >> ~/.bashrc.d/51-nvm-fix
+
RUN sudo update-alternatives --set php $(which php8.2)
RUN sudo install-packages php8.2-gd php8.2-mbstring php8.2-curl php8.2-sqlite3 php8.2-zip php8.2-xdebug php8.2-imagick
RUN pnpx playwright@1.32.3 install-deps
@@ -11,14 +18,9 @@ RUN /home/gitpod/.deno/bin/deno completions bash > /home/gitpod/.bashrc.d/90-den
echo 'export DENO_INSTALL="/home/gitpod/.deno"' >> /home/gitpod/.bashrc.d/90-deno && \
echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> /home/gitpod/.bashrc.d/90-deno
-# Install neovim and helpers
-RUN wget https://github.com/neovim/neovim/releases/download/v0.9.2/nvim-linux64.tar.gz && \
- tar xzf nvim-linux64.tar.gz && \
- sudo mv nvim-linux64 /usr/local/nvim && \
- sudo ln -s /usr/local/nvim/bin/nvim /usr/local/bin/nvim && \
- rm -rf nvim-linux64.tar.gz
-RUN sudo apt-get install -y fd-find
-RUN npm install -g neovim
+RUN sudo add-apt-repository ppa:maveonair/helix-editor && \
+ sudo apt update && \
+ sudo apt install helix
# Install phpactor
RUN curl -Lo phpactor.phar https://github.com/phpactor/phpactor/releases/latest/download/phpactor.phar
diff --git a/.idea/.gitignore b/.idea/.gitignore
index 03d7c2646..a87f3fbd7 100644
--- a/.idea/.gitignore
+++ b/.idea/.gitignore
@@ -7,3 +7,5 @@
/dataSources/
/dataSources.local.xml
/markdown.xml
+# GitHub Copilot persisted chat sessions
+/copilot/chatSessions
diff --git a/.idea/prettier.xml b/.idea/prettier.xml
index d6de67d37..6e16fd106 100644
--- a/.idea/prettier.xml
+++ b/.idea/prettier.xml
@@ -3,6 +3,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Test_Format.xml b/.idea/runConfigurations/Fix_Formatting.xml
similarity index 65%
rename from .idea/runConfigurations/Test_Format.xml
rename to .idea/runConfigurations/Fix_Formatting.xml
index d9d140b46..0189aa8e3 100644
--- a/.idea/runConfigurations/Test_Format.xml
+++ b/.idea/runConfigurations/Fix_Formatting.xml
@@ -1,9 +1,9 @@
-
+
-
+
diff --git a/.idea/silverback-template.iml b/.idea/silverback-template.iml
index 9c91dbf7b..a6f46f687 100644
--- a/.idea/silverback-template.iml
+++ b/.idea/silverback-template.iml
@@ -15,6 +15,7 @@
+
diff --git a/.lagoon/Dockerfile b/.lagoon/Dockerfile
index 45a7006f4..f81105156 100644
--- a/.lagoon/Dockerfile
+++ b/.lagoon/Dockerfile
@@ -81,6 +81,7 @@ ENV WEBROOT=web
FROM uselagoon/nginx-drupal as nginx
COPY --from=cli /app /app
+RUN cd /app/web && cp ../node_modules/@custom/ui/build/gutenberg.css .
COPY .lagoon/nginx-conf/redirects-map.conf /etc/nginx/redirects-map.conf
WORKDIR /app
diff --git a/.prettierignore b/.prettierignore
index 189e95f3a..6ad8630f6 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -2,3 +2,4 @@ _local
apps
packages
tests
+.turbo
diff --git a/INIT.md b/INIT.md
index 98c56377e..679a143b6 100644
--- a/INIT.md
+++ b/INIT.md
@@ -21,7 +21,11 @@ replace(
'# ' + process.env.PROJECT_NAME_HUMAN,
);
replace(
- 'apps/cms/config/sync/system.site.yml',
+ [
+ 'apps/cms/config/sync/system.site.yml',
+ 'tests/schema/specs/content.spec.ts',
+ 'tests/e2e/specs/drupal/metatags.spec.ts',
+ ],
'Silverback Drupal Template',
process.env.PROJECT_NAME_HUMAN,
);
@@ -97,7 +101,7 @@ Update the auth key for Gatsby user.
```ts
const authKey = randomString(32);
replace(
- 'apps/website/gatsby-config.js',
+ 'apps/cms/gatsby-config.mjs',
"auth_key: 'cfdb0555111c0f8924cecab028b53474'",
`auth_key: '${authKey}'`,
);
diff --git a/README.md b/README.md
index 74a037439..9e4a6a21c 100644
--- a/README.md
+++ b/README.md
@@ -24,8 +24,19 @@ Other steps
- [Create a new Lagoon project](https://amazeelabs.atlassian.net/wiki/spaces/ALU/pages/368115717/Create+a+new+Lagoon+project)
- [Create a new Netlify project](https://amazeelabs.atlassian.net/wiki/spaces/ALU/pages/368017428/Create+a+new+Netlify+project)
- Check the [Environment overrides](#environment-overrides) section below
+- Check the [Choose a CMS](#choose-a-cms) section below
- Create `dev` and `prod` branches (and optionally `stage`) from `release`
+## Choose a CMS
+
+The template comes with Drupal and Decap CMS enabled by default. To disable
+either (or both), follow these two steps:
+
+1. Remove the dependencies to `@custom/cms`/`@custom/decap` from
+ `apps/website/package.json`
+2. Remove the `@custom/cms`/`@custom/decap` plugins from
+ `apps/website/gatsby-config.mjs`
+
## Branches and environments
diff --git a/apps/cms/composer.lock b/apps/cms/composer.lock
index 7176d4424..07ca8aaa5 100644
--- a/apps/cms/composer.lock
+++ b/apps/cms/composer.lock
@@ -96,16 +96,16 @@
},
{
"name": "amazeelabs/graphql_directives",
- "version": "2.4.0",
+ "version": "2.5.0",
"source": {
"type": "git",
"url": "https://github.com/AmazeeLabs/graphql_directives.git",
- "reference": "57d0b5b48a42f27c612e8fe22da967e138f64e30"
+ "reference": "aa67a16d5acedc87a46f80827482527bd3bc19b2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/AmazeeLabs/graphql_directives/zipball/57d0b5b48a42f27c612e8fe22da967e138f64e30",
- "reference": "57d0b5b48a42f27c612e8fe22da967e138f64e30",
+ "url": "https://api.github.com/repos/AmazeeLabs/graphql_directives/zipball/aa67a16d5acedc87a46f80827482527bd3bc19b2",
+ "reference": "aa67a16d5acedc87a46f80827482527bd3bc19b2",
"shasum": ""
},
"require": {
@@ -127,9 +127,9 @@
"homepage": "https://silverback.netlify.app",
"support": {
"issues": "https://github.com/AmazeeLabs/graphql_directives/issues",
- "source": "https://github.com/AmazeeLabs/graphql_directives/tree/2.4.0"
+ "source": "https://github.com/AmazeeLabs/graphql_directives/tree/2.5.0"
},
- "time": "2024-02-07T13:55:07+00:00"
+ "time": "2024-04-04T10:12:23+00:00"
},
{
"name": "amazeelabs/proxy-default-content",
diff --git a/apps/cms/config/sync/config_ignore.settings.yml b/apps/cms/config/sync/config_ignore.settings.yml
index 22621eec1..3e06627a5 100644
--- a/apps/cms/config/sync/config_ignore.settings.yml
+++ b/apps/cms/config/sync/config_ignore.settings.yml
@@ -3,4 +3,5 @@ _core:
mode: simple
ignored_config_entities:
- 'webform.webform*'
+ - ~webform.webform.inquiry
enable_export_filtering: true
diff --git a/apps/cms/config/sync/views.view.content_hub.yml b/apps/cms/config/sync/views.view.content_hub.yml
new file mode 100644
index 000000000..5ea530f9e
--- /dev/null
+++ b/apps/cms/config/sync/views.view.content_hub.yml
@@ -0,0 +1,274 @@
+uuid: 52941f28-544a-4658-86d4-a806ca2adc29
+langcode: en
+status: true
+dependencies:
+ config:
+ - node.type.page
+ module:
+ - node
+ - user
+id: content_hub
+label: 'Content hub'
+module: views
+description: ''
+tag: ''
+base_table: node_field_data
+base_field: nid
+display:
+ default:
+ id: default
+ display_title: Default
+ display_plugin: default
+ position: 0
+ display_options:
+ fields:
+ title:
+ id: title
+ table: node_field_data
+ field: title
+ relationship: none
+ group_type: group
+ admin_label: ''
+ entity_type: node
+ entity_field: title
+ plugin_id: field
+ label: ''
+ exclude: false
+ alter:
+ alter_text: false
+ make_link: false
+ absolute: false
+ word_boundary: false
+ ellipsis: false
+ strip_tags: false
+ trim: false
+ html: false
+ element_type: ''
+ element_class: ''
+ element_label_type: ''
+ element_label_class: ''
+ element_label_colon: true
+ element_wrapper_type: ''
+ element_wrapper_class: ''
+ element_default_classes: true
+ empty: ''
+ hide_empty: false
+ empty_zero: false
+ hide_alter_empty: true
+ click_sort_column: value
+ type: string
+ settings:
+ link_to_entity: true
+ group_column: value
+ group_columns: { }
+ group_rows: true
+ delta_limit: 0
+ delta_offset: 0
+ delta_reversed: false
+ delta_first_last: false
+ multi_type: separator
+ separator: ', '
+ field_api_classes: false
+ pager:
+ type: mini
+ options:
+ offset: 0
+ items_per_page: 10
+ total_pages: null
+ id: 0
+ tags:
+ next: ››
+ previous: ‹‹
+ expose:
+ items_per_page: false
+ items_per_page_label: 'Items per page'
+ items_per_page_options: '5, 10, 25, 50'
+ items_per_page_options_all: false
+ items_per_page_options_all_label: '- All -'
+ offset: false
+ offset_label: Offset
+ exposed_form:
+ type: basic
+ options:
+ submit_button: Apply
+ reset_button: false
+ reset_button_label: Reset
+ exposed_sorts_label: 'Sort by'
+ expose_sort_order: true
+ sort_asc_label: Asc
+ sort_desc_label: Desc
+ access:
+ type: perm
+ options:
+ perm: 'access content'
+ cache:
+ type: tag
+ options: { }
+ empty: { }
+ sorts:
+ title:
+ id: title
+ table: node_field_data
+ field: title
+ relationship: none
+ group_type: group
+ admin_label: ''
+ entity_type: node
+ entity_field: title
+ plugin_id: standard
+ order: ASC
+ expose:
+ label: ''
+ field_identifier: ''
+ exposed: false
+ arguments: { }
+ filters:
+ status:
+ id: status
+ table: node_field_data
+ field: status
+ entity_type: node
+ entity_field: status
+ plugin_id: boolean
+ value: '1'
+ group: 1
+ expose:
+ operator: ''
+ type:
+ id: type
+ table: node_field_data
+ field: type
+ entity_type: node
+ entity_field: type
+ plugin_id: bundle
+ value:
+ page: page
+ group: 1
+ langcode:
+ id: langcode
+ table: node_field_data
+ field: langcode
+ relationship: none
+ group_type: group
+ admin_label: ''
+ entity_type: node
+ entity_field: langcode
+ plugin_id: language
+ operator: in
+ value:
+ '***LANGUAGE_language_interface***': '***LANGUAGE_language_interface***'
+ group: 1
+ exposed: false
+ expose:
+ operator_id: ''
+ label: ''
+ description: ''
+ use_operator: false
+ operator: ''
+ operator_limit_selection: false
+ operator_list: { }
+ identifier: ''
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ reduce: false
+ is_grouped: false
+ group_info:
+ label: ''
+ description: ''
+ identifier: ''
+ optional: true
+ widget: select
+ multiple: false
+ remember: false
+ default_group: All
+ default_group_multiple: { }
+ group_items: { }
+ title:
+ id: title
+ table: node_field_data
+ field: title
+ relationship: none
+ group_type: group
+ admin_label: ''
+ entity_type: node
+ entity_field: title
+ plugin_id: string
+ operator: contains
+ value: ''
+ group: 1
+ exposed: true
+ expose:
+ operator_id: title_op
+ label: Title
+ description: ''
+ use_operator: false
+ operator: title_op
+ operator_limit_selection: false
+ operator_list: { }
+ identifier: title
+ required: false
+ remember: false
+ multiple: false
+ remember_roles:
+ authenticated: authenticated
+ anonymous: '0'
+ super_admin: '0'
+ administrator: '0'
+ gatsby_build: '0'
+ editor: '0'
+ placeholder: ''
+ is_grouped: false
+ group_info:
+ label: ''
+ description: ''
+ identifier: ''
+ optional: true
+ widget: select
+ multiple: false
+ remember: false
+ default_group: All
+ default_group_multiple: { }
+ group_items: { }
+ filter_groups:
+ operator: AND
+ groups:
+ 1: AND
+ style:
+ type: default
+ options:
+ grouping: { }
+ row_class: ''
+ default_row_class: true
+ uses_fields: false
+ row:
+ type: fields
+ options:
+ default_field_elements: true
+ inline: { }
+ separator: ''
+ hide_empty: false
+ query:
+ type: views_query
+ options:
+ query_comment: ''
+ disable_sql_rewrite: false
+ distinct: false
+ replica: false
+ query_tags: { }
+ relationships: { }
+ header: { }
+ footer: { }
+ display_extenders: { }
+ cache_metadata:
+ max-age: -1
+ contexts:
+ - 'languages:language_content'
+ - 'languages:language_interface'
+ - url
+ - url.query_args
+ - 'user.node_grants:view'
+ - user.permissions
+ tags: { }
diff --git a/apps/cms/config/sync/webform.webform.inquiry.yml b/apps/cms/config/sync/webform.webform.inquiry.yml
new file mode 100644
index 000000000..b81b4b274
--- /dev/null
+++ b/apps/cms/config/sync/webform.webform.inquiry.yml
@@ -0,0 +1,222 @@
+uuid: abe65e3d-4e21-4079-9f3e-dcb8f5cf4f7b
+langcode: en
+status: open
+dependencies: { }
+weight: 0
+open: null
+close: null
+uid: 1
+template: false
+archive: false
+id: inquiry
+title: Inquiry
+description: 'Ask a simple question.'
+categories: { }
+elements: |-
+ name:
+ '#title': 'Your Name'
+ '#type': textfield
+ '#required': true
+ '#default_value': '[current-user:display-name]'
+ email:
+ '#title': 'Your Email'
+ '#type': email
+ '#required': true
+ '#default_value': '[current-user:mail]'
+ subject:
+ '#title': Subject
+ '#type': textfield
+ '#test': 'Testing contact webform from [site:name]'
+ question:
+ '#type': textarea
+ '#title': Question
+ '#required': true
+ actions:
+ '#type': webform_actions
+ '#title': 'Submit button(s)'
+ '#submit__label': 'Send message'
+css: ''
+javascript: ''
+settings:
+ ajax: false
+ ajax_scroll_top: form
+ ajax_progress_type: ''
+ ajax_effect: ''
+ ajax_speed: null
+ page: true
+ page_submit_path: ''
+ page_confirm_path: ''
+ page_theme_name: ''
+ form_title: both
+ form_submit_once: false
+ form_open_message: ''
+ form_close_message: ''
+ form_exception_message: ''
+ form_previous_submissions: true
+ form_confidential: false
+ form_confidential_message: ''
+ form_disable_remote_addr: false
+ form_convert_anonymous: false
+ form_prepopulate: false
+ form_prepopulate_source_entity: false
+ form_prepopulate_source_entity_required: false
+ form_prepopulate_source_entity_type: ''
+ form_unsaved: false
+ form_disable_back: false
+ form_submit_back: false
+ form_disable_autocomplete: false
+ form_novalidate: false
+ form_disable_inline_errors: false
+ form_required: false
+ form_autofocus: false
+ form_details_toggle: false
+ form_reset: false
+ form_access_denied: default
+ form_access_denied_title: ''
+ form_access_denied_message: ''
+ form_access_denied_attributes: { }
+ form_file_limit: ''
+ form_attributes: { }
+ form_method: ''
+ form_action: ''
+ share: false
+ share_node: false
+ share_theme_name: ''
+ share_title: true
+ share_page_body_attributes: { }
+ submission_label: ''
+ submission_exception_message: ''
+ submission_locked_message: ''
+ submission_log: false
+ submission_excluded_elements: { }
+ submission_exclude_empty: false
+ submission_exclude_empty_checkbox: false
+ submission_views: { }
+ submission_views_replace: { }
+ submission_user_columns: { }
+ submission_user_duplicate: false
+ submission_access_denied: default
+ submission_access_denied_title: ''
+ submission_access_denied_message: ''
+ submission_access_denied_attributes: { }
+ previous_submission_message: ''
+ previous_submissions_message: ''
+ autofill: false
+ autofill_message: ''
+ autofill_excluded_elements: { }
+ wizard_progress_bar: true
+ wizard_progress_pages: false
+ wizard_progress_percentage: false
+ wizard_progress_link: false
+ wizard_progress_states: false
+ wizard_start_label: ''
+ wizard_preview_link: false
+ wizard_confirmation: true
+ wizard_confirmation_label: ''
+ wizard_auto_forward: true
+ wizard_auto_forward_hide_next_button: false
+ wizard_keyboard: true
+ wizard_track: ''
+ wizard_prev_button_label: ''
+ wizard_next_button_label: ''
+ wizard_toggle: false
+ wizard_toggle_show_label: ''
+ wizard_toggle_hide_label: ''
+ wizard_page_type: container
+ wizard_page_title_tag: h2
+ preview: 0
+ preview_label: ''
+ preview_title: ''
+ preview_message: ''
+ preview_attributes: { }
+ preview_excluded_elements: { }
+ preview_exclude_empty: true
+ preview_exclude_empty_checkbox: false
+ draft: none
+ draft_multiple: false
+ draft_auto_save: false
+ draft_saved_message: ''
+ draft_loaded_message: ''
+ draft_pending_single_message: ''
+ draft_pending_multiple_message: ''
+ confirmation_type: url_message
+ confirmation_url: /page-minimal
+ confirmation_title: ''
+ confirmation_message: 'Confirmation message for Contact webform'
+ confirmation_attributes: { }
+ confirmation_back: true
+ confirmation_back_label: ''
+ confirmation_back_attributes: { }
+ confirmation_exclude_query: false
+ confirmation_exclude_token: false
+ confirmation_update: false
+ limit_total: null
+ limit_total_interval: null
+ limit_total_message: ''
+ limit_total_unique: false
+ limit_user: null
+ limit_user_interval: null
+ limit_user_message: ''
+ limit_user_unique: false
+ entity_limit_total: null
+ entity_limit_total_interval: null
+ entity_limit_user: null
+ entity_limit_user_interval: null
+ purge: none
+ purge_days: null
+ results_disabled: false
+ results_disabled_ignore: false
+ results_customize: false
+ token_view: false
+ token_update: false
+ token_delete: false
+ serial_disabled: false
+access:
+ create:
+ roles:
+ - anonymous
+ - authenticated
+ users: { }
+ permissions: { }
+ view_any:
+ roles: { }
+ users: { }
+ permissions: { }
+ update_any:
+ roles: { }
+ users: { }
+ permissions: { }
+ delete_any:
+ roles: { }
+ users: { }
+ permissions: { }
+ purge_any:
+ roles: { }
+ users: { }
+ permissions: { }
+ view_own:
+ roles: { }
+ users: { }
+ permissions: { }
+ update_own:
+ roles: { }
+ users: { }
+ permissions: { }
+ delete_own:
+ roles: { }
+ users: { }
+ permissions: { }
+ administer:
+ roles: { }
+ users: { }
+ permissions: { }
+ test:
+ roles: { }
+ users: { }
+ permissions: { }
+ configuration:
+ roles: { }
+ users: { }
+ permissions: { }
+handlers: { }
+variants: { }
diff --git a/apps/cms/gatsby-config.mjs b/apps/cms/gatsby-config.mjs
new file mode 100644
index 000000000..316fb9147
--- /dev/null
+++ b/apps/cms/gatsby-config.mjs
@@ -0,0 +1,36 @@
+import autoload from '@custom/schema/gatsby-autoload';
+
+process.env.GATSBY_DRUPAL_URL =
+ process.env.DRUPAL_EXTERNAL_URL || 'http://127.0.0.1:8888';
+
+/**
+ * @type {import('gatsby').GatsbyConfig['plugins']}
+ */
+export const plugins = [
+ {
+ resolve: '@amazeelabs/gatsby-source-silverback',
+ options: {
+ schema_configuration: './graphqlrc.yml',
+ directives: autoload,
+ drupal_url: process.env.DRUPAL_INTERNAL_URL || 'http://127.0.0.1:8888',
+ drupal_external_url:
+ // File requests are proxied through netlify.
+ process.env.NETLIFY_URL || 'http://127.0.0.1:8000',
+
+ graphql_path: '/graphql',
+ auth_key: 'cfdb0555111c0f8924cecab028b53474',
+ type_prefix: '',
+ },
+ },
+];
+
+/**
+ * @type {import('gatsby').GatsbyConfig}
+ */
+export default {
+ proxy: {
+ prefix: '/sites/default/files',
+ url: process.env.DRUPAL_EXTERNAL_URL || 'http://127.0.0.1:8888',
+ },
+ plugins,
+};
diff --git a/apps/cms/gatsby-node.mjs b/apps/cms/gatsby-node.mjs
new file mode 100644
index 000000000..c5957f4c6
--- /dev/null
+++ b/apps/cms/gatsby-node.mjs
@@ -0,0 +1,58 @@
+import { Locale } from '@custom/schema';
+import { resolve } from 'path';
+
+/**
+ *
+ * @type {import('gatsby').GatsbyNode['createPages']}
+ */
+export const createPages = async ({ actions }) => {
+ // Rewrite file requests to Drupal.
+ actions.createRedirect({
+ fromPath: '/sites/default/files/*',
+ toPath: `${process.env.GATSBY_DRUPAL_URL}/sites/default/files/:splat`,
+ statusCode: 200,
+ });
+
+ // Proxy Drupal GraphQL queries.
+ actions.createRedirect({
+ fromPath: '/graphql',
+ toPath: `${process.env.GATSBY_DRUPAL_URL}/graphql`,
+ statusCode: 200,
+ });
+
+ // Create the content hub page in each language.
+ Object.values(Locale).forEach((locale) => {
+ actions.createPage({
+ path: `/${locale}/content-hub`,
+ component: resolve(`./src/templates/content-hub.tsx`),
+ });
+ });
+
+ // Broken Gatsby links will attempt to load page-data.json files, which don't exist
+ // and also should not be piped into the strangler function. Thats why they
+ // are caught right here.
+ actions.createRedirect({
+ fromPath: '/page-data/*',
+ toPath: '/404',
+ statusCode: 404,
+ });
+
+ // Proxy Drupal webforms.
+ Object.values(Locale).forEach((locale) => {
+ actions.createRedirect({
+ fromPath: `/${locale}/form/*`,
+ toPath: `${process.env.GATSBY_DRUPAL_URL}/${locale}/form/:splat`,
+ statusCode: 200,
+ });
+ });
+
+ // Additionally proxy themes and modules as they can have additional
+ // non-aggregated assets.
+ ['themes', 'modules'].forEach((path) => {
+ actions.createRedirect({
+ fromPath: `/${path}/*`,
+ toPath: `${process.env.GATSBY_DRUPAL_URL}/${path}/:splat`,
+ statusCode: 200,
+ });
+ });
+};
diff --git a/apps/cms/package.json b/apps/cms/package.json
index 2067723be..40bcfda7c 100644
--- a/apps/cms/package.json
+++ b/apps/cms/package.json
@@ -28,6 +28,9 @@
"schema:test:update": "pnpm schema:test -u",
"import-translations": "pnpm drush scr scripts/translations-import.php"
},
+ "peerDependencies": {
+ "@amazeelabs/gatsby-source-silverback": "*"
+ },
"dependencies": {
"@custom/custom": "workspace:*",
"@custom/custom_heavy": "workspace:*",
diff --git a/apps/cms/scripts/create-lots-of-content/create-100-pages.php b/apps/cms/scripts/create-lots-of-content/create-100-pages.php
new file mode 100644
index 000000000..a204b13c9
--- /dev/null
+++ b/apps/cms/scripts/create-lots-of-content/create-100-pages.php
@@ -0,0 +1,99 @@
+writeData($imageData, "public://" . $random->machineName(32) . ".png");
+ }
+
+ // Prepare image media entities.
+ /** @var \Drupal\media\MediaInterface[] $media */
+ $media = [];
+ foreach ($images as $i => $image) {
+ $media[$i] = Media::create([
+ 'name' => $random->name(),
+ 'bundle' => 'image',
+ 'uid' => 1,
+ 'status' => TRUE,
+ 'field_media_image' => [
+ 'target_id' => $image->id(),
+ 'alt' => 'Alt text',
+ 'title' => 'Title text',
+ ],
+ ]);
+ $media[$i]->save();
+ }
+ $mediaIds = array_map(fn ($media) => $media->id(), $media);
+
+ // Create a page.
+ $title = $random->name();
+ $node = Node::create([
+ 'type' => 'page',
+ 'status' => TRUE,
+ 'uid' => 1,
+ 'title' => $title,
+ 'moderation_state' => 'published',
+ 'body' => [
+ 'value' => pageBody($mediaIds, FALSE),
+ 'format' => 'gutenberg',
+ 'summary' => '',
+ ],
+ ]);
+ $node->addTranslation('de', [
+ 'title' => $title . ' DE',
+ 'uid' => 1,
+ 'body' => [
+ 'value' => pageBody($mediaIds, TRUE),
+ 'format' => 'gutenberg',
+ 'summary' => '',
+ ],
+ ]);
+ $node->save();
+}
+
+function pageBody(array $mediaIds, bool $isGerman): string {
+ $suffix = $isGerman ? ' DE' : '';
+ return <<
+
+
+
+Some content$suffix
+
+
+
+
+
+Some content$suffix
+
+
+
+
+
+Some content$suffix
+
+
+
+
+
+
+
+
+EOT;
+}
+
+
diff --git a/apps/cms/scripts/create-lots-of-content/run.php b/apps/cms/scripts/create-lots-of-content/run.php
new file mode 100644
index 000000000..d284a93f5
--- /dev/null
+++ b/apps/cms/scripts/create-lots-of-content/run.php
@@ -0,0 +1,21 @@
+
+
Decap
-
-
\ No newline at end of file
+