diff --git a/modules/gterm/config/optional/views.view.group_terms.yml b/modules/gterm/config/optional/views.view.group_terms.yml
new file mode 100644
index 0000000..3052ab9
--- /dev/null
+++ b/modules/gterm/config/optional/views.view.group_terms.yml
@@ -0,0 +1,618 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - group
+    - taxonomy
+id: group_terms
+label: 'Group Terms'
+module: group
+description: ''
+tag: ''
+base_table: group_content_field_data
+base_field: id
+core: 8.x
+display:
+  default:
+    display_plugin: default
+    id: default
+    display_title: Master
+    position: 0
+    display_options:
+      access:
+        type: group_permission
+        options:
+          group_permission: 'access group_term overview'
+      cache:
+        type: tag
+        options: {  }
+      query:
+        type: views_query
+        options:
+          disable_sql_rewrite: false
+          distinct: false
+          replica: false
+          query_comment: ''
+          query_tags: {  }
+      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
+      pager:
+        type: full
+        options:
+          items_per_page: 50
+          offset: 0
+          id: 0
+          total_pages: null
+          tags:
+            previous: ‹‹
+            next: ››
+            first: '« First'
+            last: 'Last »'
+          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
+          quantity: 9
+      style:
+        type: table
+        options:
+          grouping: {  }
+          row_class: ''
+          default_row_class: true
+          override: true
+          sticky: true
+          caption: ''
+          summary: ''
+          description: ''
+          columns:
+            name: name
+            group_roles: group_roles
+            changed: changed
+            created: created
+            view_group_content: view_group_content
+            edit_group_content: edit_group_content
+            delete_group_content: delete_group_content
+            dropbutton: dropbutton
+          info:
+            name:
+              sortable: true
+              default_sort_order: asc
+              align: ''
+              separator: ''
+              empty_column: false
+              responsive: ''
+            group_roles:
+              align: ''
+              separator: ''
+              empty_column: false
+              responsive: ''
+            changed:
+              sortable: true
+              default_sort_order: asc
+              align: ''
+              separator: ''
+              empty_column: false
+              responsive: ''
+            created:
+              sortable: true
+              default_sort_order: asc
+              align: ''
+              separator: ''
+              empty_column: false
+              responsive: ''
+            view_group_content:
+              sortable: false
+              default_sort_order: asc
+              align: ''
+              separator: ''
+              empty_column: false
+              responsive: ''
+            edit_group_content:
+              sortable: false
+              default_sort_order: asc
+              align: ''
+              separator: ''
+              empty_column: false
+              responsive: ''
+            delete_group_content:
+              sortable: false
+              default_sort_order: asc
+              align: ''
+              separator: ''
+              empty_column: false
+              responsive: ''
+            dropbutton:
+              sortable: false
+              default_sort_order: asc
+              align: ''
+              separator: ''
+              empty_column: false
+              responsive: ''
+          default: '-1'
+          empty_table: true
+      row:
+        type: fields
+        options:
+          inline: {  }
+          separator: ''
+          hide_empty: false
+          default_field_elements: true
+      fields:
+        name:
+          id: name
+          table: taxonomy_term_field_data
+          field: name
+          relationship: gc__taxonomy_term
+          group_type: group
+          admin_label: ''
+          label: Name
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            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
+          convert_spaces: false
+          entity_type: taxonomy_term
+          entity_field: name
+          plugin_id: term_name
+        tid:
+          id: tid
+          table: taxonomy_term_field_data
+          field: tid
+          relationship: gc__taxonomy_term
+          group_type: group
+          admin_label: ''
+          label: 'Term ID'
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            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: number_integer
+          settings:
+            thousand_separator: ''
+            prefix_suffix: 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
+          entity_type: taxonomy_term
+          entity_field: tid
+          plugin_id: field
+        changed:
+          id: changed
+          table: taxonomy_term_field_data
+          field: changed
+          relationship: gc__taxonomy_term
+          group_type: group
+          admin_label: ''
+          label: 'Updated date'
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            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: timestamp
+          settings:
+            date_format: medium
+            custom_date_format: ''
+            timezone: ''
+          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
+          entity_type: taxonomy_term
+          entity_field: changed
+          plugin_id: field
+        edit_taxonomy_term:
+          id: edit_taxonomy_term
+          table: taxonomy_term_data
+          field: edit_taxonomy_term
+          relationship: gc__taxonomy_term
+          group_type: group
+          admin_label: ''
+          label: 'Link to edit Taxonomy term'
+          exclude: true
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            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
+          text: edit
+          entity_type: taxonomy_term
+          plugin_id: entity_link_edit
+        delete_taxonomy_term:
+          id: delete_taxonomy_term
+          table: taxonomy_term_data
+          field: delete_taxonomy_term
+          relationship: gc__taxonomy_term
+          group_type: group
+          admin_label: ''
+          label: 'Link to delete Taxonomy term'
+          exclude: true
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            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
+          text: delete
+          entity_type: taxonomy_term
+          plugin_id: entity_link_delete
+        dropbutton:
+          id: dropbutton
+          table: views
+          field: dropbutton
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: Operations
+          exclude: false
+          alter:
+            alter_text: false
+            text: ''
+            make_link: false
+            path: ''
+            absolute: false
+            external: false
+            replace_spaces: false
+            path_case: none
+            trim_whitespace: false
+            alt: ''
+            rel: ''
+            link_class: ''
+            prefix: ''
+            suffix: ''
+            target: ''
+            nl2br: false
+            max_length: 0
+            word_boundary: true
+            ellipsis: true
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
+            strip_tags: false
+            trim: false
+            preserve_tags: ''
+            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
+          fields:
+            view_taxonomy_term: view_taxonomy_term
+            edit_taxonomy_term: edit_taxonomy_term
+            delete_taxonomy_term: delete_taxonomy_term
+            name: '0'
+            tid: '0'
+            description__format: '0'
+          destination: true
+          plugin_id: dropbutton
+      filters: {  }
+      sorts: {  }
+      header: {  }
+      footer: {  }
+      empty:
+        area_text_custom:
+          id: area_text_custom
+          table: views
+          field: area_text_custom
+          relationship: none
+          group_type: group
+          admin_label: ''
+          empty: true
+          tokenize: false
+          content: 'No terms available.'
+          plugin_id: text_custom
+      relationships:
+        gc__taxonomy_term:
+          id: gc__taxonomy_term
+          table: group_content_field_data
+          field: gc__taxonomy_term
+          relationship: none
+          group_type: group
+          admin_label: 'Group content Taxonomy term'
+          required: true
+          group_content_plugins:
+            'group_term:gtdx_vocab': '0'
+            'group_term:store_tags': '0'
+            'group_term:tags': '0'
+            'group_term:time_period': '0'
+            'group_term:yc_vocab': '0'
+          entity_type: group_content
+          plugin_id: group_content_to_entity
+      arguments:
+        gid:
+          id: gid
+          table: group_content_field_data
+          field: gid
+          relationship: none
+          group_type: group
+          admin_label: ''
+          default_action: 'access denied'
+          exception:
+            value: all
+            title_enable: false
+            title: All
+          title_enable: true
+          title: '{{ arguments.gid|placeholder }} terms'
+          default_argument_type: fixed
+          default_argument_options:
+            argument: ''
+          default_argument_skip_url: false
+          summary_options:
+            base_path: ''
+            count: true
+            items_per_page: 25
+            override: false
+          summary:
+            sort_order: asc
+            number_of_records: 0
+            format: default_summary
+          specify_validation: false
+          validate:
+            type: none
+            fail: 'not found'
+          validate_options: {  }
+          break_phrase: false
+          not: false
+          entity_type: group_content
+          entity_field: gid
+          plugin_id: numeric
+      display_extenders: {  }
+      title: Terms
+    cache_metadata:
+      max-age: 0
+      contexts:
+        - group_membership.roles.permissions
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+      tags: {  }
+  page_1:
+    display_plugin: page
+    id: page_1
+    display_title: Page
+    position: 1
+    display_options:
+      display_extenders: {  }
+      path: group/%group/terms
+      menu:
+        type: tab
+        title: Terms
+        description: ''
+        expanded: false
+        parent: ''
+        weight: 20
+        context: '0'
+        menu_name: main
+    cache_metadata:
+      max-age: 0
+      contexts:
+        - group_membership.roles.permissions
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+      tags: {  }
diff --git a/modules/gterm/gterm.group.permissions.yml b/modules/gterm/gterm.group.permissions.yml
new file mode 100644
index 0000000..18dc088
--- /dev/null
+++ b/modules/gterm/gterm.group.permissions.yml
@@ -0,0 +1,3 @@
+access group_term overview:
+  title: 'Access group term overview'
+  description: 'Access the overview of all group terms, regardless of vocabulary'
diff --git a/modules/gterm/gterm.info.yml b/modules/gterm/gterm.info.yml
new file mode 100644
index 0000000..9a93bac
--- /dev/null
+++ b/modules/gterm/gterm.info.yml
@@ -0,0 +1,9 @@
+name: 'Group Term'
+description: 'Enables Group functionality for taxonomy terms'
+package: 'Group'
+type: 'module'
+version: 1.0
+core: '8.x'
+dependencies:
+  - 'taxonomy'
+  - 'group'
diff --git a/modules/gterm/gterm.module b/modules/gterm/gterm.module
new file mode 100644
index 0000000..775134e
--- /dev/null
+++ b/modules/gterm/gterm.module
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * @file
+ * Enables Group functionality for the Taxonomy module.
+ */
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\group\Entity\GroupContent;
+use Drupal\group\Entity\GroupContentType;
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function gterm_form_taxonomy_term_form_alter(&$form, $form_state) {
+  $form['actions']['submit']['#submit'][] = 'gterm_save_group_content';
+  //  $form['#submit'][] = 'gterm_save_group_content';
+}
+
+/**
+ * taxonomy_term_form
+ */
+function gterm_save_group_content($form, $form_state) {
+  // Group was added in \Drupal\gterm\Controller\GroupTaxonomyController::add().
+  if ($group = $form_state->get('group')) {
+    $term = $form_state->getFormObject()->getEntity();
+    $plugin_id = 'group_term:' . $term->vid->target_id;
+    $plugin = $group->getGroupType()->getContentPlugin($plugin_id);
+
+    $values = [
+      'type' => $plugin->getContentTypeConfigId(),
+      'gid' => $group->id(),
+      'entity_id' => $term->id(),
+    ];
+    GroupContent::create($values)->save();
+  }
+}
+
+/**
+ * Implements hook_taxonomy_term_access().
+ *
+ * When trying to view, update or delete a term it suffices to have the right to
+ * do so in only one group the node belongs to. If you wish to prevent any such
+ * action on your own terms, implement hook_taxonomy_term_access() in your module.
+ */
+function gterm_taxonomy_term_access(\Drupal\Core\Entity\EntityInterface $term, $op, \Drupal\Core\Session\AccountInterface $account) {
+  // We do not care about create access as we have our own wizard for that. Any
+  // operation aside from 'view', 'update' and 'delete' is also unsupported.
+  if (!in_array($op, ['view', 'update', 'delete'])) {
+    return AccessResult::neutral();
+  }
+
+  $plugin_id = 'group_term:' . $term->bundle();
+
+  // Only act if there are group content types for this vocabulary.
+  $group_content_types = GroupContentType::loadByContentPluginId($plugin_id);
+  if (empty($group_content_types)) {
+    return AccessResult::neutral();
+  }
+
+  // Load all the group content for this term.
+  $group_contents = \Drupal::entityTypeManager()
+    ->getStorage('group_content')
+    ->loadByProperties([
+      'type' => array_keys($group_content_types),
+      'entity_id' => $term->id(),
+    ]);
+
+  // If the term does not belong to any group, we have nothing to say.
+  if (empty($group_contents)) {
+    return AccessResult::neutral();
+  }
+
+  /** @var \Drupal\group\Entity\GroupInterface[] $groups */
+  $groups = [];
+  foreach ($group_contents as $group_content) {
+    /** @var \Drupal\group\Entity\GroupContentInterface $group_content */
+    $group = $group_content->getGroup();
+    $groups[$group->id()] = $group;
+  }
+
+  // From this point on you need group to allow you to perform the operation.
+  switch ($op) {
+    case 'view':
+      foreach ($groups as $group) {
+        if ($group->hasPermission("view ".$term->bundle()." term", $account)) {
+          return AccessResult::allowed();
+        }
+      }
+      break;
+
+    case 'update':
+    case 'delete':
+      foreach ($groups as $group) {
+        if ($group->hasPermission("edit ".$term->bundle()." term", $account)) {
+          return AccessResult::allowed();
+        }
+      }
+      break;
+  }
+
+  // Instead of outright forbidding access when no group granted it, we return
+  // a neutral access result to play nice with other modules. If the end result
+  // is still neutral, Drupal will deny access anyway.
+  return AccessResult::neutral();
+}
diff --git a/modules/gterm/gterm.routing.yml b/modules/gterm/gterm.routing.yml
new file mode 100644
index 0000000..8cfdcbb
--- /dev/null
+++ b/modules/gterm/gterm.routing.yml
@@ -0,0 +1,2 @@
+route_callbacks:
+  - '\Drupal\gterm\Routing\GroupTermRouteProvider::getRoutes'
diff --git a/modules/gterm/src/.DS_Store b/modules/gterm/src/.DS_Store
new file mode 100644
index 0000000..942e42c
Binary files /dev/null and b/modules/gterm/src/.DS_Store differ
diff --git a/modules/gterm/src/Controller/.DS_Store b/modules/gterm/src/Controller/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/modules/gterm/src/Controller/.DS_Store differ
diff --git a/modules/gterm/src/Controller/GroupTaxonomyController.php b/modules/gterm/src/Controller/GroupTaxonomyController.php
new file mode 100644
index 0000000..44fad51
--- /dev/null
+++ b/modules/gterm/src/Controller/GroupTaxonomyController.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Drupal\gterm\Controller;
+
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\group\Entity\GroupInterface;
+use Drupal\taxonomy\Entity\Term;
+use Drupal\taxonomy\VocabularyInterface;
+
+/**
+ * Returns responses for 'group_term' GroupContent routes.
+ */
+class GroupTaxonomyController extends ControllerBase {
+
+  /**
+   * Gets the form for adding a taxonomy term to a group.
+   *
+   * @param \Drupal\group\Entity\GroupInterface $group
+   *   The group to add the taxonomy term to.
+   * @param \Drupal\taxonomy\VocabularyInterface $taxonomy_vocabulary
+   *   The vocabulary to create a term in.
+   *
+   * @return array
+   *   The form array.
+   */
+  function addForm(GroupInterface $group, VocabularyInterface $taxonomy_vocabulary) {
+    \Drupal::logger('gterm')->notice("Called with vocab: " . $taxonomy_vocabulary->id());
+    // Re-use the default taxonomy_term entity form.
+    $term = Term::create(['vid' => $taxonomy_vocabulary->id()]);
+    return $this->entityFormBuilder()->getForm($term, 'default', ['group' => $group]);
+  }
+
+  /**
+   * Gets the title for the term addition form.
+   *
+   * @param \Drupal\group\Entity\GroupInterface $group
+   *   The group to add the taxonomy term to.
+   * @param \Drupal\taxonomy\VocabularyInterface $taxonomy_vocabulary
+   *   The vocabulary to create a term in.
+   *
+   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
+   *   The translated title for the form.
+   */
+  function addTitle(GroupInterface $group, VocabularyInterface $taxonomy_vocabulary) {
+    $t_args = ['%vocabulary' => $taxonomy_vocabulary->label(), '%group' => $group->label()];
+    return $this->t('Add %vocabulary term to %group', $t_args);
+  }
+
+}
diff --git a/modules/gterm/src/Plugin/.DS_Store b/modules/gterm/src/Plugin/.DS_Store
new file mode 100644
index 0000000..8d80809
Binary files /dev/null and b/modules/gterm/src/Plugin/.DS_Store differ
diff --git a/modules/gterm/src/Plugin/GroupContentEnabler/GroupTerm.php b/modules/gterm/src/Plugin/GroupContentEnabler/GroupTerm.php
new file mode 100644
index 0000000..a36e92b
--- /dev/null
+++ b/modules/gterm/src/Plugin/GroupContentEnabler/GroupTerm.php
@@ -0,0 +1,128 @@
+<?php
+
+namespace Drupal\gterm\Plugin\GroupContentEnabler;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Url;
+use Drupal\group\Access\GroupAccessResult;
+use Drupal\group\Entity\GroupInterface;
+use Drupal\group\Entity\GroupContentInterface;
+use Drupal\group\Plugin\GroupContentEnablerBase;
+use Drupal\taxonomy\Entity\Vocabulary;
+
+/**
+ * Provides a content enabler for taxonomy terms.
+ *
+ * @GroupContentEnabler(
+ *   id = "group_term",
+ *   label = @Translation("Group term"),
+ *   description = @Translation("Adds taxonomy terms to a group."),
+ *   entity_type_id = "taxonomy_term",
+ *   pretty_path_key = "term",
+ *   enforced = FALSE,
+ *   deriver = "Drupal\gterm\Plugin\GroupContentEnabler\GroupTermDeriver"
+ * )
+ */
+class GroupTerm extends GroupContentEnablerBase {
+
+  /**
+   * Retrieves the vocabulary this plugin supports.
+   *
+   * @return Vocabulary
+   *   The Vocab this plugin supports.
+   */
+  protected function getVocabulary() {
+    return Vocabulary::load($this->getEntityBundle());
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getGroupOperations(GroupInterface $group) {
+    $account = \Drupal::currentUser();
+    $vocabulary = $this->getEntityBundle();
+    $operations = [];
+
+    return $operations;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPermissions() {
+    $vocabulary = $this->getEntityBundle();
+    $vocabulary_arg = ['%vocabulary' => $this->getVocabulary()->label()];
+    $defaults = ['title_args' => $vocabulary_arg];
+
+    $permissions["create $vocabulary term"] = [
+      'title' => 'Create terms in %vocabulary',
+    ] + $defaults;
+
+    $permissions["view $vocabulary term"] = [
+      'title' => 'View terms in %vocabulary',
+    ] + $defaults;
+
+    $permissions["edit $vocabulary term"] = [
+      'title' => 'Edit terms in %vocabulary',
+    ] + $defaults;
+
+    $permissions["delete $vocabulary term"] = [
+      'title' => 'Delete terms in %vocabulary',
+    ] + $defaults;
+
+    return $permissions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createAccess(GroupInterface $group, AccountInterface $account) {
+    $vocabulary = $this->getEntityBundle();
+    return GroupAccessResult::allowedIfHasGroupPermission($group, $account, "create $vocabulary term");
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function viewAccess(GroupContentInterface $group_content, AccountInterface $account) {
+    $group = $group_content->getGroup();
+    $vocabulary = $this->getEntityBundle();
+    return GroupAccessResult::allowedIfHasGroupPermission($group, $account, "view $vocabulary term");
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function updateAccess(GroupContentInterface $group_content, AccountInterface $account) {
+    $group = $group_content->getGroup();
+    $vocabulary = $this->getEntityBundle();
+    return GroupAccessResult::allowedIfHasGroupPermission($group, $account, "edit $vocabulary term");
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function deleteAccess(GroupContentInterface $group_content, AccountInterface $account) {
+    $group = $group_content->getGroup();
+    $vocabulary = $this->getEntityBundle();
+    return GroupAccessResult::allowedIfHasGroupPermission($group, $account, "delete $vocabulary term");
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    $config = parent::defaultConfiguration();
+    $config['entity_cardinality'] = 1;
+    return $config;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function calculateDependencies() {
+    return ['module' => ['taxonomy']];
+  }
+
+}
diff --git a/modules/gterm/src/Plugin/GroupContentEnabler/GroupTermDeriver.php b/modules/gterm/src/Plugin/GroupContentEnabler/GroupTermDeriver.php
new file mode 100644
index 0000000..e4fcb0c
--- /dev/null
+++ b/modules/gterm/src/Plugin/GroupContentEnabler/GroupTermDeriver.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Drupal\gterm\Plugin\GroupContentEnabler;
+
+use Drupal\Component\Plugin\Derivative\DeriverBase;
+use Drupal\taxonomy\Entity\Vocabulary;
+
+class GroupTermDeriver extends DeriverBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinitions($base_plugin_definition) {
+    foreach (Vocabulary::loadMultiple() as $name => $vocabulary) {
+      $label = $vocabulary->label();
+
+      $this->derivatives[$name] = [
+        'entity_bundle' => $name,
+        'label' => t('Group term') . " ($label)",
+        'description' => t('Adds %type terms to groups.', ['%type' => $label]),
+      ] + $base_plugin_definition;
+    }
+    return $this->derivatives;
+  }
+
+}
diff --git a/modules/gterm/src/Routing/GroupTermRouteProvider.php b/modules/gterm/src/Routing/GroupTermRouteProvider.php
new file mode 100644
index 0000000..707c3f1
--- /dev/null
+++ b/modules/gterm/src/Routing/GroupTermRouteProvider.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Drupal\gterm\Routing;
+
+use Drupal\taxonomy\Entity\Vocabulary;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Provides routes for group_term group content.
+ */
+class GroupTermRouteProvider {
+
+  /**
+   * Provides the shared collection route for group term plugins.
+   */
+  public function getRoutes() {
+    $routes = $plugin_ids = $permissions_create = [];
+
+    foreach (Vocabulary::loadMultiple() as $name => $vocabulary) {
+      $plugin_id = "group_term:$name";
+
+      $plugin_ids[] = $plugin_id;
+      $permissions_create[] = "create $name term";
+    }
+
+    // If there are no vocabularies yet, we cannot have any plugin IDs and should
+    // therefore exit early because we cannot have any routes for them either.
+    if (empty($plugin_ids)) {
+      return $routes;
+    }
+
+    $routes['entity.group_content.group_term_add_page'] = new Route('group/{group}/term/create/{taxonomy_vocabulary}');
+    $routes['entity.group_content.group_term_add_page']
+      ->setDefaults([
+        '_title' => 'Create term',
+        '_controller' => '\Drupal\gterm\Controller\GroupTaxonomyController::addForm',
+        '_title_callback' => '\Drupal\gterm\Controller\GroupTaxonomyController::addTitle',
+        'create_mode' => TRUE,
+      ])
+      ->setRequirement('_group_permission', implode('+', $permissions_create))
+      ->setRequirement('_group_installed_content', implode('+', $plugin_ids))
+      ->setOption('_group_operation_route', TRUE);
+
+    return $routes;
+  }
+
+}
