diff --git a/field_group.module b/field_group.module
index 3254e51..227eade 100755
--- a/field_group.module
+++ b/field_group.module
@@ -167,6 +167,43 @@ function field_group_theme() {
 }
 
 /**
+ * Implements hook_theme_registry_alter().
+ */
+function field_group_theme_registry_alter(&$theme_registry) {
+
+  // Inject field_group_build_entity_groups in all entity theming functions.
+  $entity_info = entity_get_info();
+  $entities = array();
+  foreach ($entity_info as $entity => $info) {
+    if (isset($entity_info[$entity]['fieldable']) && $entity_info[$entity]['fieldable']) {
+      // User uses user_profile for theming.
+      if ($entity == 'user') $entity = 'user_profile';
+      $entities[] = $entity;
+    }
+  }
+
+  // Support for File Entity.
+  if (isset($theme_registry['file_entity'])) {
+    $entities[] = 'file_entity';
+  }
+
+  // Support for Entity API.
+  if (isset($theme_registry['entity'])) {
+    $entities[] = 'entity';
+  }
+
+  foreach ($entities as $entity) {
+    $theme_registry[$entity]['preprocess functions'][] = 'field_group_build_entity_groups';
+    // DS support, make sure it comes after field_group.
+    if ($key = array_search('ds_entity_variables', $theme_registry[$entity]['preprocess functions'])) {
+      unset($theme_registry[$entity]['preprocess functions'][$key]);
+      $theme_registry[$entity]['preprocess functions'][] = 'ds_entity_variables';
+    }
+  }
+
+}
+
+/**
  * Implements hook_field_attach_delete_bundle().
  *
  * @param String $entity_type
@@ -195,6 +232,7 @@ function field_group_field_attach_delete_bundle($entity_type, $bundle) {
 function field_group_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
   $form['#attached']['css'][] = drupal_get_path('module', 'field_group') . '/field_group.field_ui.css';
   field_group_attach_groups($form, 'form', $form_state);
+  $form['#pre_render'][] = 'field_group_form_pre_render';
 }
 
 /**
@@ -1175,6 +1213,7 @@ function field_group_field_extra_fields() {
 
 /**
  * Implements hook_field_attach_rename_bundle().
+ * TODO: also update identifier
  */
 function field_group_field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) {
   db_query('UPDATE {field_group} SET bundle = :bundle WHERE bundle = :old_bundle AND entity_type = :entity_type', array(
@@ -1659,45 +1698,59 @@ function field_group_attach_groups(&$element, $view_mode, $form_state = array())
   }
   $element['#group_children'] = $group_children;
 
-  // Add a pre render callback.
-  // This is needed since process seems too early for the front view modes.
-  // This is main bottleneck in field_group. By using this, we can't process
-  // our added groups in a normal way, resulting in early creation of vertical
-  // tabs, horizontal tabs and multipages.
-  $element['#pre_render'][] = 'field_group_build_pre_render';
+}
 
+/**
+ * Pre render callback for rendering groups.
+ * @see field_group_field_attach_form
+ * @param $element Form that is beïng rendered.
+ */
+function field_group_form_pre_render(&$element) {
+  return field_group_build_entity_groups($element, 'form');
 }
 
 /**
- * Process/ Pre-render callback.
+ * Preprocess/ Pre-render callback.
  *
- * Depending on whether it is a form build or content build.
- * Form api go through more than a regular build. #process is
- * needed here, where #pre_render is ideal for the regular array.
- * @see field_group_attach_groups()
+ * @see field_group_form_pre_render()
+ * @see field_group_theme_registry_alter
  * @see field_group_fields_nest()
- * @param $element Form element
+ * @param $vars preprocess vars or form element
+ * @param $type The type of object beïng rendered
  * @return $element Array with re-arranged fields in forms.
  */
-function field_group_build_pre_render($element) {
+function field_group_build_entity_groups(&$vars, $type) {
 
-  // Skip the nesting and field_group functions if no fieldgroups.
-  // This could be because you don't see them in the UI or programmatically.
-  if (empty($element['#fieldgroups'])) {
-    return $element;
+  if ($type == 'form') {
+    $element = &$vars;
+    $nest_vars = NULL;
+  }
+  else {
+    $element = &$vars['elements'];
+    $nest_vars = &$vars;
   }
 
-  // Merge our #fieldgroups with #groups to avoid conflicts on fieldset types.
-  $element['#groups'] = array_merge($element['#groups'], $element['#fieldgroups']);
+  if (!isset($element['#groups'])) {
+    return $element;
+  }
 
   // Nest the fields in the corresponding field groups.
-  field_group_fields_nest($element);
+  field_group_fields_nest($element, $nest_vars);
 
   // Allow others to alter the pre_rendered build.
   drupal_alter('field_group_build_pre_render', $element);
 
-  return $element;
+  // Return the element on forms.
+  if ($type == 'form') {
+    return $element;
+  }
 
+  // Put groups inside content if we are rendering an entity_view.
+  foreach ($element['#groups'] as $group) {
+    if (!empty($element[$group->group_name])) {
+      $vars['content'][$group->group_name] = $element[$group->group_name];
+    }
+  }
 }
 
 /**
@@ -1709,8 +1762,10 @@ function field_group_build_pre_render($element) {
  * stash fields and groups in it while we go deeper in the array.
  * @param Array $element
  *   The current element to analyse for grouping.
+ * @param Array $vars
+ *   Rendering vars from the entity beïng viewed.
  */
-function field_group_fields_nest(&$element) {
+function field_group_fields_nest(&$element, $vars = NULL) {
 
   // Create all groups and keep a flat list of references to these groups.
   $group_references = array();
@@ -1723,16 +1778,39 @@ function field_group_fields_nest(&$element) {
   // direct access as we don't know where in the root_element hierarchy the
   // parent currently is situated.
   foreach ($element['#group_children'] as $child_name => $parent_name) {
-    // Block denied fields (#access) before they are put in groups.
-    // Fields (not groups) that don't have children (like field_permissions) are removed
-    // in field_group_field_group_build_pre_render_alter.
-    if (isset($element[$child_name]) && (!isset($element[$child_name]['#access']) || $element[$child_name]['#access'])) {
+
+    // Entity beïng viewed
+    if ($vars) {
+      // If not a group, check vars['content'] for empty field.
+      if (!isset($element['#groups'][$child_name])) {
+        if (isset($vars['content'][$child_name])) {
+          $group_references[$parent_name][$child_name] = $vars['content'][$child_name];
+          unset($vars['content'][$child_name]);
+        }
+      }
       // If this is a group, we have to use a reference to keep the reference
       // list intact (but if it is a field we don't mind).
-      $group_references[$parent_name][$child_name] = &$element[$child_name];
+      else {
+        $group_references[$parent_name][$child_name] = &$element[$child_name];
+        unset($element[$child_name]);
+      }
     }
-    // The child has been copied to its parent: remove it from the root element.
-    unset($element[$child_name]);
+    // Form beïng viewed
+    else {
+
+      // Block denied fields (#access) before they are put in groups.
+      // Fields (not groups) that don't have children (like field_permissions) are removed
+      // in field_group_field_group_build_pre_render_alter.
+      if (isset($element[$child_name]) && (!isset($element[$child_name]['#access']) || $element[$child_name]['#access'])) {
+        // If this is a group, we have to use a reference to keep the reference
+        // list intact (but if it is a field we don't mind).
+        $group_references[$parent_name][$child_name] = &$element[$child_name];
+      }
+
+      // The child has been copied to its parent: remove it from the root element.
+      unset($element[$child_name]);
+    }
+
   }
 
   // Bring extra element wrappers to achieve a grouping of fields.
