diff --git a/modules/ui_patterns_field_group/src/Plugin/UiPatterns/Source/FieldgroupSource.php b/modules/ui_patterns_field_group/src/Plugin/UiPatterns/Source/FieldgroupSource.php
new file mode 100644
index 00000000..b7d557a4
--- /dev/null
+++ b/modules/ui_patterns_field_group/src/Plugin/UiPatterns/Source/FieldgroupSource.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace Drupal\ui_patterns_field_group\Plugin\UiPatterns\Source;
+
+use Drupal\ui_patterns\Plugin\PatternSourceBase;
+
+/**
+ * Defines Fields API pattern source plugin.
+ *
+ * @UiPatternsSource(
+ *   id = "fieldgroup",
+ *   label = @Translation("Fieldgroups"),
+ *   provider = "field_group",
+ *   tags = {
+ *     "entity_display"
+ *   }
+ * )
+ */
+class FieldgroupSource extends PatternSourceBase {
+
+  /**
+   * Return list of source fields.
+   *
+   * @return \Drupal\ui_patterns\Definition\PatternSourceField[]
+   *   List of source fields.
+   *
+   * @throws \Drupal\Component\Plugin\Exception\PluginException
+   */
+  public function getSourceFields() {
+    $sources = [];
+    $entity_type_id = $this->getContextProperty('entity_type');
+    $bundle = $this->getContextProperty('entity_bundle');
+    $view_mode = $this->getContextProperty('entity_view_mode');
+
+    $groups = field_group_info_groups($entity_type_id, $bundle, 'view', $view_mode);
+
+    foreach ($groups as $group_name => $group) {
+      if (empty($this->getContextProperty('limit')) || in_array($group_name, $this->getContextProperty('limit'))) {
+        $sources[] = $this->getSourceField($group_name, $group->label);
+      }
+    }
+    $sources[] = $this->getSourceField('_label', 'Group label');
+
+    return $sources;
+  }
+
+}
diff --git a/modules/ui_patterns_field_group/src/Plugin/field_group/FieldGroupFormatter/PatternFormatter.php b/modules/ui_patterns_field_group/src/Plugin/field_group/FieldGroupFormatter/PatternFormatter.php
index 20970b0c..05dc508c 100644
--- a/modules/ui_patterns_field_group/src/Plugin/field_group/FieldGroupFormatter/PatternFormatter.php
+++ b/modules/ui_patterns_field_group/src/Plugin/field_group/FieldGroupFormatter/PatternFormatter.php
@@ -98,18 +98,75 @@ public static function create(ContainerInterface $container, array $configuratio
    * {@inheritdoc}
    */
   public function preRender(&$element, $rendering_object) {
+    $this->preRenderGroup($element, $this->group->group_name, $rendering_object);
+  }
 
-    $fields = [];
-    $mapping = $this->getSetting('pattern_mapping');
-    foreach ($mapping as $field) {
-      $fields[$field['destination']][] = $element[$field['source']];
+  /**
+   * Recursive method to build the fieldgroup content.
+   *
+   * This method checks if one of the fieldgroup items are a fieldgroup pattern
+   * themselve. If so, we must build its configuration again and check if this
+   * fieldgroup doesn't have fieldgroup pattern items itself. (And the story
+   * keeps going until there are no more people alive on earth).
+   *
+   * @param array $element
+   *   Renderable array of the outputed content.
+   * @param array $group_settings
+   *   Pattern config settings.
+   *
+   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
+   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
+   */
+  protected function preRenderGroup(array &$element, $group_name, array $rendering_object) {
+    // Do not pre render the group twice.
+    if (!empty($element['#pattern_pre_rendered'])) {
+      return;
+    }
+
+    // Load field group settings.
+    $group = $rendering_object['#fieldgroups'][$group_name];
+
+    // Handle groups managed by UI Patterns recursively.
+    if ($group->format_type == 'pattern_formatter') {
+      // Move content into their fields.
+      foreach ($group->format_settings['pattern_mapping'] as $field) {
+        if ($field['plugin'] == 'fieldgroup') {
+          if ($field['source'] === '_label') {
+            $element[$field['source']] = ['#markup' => $group->label];
+          }
+          else {
+            $this->preRenderGroup($element[$field['source']], $field['source'], $rendering_object);
+          }
+        }
+        $element['#fields'][$field['destination']][$field['source']] = $element[$field['source']];
+      }
+
+      // Add render array metadata.
+      $this->addRenderContext($element, $group->format_settings);
+    }
+    // Fallback to default pre_rendering for fieldgroups not managed by UI
+    // Patterns.
+    else {
+      field_group_pre_render($element, $group, $rendering_object);
+    }
+  }
+
+  /**
+   * Helper to build the context expected to render the fieldgroup pattern.
+   *
+   * @param array $element
+   *   Field data.
+   * @param array $format_settings
+   *   The pattern format settings.
+   */
+  protected function addRenderContext(array &$element, array $format_settings) {
+    $element['#id'] = $format_settings['pattern'];
+    if (!empty($format_settings['pattern_variant'])) {
+      $element['#variant'] = $format_settings['pattern_variant'];
     }
 
     $element['#type'] = 'pattern';
-    $element['#id'] = $this->getSetting('pattern');
-    $element['#fields'] = $fields;
     $element['#multiple_sources'] = TRUE;
-    $element['#variant'] = $this->getSetting('pattern_variant');
 
     // Allow default context values to not override those exposed elsewhere.
     $element['#context']['type'] = 'field_group';
@@ -119,17 +176,13 @@ public function preRender(&$element, $rendering_object) {
     $element['#context']['view_mode'] = $this->configuration['group']->mode;
 
     // Pass current entity to pattern context, if any.
-    $element['#context']['entity'] = $this->entityFinder->findEntityFromFields($element['#fields']);
-  }
+    if (!empty($element['#fields'])) {
+      $element['#context']['entity'] = $this->entityFinder->findEntityFromFields($element['#fields']);
+    }
 
-  /**
-   * Get field group name.
-   *
-   * @return string
-   *   Field group name.
-   */
-  protected function getFieldGroupName() {
-    return $this->configuration['group']->group_name;
+    // Nested groups can be rendered in any order so mark this one as done to
+    // prevent issues.
+    $element['#pattern_pre_rendered'] = TRUE;
   }
 
   /**
@@ -144,6 +197,7 @@ public function settingsForm() {
       $context = [
         'entity_type' => $this->configuration['group']->entity_type,
         'entity_bundle' => $this->configuration['group']->bundle,
+        'entity_view_mode' => $this->configuration['group']->mode,
         'limit' => $this->configuration['group']->children,
       ];