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 00000000..3052ab9a
--- /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 00000000..18dc0885
--- /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 00000000..9a93bacf
--- /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.links.action.yml b/modules/gterm/gterm.links.action.yml
new file mode 100644
index 00000000..b0d9d8d9
--- /dev/null
+++ b/modules/gterm/gterm.links.action.yml
@@ -0,0 +1,5 @@
+entity.taxonomy_term.group_add_form:
+  route_name: entity.taxonomy_term.group_add_form
+  title: 'Add term to group'
+  appears_on:
+    - entity.taxonomy_vocabulary.group_overview_form
diff --git a/modules/gterm/gterm.module b/modules/gterm/gterm.module
new file mode 100644
index 00000000..0de7f501
--- /dev/null
+++ b/modules/gterm/gterm.module
@@ -0,0 +1,105 @@
+<?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_node_access().
+ *
+ * When trying to view, update or delete a node 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_node_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 node type.
+  $group_content_types = GroupContentType::loadByContentPluginId($plugin_id);
+  if (empty($group_content_types)) {
+    return AccessResult::neutral();
+  }
+
+  // Load all the group content for this node.
+  $group_contents = \Drupal::entityTypeManager()
+    ->getStorage('group_content')
+    ->loadByProperties([
+      'type' => array_keys($group_content_types),
+      'entity_id' => $term->id(),
+    ]);
+
+  // If the node 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 requested
+  // operation. If you are not granted access for a node belonging to a group,
+  // you should be denied access instead.
+  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;
+  }
+
+  return AccessResult::forbidden();
+}
\ No newline at end of file
diff --git a/modules/gterm/gterm.routing.yml b/modules/gterm/gterm.routing.yml
new file mode 100644
index 00000000..1b72f063
--- /dev/null
+++ b/modules/gterm/gterm.routing.yml
@@ -0,0 +1,19 @@
+entity.taxonomy_vocabulary.group_overview_form:
+  path: '/group/{group}/vocabulary/{taxonomy_vocabulary}'
+  defaults:
+    _form: 'Drupal\gterm\Form\GroupOverviewTerms'
+    _title_callback: 'Drupal\gterm\Form\GroupOverviewTerms::title'
+  requirements:
+    _group_term_admin_access: 'TRUE'
+  options:
+    _group_operation_route: 'TRUE'
+
+entity.taxonomy_term.group_add_form:
+  path: '/group/{group}/vocabulary/manage/{taxonomy_vocabulary}/add'
+  defaults:
+    _controller: '\Drupal\gterm\Controller\GroupTaxonomyController::addForm'
+    _title_callback: '\Drupal\gterm\Controller\GroupTaxonomyController::addTitle'
+  requirements:
+    _group_term_admin_access: 'TRUE'
+  options:
+    _group_operation_route: 'TRUE'
\ No newline at end of file
diff --git a/modules/gterm/gterm.services.yml b/modules/gterm/gterm.services.yml
new file mode 100644
index 00000000..205b6ca5
--- /dev/null
+++ b/modules/gterm/gterm.services.yml
@@ -0,0 +1,5 @@
+services:
+  access_check.gterm.admin:
+    class: Drupal\gterm\Access\GroupTermAdminAccessCheck
+    tags:
+      - { name: access_check, applies_to: _group_term_admin_access }
diff --git a/modules/gterm/src/Access/GroupTermAdminAccessCheck.php b/modules/gterm/src/Access/GroupTermAdminAccessCheck.php
new file mode 100644
index 00000000..a25d8d18
--- /dev/null
+++ b/modules/gterm/src/Access/GroupTermAdminAccessCheck.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Drupal\gterm\Access;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Routing\Access\AccessInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\group\Entity\GroupInterface;
+use Drupal\taxonomy\VocabularyInterface;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Determines access to group taxonomy forms.
+ */
+class GroupTermAdminAccessCheck implements AccessInterface {
+
+  /**
+   * Checks access to the group taxonomy pages.
+   *
+   * @param \Symfony\Component\Routing\Route $route
+   *   The route to check against.
+   * @param \Drupal\Core\Session\AccountInterface $account
+   *   The currently logged in account.
+   * @param \Drupal\group\Entity\GroupInterface $group
+   *   The group with which to relate the term.
+   * @param \Drupal\taxonomy\VocabularyInterface $taxonomy_vocabulary
+   *   The vocabulary in which to create the term.
+   *
+   * @return \Drupal\Core\Access\AccessResultInterface
+   *   The access result.
+   */
+  public function access(Route $route, AccountInterface $account, GroupInterface $group, VocabularyInterface $taxonomy_vocabulary) {
+    $needs_access = $route->getRequirement('_group_term_admin_access') === 'TRUE';
+    $vocabulary = $taxonomy_vocabulary->id();
+
+    // We can only get the group content type ID if the plugin is installed.
+    if (!$group->getGroupType()->hasContentPlugin("group_term:$vocabulary")) {
+      return AccessResult::neutral();
+    }
+
+    // Determine whether the user can manipulate terms of the provided type.
+    $access = FALSE;
+    foreach (['create', 'edit', 'delete'] as $op) {
+      $permission = "$op $vocabulary term";
+      $access = $access || $group->hasPermission($permission, $account);
+    }
+
+    // Only allow access if the user can manipulate group terms of the provided
+    // type or if he doesn't need access to do so.
+    return AccessResult::allowedIf($access xor !$needs_access);
+  }
+
+}
diff --git a/modules/gterm/src/Controller/GroupTaxonomyController.php b/modules/gterm/src/Controller/GroupTaxonomyController.php
new file mode 100644
index 00000000..772297b3
--- /dev/null
+++ b/modules/gterm/src/Controller/GroupTaxonomyController.php
@@ -0,0 +1,48 @@
+<?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) {
+    // 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/Form/GroupOverviewTerms.php b/modules/gterm/src/Form/GroupOverviewTerms.php
new file mode 100644
index 00000000..b94beb8a
--- /dev/null
+++ b/modules/gterm/src/Form/GroupOverviewTerms.php
@@ -0,0 +1,251 @@
+<?php
+
+namespace Drupal\gterm\Form;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\group\Entity\GroupContentType;
+use Drupal\group\Entity\GroupInterface;
+use Drupal\group\Entity\GroupContent;
+use Drupal\taxonomy\Form\OverviewTerms;
+use Drupal\taxonomy\VocabularyInterface;
+
+/**
+ * Provides a group's terms overview form for one vocabulary.
+ */
+class GroupOverviewTerms extends OverviewTerms {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'group_taxonomy_overview_terms';
+  }
+
+  /**
+   * Form constructor.
+   *
+   * Display a tree of all the terms in a vocabulary & group, with options to
+   * edit each one. The form is made drag and drop by the theme function.
+   *
+   * @param array $form
+   *   An associative array containing the structure of the form.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The current state of the form.
+   * @param \Drupal\group\Entity\GroupInterface $group
+   *   The group whose terms we are viewing
+   * @param \Drupal\taxonomy\VocabularyInterface $taxonomy_vocabulary
+   *   The vocabulary to display the overview form for.
+   *
+   * @return array
+   *   The form structure.
+   *
+   * @note most of this is copied from the parent.
+   */
+  public function buildForm(array $form, FormStateInterface $form_state, GroupInterface $group = NULL, VocabularyInterface $taxonomy_vocabulary = NULL) {
+    $current_page = $tree = [];
+    $delta = 0;
+    $parent_fields = FALSE;
+    $form_state->set(['taxonomy', 'vocabulary'], $taxonomy_vocabulary);
+    $groupContents = $group->getContent('group_term:'.$taxonomy_vocabulary->id());
+
+    foreach ($groupContents as $groupContent) {
+      $tree[] = $groupContent->getEntity();
+    }
+
+    $tree_index = 0;
+    do {
+      // In case this tree is completely empty.
+      if (empty($tree[$tree_index])) {
+        break;
+      }
+      $delta++;
+
+      // Do not let a term start the page that is not at the root.
+      $term = $tree[$tree_index];
+      if (isset($term->depth) && ($term->depth > 0)) {
+        while ($pterm = $tree[--$tree_index]) {
+          $before_entries--;
+          if ($pterm->depth == 0) {
+            $tree_index--;
+            // Jump back to the start of the root level parent.
+            continue 2;
+          }
+        }
+      }
+      $term_deltas[$term->id()] = isset($term_deltas[$term->id()]) ? $term_deltas[$term->id()] + 1 : 0;
+      $key = 'tid:' . $term->id() . ':' . $term_deltas[$term->id()];
+      $current_page[$key] = $term;
+    } while (isset($tree[++$tree_index]));
+
+    // If this form was already submitted once, it's probably hit a validation
+    // error. Ensure the form is rebuilt in the same order as the user
+    // submitted.
+    $user_input = $form_state->getUserInput();
+    if (!empty($user_input)) {
+      // Get the POST order.
+      $order = array_flip(array_keys($user_input['terms']));
+      // Update our form with the new order.
+      $current_page = array_merge($order, $current_page);
+      debug($current_page);
+      foreach ($current_page as $tid => $term) {
+        // Verify this is a term for the current page and set at the current
+        // depth.
+        if (is_array($user_input['terms'][$tid]) && is_numeric($user_input['terms'][$tid]['term']['tid'])) {
+          $current_page[$tid]->depth = $user_input['terms'][$tid]['term']['depth'];
+        }
+        else {
+          unset($current_page[$tid]);
+        }
+      }
+    }
+    $errors = $form_state->getErrors();
+    $destination = $this->getDestinationArray();
+    $row_position = 0;
+    // Build the actual form.
+    $form['terms'] = array(
+      '#type' => 'table',
+      '#header' => array($this->t('Name'), $this->t('Weight'), $this->t('Operations')),
+      '#empty' => $this->t(
+        'No terms available. <a href=":link">Add term</a>.',
+        [
+          ':link' => $this->url(
+            'entity.taxonomy_term.group_add_form',
+            ['taxonomy_vocabulary' => $taxonomy_vocabulary->id(), 'group' => $group->id()]
+          )
+        ]
+      ),
+      '#attributes' => array(
+        'id' => 'taxonomy',
+      ),
+    );
+
+
+     foreach ($current_page as $key => $term) {
+      /** @var $term \Drupal\Core\Entity\EntityInterface */
+      $form['terms'][$key]['#term'] = $term;
+      $indentation = array();
+      if (isset($term->depth) && $term->depth > 0) {
+        $indentation = array(
+          '#theme' => 'indentation',
+          '#size' => $term->depth,
+        );
+      }
+      $form['terms'][$key]['term'] = array(
+        '#prefix' => !empty($indentation) ? drupal_render($indentation) : '',
+        '#type' => 'link',
+        '#title' => $term->getName(),
+        '#url' => $term->urlInfo(),
+      );
+      if ($taxonomy_vocabulary->getHierarchy() != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1) {
+        $parent_fields = TRUE;
+        $form['terms'][$key]['term']['tid'] = array(
+          '#type' => 'hidden',
+          '#value' => $term->id(),
+          '#attributes' => array(
+            'class' => array('term-id'),
+          ),
+        );
+        $form['terms'][$key]['term']['parent'] = array(
+          '#type' => 'hidden',
+          // Yes, default_value on a hidden. It needs to be changeable by the
+          // javascript.
+          '#default_value' => $term->parents[0],
+          '#attributes' => array(
+            'class' => array('term-parent'),
+          ),
+        );
+        $form['terms'][$key]['term']['depth'] = array(
+          '#type' => 'hidden',
+          // Same as above, the depth is modified by javascript, so it's a
+          // default_value.
+          '#default_value' => $term->depth,
+          '#attributes' => array(
+            'class' => array('term-depth'),
+          ),
+        );
+      }
+      $form['terms'][$key]['weight'] = array(
+        '#type' => 'weight',
+        '#delta' => $delta,
+        '#title' => $this->t('Weight for added term'),
+        '#title_display' => 'invisible',
+        '#default_value' => $term->getWeight(),
+        '#attributes' => array(
+          'class' => array('term-weight'),
+        ),
+      );
+      $operations = array(
+        'edit' => array(
+          'title' => $this->t('Edit'),
+          'query' => $destination,
+          'url' => $term->urlInfo('edit-form'),
+        ),
+        'delete' => array(
+          'title' => $this->t('Delete'),
+          'query' => $destination,
+          'url' => $term->urlInfo('delete-form'),
+        ),
+      );
+      if ($this->moduleHandler->moduleExists('content_translation') && content_translation_translate_access($term)->isAllowed()) {
+        $operations['translate'] = array(
+          'title' => $this->t('Translate'),
+          'query' => $destination,
+          'url' => $term->urlInfo('drupal:content-translation-overview'),
+        );
+      }
+      $form['terms'][$key]['operations'] = array(
+        '#type' => 'operations',
+        '#links' => $operations,
+      );
+
+      $form['terms'][$key]['#attributes']['class'] = array();
+      if ($parent_fields) {
+        $form['terms'][$key]['#attributes']['class'][] = 'draggable';
+      }
+
+      // Add an error class if this row contains a form error.
+      foreach ($errors as $error_key => $error) {
+        if (strpos($error_key, $key) === 0) {
+          $form['terms'][$key]['#attributes']['class'][] = 'error';
+        }
+      }
+      $row_position++;
+    }
+
+    if ($parent_fields) {
+      $form['terms']['#tabledrag'][] = array(
+        'action' => 'match',
+        'relationship' => 'parent',
+        'group' => 'term-parent',
+        'subgroup' => 'term-parent',
+        'source' => 'term-id',
+        'hidden' => FALSE,
+      );
+      $form['terms']['#tabledrag'][] = array(
+        'action' => 'depth',
+        'relationship' => 'group',
+        'group' => 'term-depth',
+        'hidden' => FALSE,
+      );
+      $form['terms']['#attached']['library'][] = 'taxonomy/drupal.taxonomy';
+    }
+    $form['terms']['#tabledrag'][] = array(
+      'action' => 'order',
+      'relationship' => 'sibling',
+      'group' => 'term-weight',
+    );
+
+    if ($taxonomy_vocabulary->getHierarchy() != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1) {
+      $form['actions'] = array('#type' => 'actions', '#tree' => FALSE);
+      $form['actions']['submit'] = array(
+        '#type' => 'submit',
+        '#value' => $this->t('Save'),
+        '#button_type' => 'primary',
+      );
+    }
+    $form['#title'] = $this->t('Terms in %vocabulary', ['%vocabulary' => $taxonomy_vocabulary->label()]);
+
+    return $form;
+  }
+
+}
diff --git a/modules/gterm/src/Plugin/GroupContentEnabler/GroupTerm.php b/modules/gterm/src/Plugin/GroupContentEnabler/GroupTerm.php
new file mode 100644
index 00000000..52f6a823
--- /dev/null
+++ b/modules/gterm/src/Plugin/GroupContentEnabler/GroupTerm.php
@@ -0,0 +1,137 @@
+<?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 = [];
+
+    if ($group->hasPermission("create $vocabulary term", $account) || $group->hasPermission("edit $vocabulary term", $account) || $group->hasPermission("delete $vocabulary term", $account)) {
+      $route_params = ['group' => $group->id(), 'taxonomy_vocabulary' => $this->getEntityBundle()];
+      $operations["gterm-admin-$vocabulary"] = [
+        'title' => $this->t('Administer @type terms', ['@type' => $this->getVocabulary()->label()]),
+        'url' => new Url('entity.taxonomy_vocabulary.group_overview_form', $route_params),
+        'weight' => 50,
+      ];
+    }
+
+    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 00000000..e4fcb0cf
--- /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;
+  }
+
+}
