diff --git a/gui/src/components/archive/MetainfoBrowser.js b/gui/src/components/archive/MetainfoBrowser.js
index 4f255f94d72e4823d99baef548cdb6e41625a96a..63eaebed5f321ebf1bca40490d9699fac8e45bd9 100644
--- a/gui/src/components/archive/MetainfoBrowser.js
+++ b/gui/src/components/archive/MetainfoBrowser.js
@@ -68,6 +68,8 @@ If you bookmark this page, you can save the definition represented by the highli
 To learn more about the meta-info, visit the [meta-info documentation](${appBase}/docs/metainfo.html).
 `
 
+const showInnerSectionDefinitions = false
+
 function defCompare(a, b) {
   return a.name.localeCompare(b.name)
 }
@@ -328,7 +330,7 @@ class CategoryDefAdaptor extends MetainfoAdaptor {
   }
 }
 
-function SectionDef({def}) {
+function SectionDefContent({def}) {
   const config = useRecoilValue(configState)
   const metainfoConfig = useRecoilValue(metainfoConfigState)
   const filter = def.extends_base_section ? () => true : def => {
@@ -347,8 +349,7 @@ function SectionDef({def}) {
     return false
   }
 
-  return <Content style={{backgroundColor: 'grey'}}>
-    <Definition def={def} kindLabel="section definition" />
+  return <React.Fragment>
     <DefinitionProperties def={def} />
     {def.base_sections.length > 0 &&
       <Compartment title="base section">
@@ -394,7 +395,7 @@ function SectionDef({def}) {
         })
       }
     </Compartment>
-    <Compartment title="inner section definitions">
+    {showInnerSectionDefinitions && <Compartment title="inner section definitions">
       {def.inner_section_definitions.filter(filter)
         .map(innerSectionDef => {
           const key = `innerSectionDef@${innerSectionDef.name}`
@@ -411,8 +412,18 @@ function SectionDef({def}) {
           </Item>
         })
       }
-    </Compartment>
+    </Compartment>}
     <DefinitionDetails def={def} />
+  </React.Fragment>
+}
+SectionDefContent.propTypes = ({
+  def: PropTypes.object
+})
+
+function SectionDef({def}) {
+  return <Content style={{backgroundColor: 'grey'}}>
+    <Definition def={def} kindLabel="section definition" />
+    <SectionDefContent def={def} />
   </Content>
 }
 SectionDef.propTypes = ({
@@ -420,14 +431,13 @@ SectionDef.propTypes = ({
 })
 
 function SubSectionDef({def}) {
+  const sectionDef = resolveRef(def.sub_section)
   return <React.Fragment>
     <Content>
-      <Definition def={def} kindLabel="sub section definition"/>
-      <DefinitionProperties def={def}>
-        {def.repeats && <Typography><b>repeats</b>:&nbsp;true</Typography>}
-      </DefinitionProperties>
+      <Title def={def} isDefinition kindLabel="sub section definition" />
+      <DefinitionDocs def={sectionDef} />
+      <SectionDefContent def={sectionDef} />
     </Content>
-    <SectionDef def={resolveRef(def.sub_section)} />
   </React.Fragment>
 }
 SubSectionDef.propTypes = ({
@@ -482,9 +492,8 @@ QuantityDef.propTypes = ({
   def: PropTypes.object
 })
 
-function Definition({def, ...props}) {
+function DefinitionDocs({def}) {
   return <React.Fragment>
-    <Title def={def} isDefinition {...props} />
     {def.description && !def.extends_base_section &&
       <Compartment title="description">
         <Box marginTop={1} marginBottom={1}>
@@ -503,6 +512,16 @@ function Definition({def, ...props}) {
     }
   </React.Fragment>
 }
+DefinitionDocs.propTypes = {
+  def: PropTypes.object.isRequired
+}
+
+function Definition({def, ...props}) {
+  return <React.Fragment>
+    <Title def={def} isDefinition {...props} />
+    <DefinitionDocs def={def} />
+  </React.Fragment>
+}
 Definition.propTypes = {
   def: PropTypes.object.isRequired
 }
diff --git a/nomad/datamodel/metainfo/nexus.py b/nomad/datamodel/metainfo/nexus.py
index e2b03ebc3a3b983b16a16d38a5502e815124b212..f8655b562be8e3ee64fe6ed26fadfec8de052750 100644
--- a/nomad/datamodel/metainfo/nexus.py
+++ b/nomad/datamodel/metainfo/nexus.py
@@ -43,6 +43,19 @@ _definition_sections: Dict[str, Section] = dict()
 _xml_parent_map: Dict[ET.Element, ET.Element] = None
 _nx_doc_base = 'https://manual.nexusformat.org/classes'
 
+# TODO There are more types in nxdl, but they are not used by the current base classes and
+# application definitions.
+_nx_types = {
+    'NX_FLOAT': np.dtype(np.float64),
+    'NX_CHAR': str,
+    'NX_BOOLEAN': bool,
+    'NX_INT': np.dtype(np.int64),
+    'NX_NUMBER': np.dtype(np.number),
+    'NX_POSINT': np.dtype(np.uint64),
+    'NX_BINARY': Bytes,
+    'NX_DATE_TIME': Datetime
+}
+
 
 def to_camel_case(snake_str: str, upper: bool = False) -> str:
     components = snake_str.split('_')
@@ -69,7 +82,7 @@ def nx_documenation_url(xml_node: ET.Element, nx_type: str):
     return doc_url
 
 
-def get_section(name: str, **kwargs) -> Section:
+def get_or_create_section(name: str, **kwargs) -> Section:
     '''
     Returns the 'existing' metainfo section for a given top-level nexus base-class name.
 
@@ -82,34 +95,48 @@ def get_section(name: str, **kwargs) -> Section:
         section.more.update(**kwargs)
         return section
 
-    section = Section(validate=validate, name=name, more=kwargs)
+    section = Section(validate=validate, name=name, **kwargs)
     current_package.section_definitions.append(section)
     _definition_sections[section.name] = section
 
     return section
 
 
-def add_definition_properties(xml_node: ET.Element, definition: Definition, nx_type: str = None):
+def get_enum(xml_node: ET.Element):
+    enumeration = xml_node.find('nx:enumeration', xml_namespaces)
+    if enumeration is not None:
+        enum_values = []
+        for enum_value in enumeration.findall('nx:item', xml_namespaces):
+            enum_values.append(enum_value.attrib['value'])
+        return MEnum(*enum_values)
+    return None
+
+
+def add_common_properties(xml_node: ET.Element, definition: Definition):
     '''
-    Adds general metainfo definition properties (e.g. name, deprecated, description)
+    Adds general metainfo definition properties (e.g. deprecated, docs, optional, ...)
     from the given nexus XML node to the given metainfo definition.
     '''
+    nx_kind = definition.more.get('nx_kind')
     xml_attrs = xml_node.attrib
 
-    if 'name' in xml_attrs:
-        name = xml_attrs['name']
-        if nx_type and nx_type != 'class':
-            name = f'nx_{nx_type}_{name}'
-        definition.name = name
+    # Read properties from potential base section. Those are not inherited, but we
+    # duplicate them for a nicer presentation
+    if isinstance(definition, Section) and len(definition.base_sections) > 0:
+        base_section = definition.base_sections[0]
+        if base_section.description:
+            definition.description = base_section.description
+        if base_section.deprecated:
+            definition.deprecated = base_section.deprecated
+        if len(base_section.more) > 0:
+            definition.more.update(**base_section.more)
 
-    # Add a link to the nexus classes documentation
     links = []
-    if nx_type is not None:
-        doc_url = nx_documenation_url(xml_node, nx_type)
+    if nx_kind is not None:
+        doc_url = nx_documenation_url(xml_node, nx_kind)
         if doc_url:
             links.append(doc_url)
 
-    # Read additional urls from the XML doc element
     doc = xml_node.find('nx:doc', xml_namespaces)
     if doc is not None and doc.text is not None:
         definition.description = strip(doc.text)
@@ -134,17 +161,7 @@ def add_definition_properties(xml_node: ET.Element, definition: Definition, nx_t
     if 'recommended' in xml_attrs:
         definition.more['nx_recommended'] = xml_attrs['recommended']
 
-    # TODO there are probably even more nxdl attributes
-
-
-def get_enum(xml_node: ET.Element):
-    enumeration = xml_node.find('nx:enumeration', xml_namespaces)
-    if enumeration is not None:
-        enum_values = []
-        for enum_value in enumeration.findall('nx:item', xml_namespaces):
-            enum_values.append(enum_value.attrib['value'])
-        return MEnum(*enum_values)
-    return None
+    # TODO there are probably even more nxdl attributes?
 
 
 def add_attributes(xml_node: ET.Element, section: Section):
@@ -156,54 +173,84 @@ def add_attributes(xml_node: ET.Element, section: Section):
         type: Any = get_enum(xml_node)
         if type is None:
             type = str
-        quantity = Quantity(type=type, nx_kind='attribute')
-        add_definition_properties(attribute, quantity)
+        quantity = Quantity(type=type, nx_kind='attribute', name=attribute.attrib['name'])
+        add_common_properties(attribute, quantity)
         section.quantities.append(quantity)
 
 
-# TODO There are more types in nxdl, but they are not used by the current base classes and
-# application definitions.
-_nx_types = {
-    'NX_FLOAT': np.dtype(np.float64),
-    'NX_CHAR': str,
-    'NX_BOOLEAN': bool,
-    'NX_INT': np.dtype(np.int64),
-    'NX_NUMBER': np.dtype(np.number),
-    'NX_POSINT': np.dtype(np.uint64),
-    'NX_BINARY': Bytes,
-    'NX_DATE_TIME': Datetime
-}
+def add_group_properties(xml_node: ET.Element, section: Section):
+    '''
+    Adds all properties that can be generated from the given nexus group XML node to
+    the given (empty) metainfo section definition.
+    '''
+    for group in xml_node.findall('nx:group', xml_namespaces):
+        group_section = create_group_section(group)
+        section.inner_section_definitions.append(group_section)
+
+        if 'name' in group.attrib:
+            name = f'nx_group_{group.attrib["name"]}'
+        else:
+            name = group.attrib['type'].replace('NX', 'nx_group_')
+
+        max_occurs = group.attrib.get('maxOccurs', '0')
+        repeats = max_occurs == 'unbounded' or int(max_occurs) > 1
+        section.sub_sections.append(SubSection(
+            section_def=group_section, nx_kind='group', name=name, repeats=repeats))
+
+    for field in xml_node.findall('nx:field', xml_namespaces):
+        field_section = create_field_section(field)
+        section.inner_section_definitions.append(field_section)
+
+        section.sub_sections.append(SubSection(
+            section_def=field_section, nx_kind='field',
+            name=f'nx_field_{field.attrib["name"]}'))
+
+    add_attributes(xml_node, section)
 
 
-def section_from_field(xml_node: ET.Element) -> Section:
+def add_template_properties(xml_node: ET.Element, section: Section):
     '''
-    Generates a metainfo section for the given nexus field XML node.
+    Adds potential abilities of a group or field section to act as a TEMPLATE or
+    nameType="any" definition.
     '''
-    xml_attrs = xml_node.attrib
-    nx_name = xml_attrs['name']
-    name = to_camel_case(nx_name, True) + 'Field'
-    section = Section(validate=validate, name=name, more=dict(nx_kind='field'))
-    if nx_name.lower() != nx_name:
+    is_template = section.name.lower() != section.name or xml_node.attrib.get('nameType', '') == 'any'
+    if is_template:
         section.quantities.append(Quantity(
             name='nx_name', type=str, description='''
                 This is a nexus template property. This quantity holds the actual name used
                 in the nexus data.'''))
-    value = Quantity(name='nx_value', description='The value for this nexus field')
-    section.quantities.append(value)
+
+
+def create_field_section(xml_node: ET.Element):
+    '''
+    Creates a metainfo section from the nexus field given as xml node.
+    '''
+    xml_attrs = xml_node.attrib
+
+    assert 'name' in xml_attrs, 'field has not name'
+    field_section = Section(
+        validate=validate, nx_kind='field',
+        name=to_camel_case(xml_attrs['name'], True) + 'Field')
+
+    add_template_properties(xml_node, field_section)
+
+    value_quantity = Quantity(name='nx_value', description='The value for this nexus field')
+    field_section.quantities.append(value_quantity)
 
     if 'type' in xml_attrs:
         nx_type = xml_attrs['type']
         if nx_type not in _nx_types:
             raise NotImplementedError(f'type {nx_type} is not supported')
-        value.type = _nx_types[nx_type]
+        value_quantity.type = _nx_types[nx_type]
+        field_section.more['nx_type'] = nx_type
     else:
-        value.type = get_enum(xml_node)
-        if value.type is None:
-            value.type = Any
+        value_quantity.type = get_enum(xml_node)
+        if value_quantity.type is None:
+            value_quantity.type = Any
 
-    if 'unit' in xml_attrs:
-        # TODO map unit
-        pass
+    if 'units' in xml_attrs:
+        field_section.more['nx_units'] = xml_attrs['units']
+        # TODO map unit to value
 
     dimensions = xml_node.find('nx:dimensions', xml_namespaces)
     if dimensions is not None:
@@ -215,90 +262,60 @@ def section_from_field(xml_node: ET.Element) -> Section:
             except ValueError:
                 pass
             shape.append(dimension_value)
-        value.shape = shape
+        value_quantity.shape = shape
 
-    add_attributes(xml_node, section)
+    add_common_properties(xml_node, field_section)
+    add_attributes(xml_node, field_section)
 
-    return section
+    return field_section
 
 
-def add_group_properties(xml_node: ET.Element, definition_section: Section):
+def create_group_section(xml_node: ET.Element) -> Section:
     '''
-    Adds all properties that can be generated from the given nexus group XML node to
-    the given (empty) metainfo section definition.
+    Creates a metainfo section from the nexus group given as xml node.
     '''
-    add_attributes(xml_node, definition_section)
-
-    for group in xml_node.findall('nx:group', xml_namespaces):
-        assert 'type' in group.attrib, 'group has not type'
-
-        type = group.attrib['type']
-        base_section = get_section(type)
-        empty_definition = len(group) == 0 or (
-            len(group) == 1 and group.find('nx:doc', xml_namespaces) is not None)
-        if empty_definition:
-            # The group does not define anything new, we can directly use the base definition
-            group_section = base_section
-        else:
-            if 'name' in group.attrib:
-                name = to_camel_case(group.attrib['name'], True) + 'Group'
-            else:
-                name = to_camel_case(type, True) + 'Group'
-
-            group_section = Section(validate=validate, name=name)
-            group_section.base_sections = [base_section]
-            definition_section.inner_section_definitions.append(group_section)
-            add_group_properties(group, group_section)
-
-        sub_section = SubSection(section_def=group_section, nx_kind='group')
-        add_definition_properties(group, sub_section, nx_type='group')
-        if sub_section.name is None:
-            sub_section.name = type.replace('NX', 'nx_group_')
-        definition_section.sub_sections.append(sub_section)
+    xml_attrs = xml_node.attrib
+    type = xml_attrs['type']
 
-    for field in xml_node.findall('nx:field', xml_namespaces):
-        assert 'name' in field.attrib, 'field has not name'
+    if 'name' in xml_attrs:
+        name = to_camel_case(xml_attrs['name'], True) + 'Group'
+    else:
+        name = to_camel_case(type, True) + 'Group'
 
-        field_section = section_from_field(field)
-        definition_section.inner_section_definitions.append(field_section)
+    group_section = Section(
+        validate=validate, nx_kind='group', name=name,
+        base_sections=[get_or_create_section(type)])
 
-        more = dict(nx_kind='field')
-        more.update(**{
-            f'nx_{key}': field.attrib[key]
-            for key in ['type', 'units'] if key in field.attrib})
-        field_sub_section = SubSection(section_def=field_section, **more)
-        add_definition_properties(field, field_sub_section, nx_type='field')
-        definition_section.sub_sections.append(field_sub_section)
+    add_common_properties(xml_node, group_section)
+    add_template_properties(xml_node, group_section)
+    add_group_properties(xml_node, group_section)
 
-    return definition_section
+    return group_section
 
 
-def section_from_class(nxdl_file: str):
+def create_class_section(xml_node: ET.Element) -> Section:
     '''
-    Creates a metainfo section from the top-level nexus group definition in the given
-    nxdl file and adds it to the current metainfo package.
+    Creates a metainfo section from the top-level nexus definition given as xml node.
     '''
-    xml_tree = ET.parse(nxdl_file)
-    definition = xml_tree.getroot()
-    xml_attrs = definition.attrib
-    global _xml_parent_map
-    _xml_parent_map = {child: parent for parent in xml_tree.iter() for child in parent}
-
-    assert xml_attrs.get('type') == 'group', 'definition is not a group'
+    xml_attrs = xml_node.attrib
     assert 'name' in xml_attrs
 
-    definition_section = get_section(xml_attrs['name'], nx_kind=xml_attrs['type'])
+    class_section = get_or_create_section(xml_attrs['name'], nx_kind=xml_attrs['type'])
+
     if 'extends' in xml_attrs:
-        base_section = get_section(xml_attrs['extends'])
-        definition_section.base_sections = [base_section]
-    add_group_properties(definition, definition_section)
-    add_definition_properties(definition, definition_section, nx_type='class')
+        base_section = get_or_create_section(xml_attrs['extends'])
+        class_section.base_sections = [base_section]
+
+    add_common_properties(xml_node, class_section)
+    add_group_properties(xml_node, class_section)
 
+    return class_section
 
-def package_from_directory(path: str, package_name: str) -> Package:
+
+def create_package_from_nxdl_directory(path: str, package_name: str) -> Package:
     '''
-    Creates a metainfo package from the given nexus directory. Will the respective
-    metainfo definitions generated from all the nxdl files in that directory.
+    Creates a metainfo package from the given nexus directory. Will generate the respective
+    metainfo definitions from all the nxdl files in that directory.
     '''
     global current_package
     current_package = Package(name=package_name)
@@ -308,8 +325,19 @@ def package_from_directory(path: str, package_name: str) -> Package:
             continue
 
         try:
-            section_from_class(
-                os.path.join(path, nxdl_file))
+            nxdl_path = os.path.join(path, nxdl_file)
+            xml_tree = ET.parse(nxdl_path)
+            xml_node = xml_tree.getroot()
+
+            global _xml_parent_map
+            _xml_parent_map = {child: parent for parent in xml_tree.iter() for child in parent}
+
+            assert xml_node.attrib.get('type') == 'group', 'definition is not a group'
+
+            # The section gets already implicitly added to current_package by
+            # get_or_create_section
+            create_class_section(xml_node)
+
         except Exception as e:
             print(f'Exception while mapping {nxdl_file}', file=sys.stderr)
             raise e
@@ -327,7 +355,7 @@ nx_definitions_path = os.path.join(
 packages: List[Package] = []
 for nx_package in ['base_classes', 'applications']:
     path = os.path.join(nx_definitions_path, nx_package)
-    packages.append(package_from_directory(path, f'nexus_{nx_package}'))
+    packages.append(create_package_from_nxdl_directory(path, f'nexus_{nx_package}'))
 # TODO there are problems generating with nx_package='contributed_definitions'
 
 
diff --git a/tests/metainfo/test_metainfo.py b/tests/metainfo/test_metainfo.py
index 217454d6f7d310b830ed7e55ce9772a6a4cfb58d..aabab5c27982c83d0991e0750c925b630be2a844 100644
--- a/tests/metainfo/test_metainfo.py
+++ b/tests/metainfo/test_metainfo.py
@@ -318,11 +318,15 @@ class TestM2:
         class TestSection(MSection):
             m_def = Section(this_does_not_exist_in_metainfo='value')
             test_quantity = Quantity(type=str, also_no_metainfo_quantity=1, one_more=False)
+            test_delayed_more_quantity = Quantity(type=str)
             another_test_quantity = Quantity(type=str)
 
+        TestSection.test_delayed_more_quantity.more = dict(one_more='test')
+
         assert TestSection.m_def.more['this_does_not_exist_in_metainfo'] == 'value'
         assert TestSection.test_quantity.more['also_no_metainfo_quantity'] == 1
         assert not TestSection.test_quantity.more['one_more']
+        assert TestSection.test_delayed_more_quantity.more['one_more'] == 'test'
         assert len(TestSection.another_test_quantity.more) == 0
 
         assert TestSection.m_def.this_does_not_exist_in_metainfo == 'value'