diff --git a/docs/plugins.md b/docs/plugins.md
index 795cabc0054121b6f38e329bcffdf8423aa40ba2..d733a06ee8866a5a2cd408902709a59776f84674 100644
--- a/docs/plugins.md
+++ b/docs/plugins.md
@@ -94,7 +94,7 @@ code. This also means that the package has to be in your `PYTHONPATH` (see below
 
 
 {{pydantic_model('nomad.config.plugins.Schema', heading='### Parser plugin metadata')}}
-{{pydantic_model('nomad.config.plugins.Parser', heading='### Schema plugin metadata')}}
+{{pydantic_model('nomad.config.plugins.Parser', heading='### Schema plugin metadata', hide=['code_name','code_category','code_homepage','metadata'])}}
 
 Now follow the instructions for one of our examples and try for yourself:
 
diff --git a/examples/plugins/parser b/examples/plugins/parser
index 5059c528828875b94210f7130eed0670372ae46f..4fb997b669bc802a8ead1d1ed7f78e255687c599 160000
--- a/examples/plugins/parser
+++ b/examples/plugins/parser
@@ -1 +1 @@
-Subproject commit 5059c528828875b94210f7130eed0670372ae46f
+Subproject commit 4fb997b669bc802a8ead1d1ed7f78e255687c599
diff --git a/examples/plugins/schema b/examples/plugins/schema
index b6642e43b768a01aa5ded08af56980e144d204c1..c6ba2ce8b842df5e29c6a3a8e1ce080c0c260163 160000
--- a/examples/plugins/schema
+++ b/examples/plugins/schema
@@ -1 +1 @@
-Subproject commit b6642e43b768a01aa5ded08af56980e144d204c1
+Subproject commit c6ba2ce8b842df5e29c6a3a8e1ce080c0c260163
diff --git a/nomad/config/plugins.py b/nomad/config/plugins.py
index 6e8a46e4f72a5a60a464dc8a3269c975d5788aa7..f60b847b5f59ba0561a3e21f742ce088fa5da143 100644
--- a/nomad/config/plugins.py
+++ b/nomad/config/plugins.py
@@ -33,8 +33,8 @@ class PluginBase(BaseModel):
     This should not be used. Plugins should instantiate concrete Plugin models like
     Parser or Schema.
     '''
-    name: str
-    description: Optional[str]
+    name: str = Field(description='A short descriptive human readable name for the plugin.')
+    description: Optional[str] = Field(description='A human readable description of the plugin.')
 
 
 class PythonPluginBase(PluginBase):
@@ -42,8 +42,8 @@ class PythonPluginBase(PluginBase):
     A base model for NOMAD plugins that are implemented in Python.
     '''
     python_package: str = Field(description='''
-        Name of the python package that contains the plugin code and an optional
-        plugin metadata file `nomad_plugin.yaml`.
+        Name of the python package that contains the plugin code and a
+        plugin metadata file called `nomad_plugin.yaml`.
     ''')
 
     @classmethod
@@ -89,7 +89,9 @@ class Schema(PythonPluginBase):
     '''
     A Schema describes a NOMAD Python schema that can be loaded as a plugin.
     '''
-    plugin_type: Literal['schema'] = 'schema'
+    plugin_type: Literal['schema'] = Field('schema', description='''
+        The type of the plugin. This has to be the string `schema` for schema plugins.
+    ''')
 
 
 class Parser(PythonPluginBase):
@@ -113,23 +115,14 @@ class Parser(PythonPluginBase):
     #      abstract is_mainfile, which does not allow to separate parser implementation and plugin
     #      definition.
 
-    plugin_type: Literal['parser'] = 'parser'
+    plugin_type: Literal['parser'] = Field('parser', description='''
+        The type of the plugin. This has to be the string `parser` for parser plugins.
+    ''')
 
-    code_name: Optional[str]
-    code_homepage: Optional[str]
-    code_category: Optional[str]
-    mainfile_contents_re: Optional[str]
-    mainfile_binary_header: Optional[bytes]
-    mainfile_binary_header_re: Optional[bytes]
-    mainfile_mime_re: str = Field(r'text/.*')
-    mainfile_name_re: str = Field(r'.*')
-    mainfile_alternative: bool = False
-    mainfile_contents_dict: Optional[dict]
-    domain: str = Field('dft')
-    supported_compressions: List[str] = Field([])
-    metadata: Optional[dict] = Field(description='''
-        Metadata passed to the UI. Deprecated. ''')
-    parser_class_name: str
+    parser_class_name: str = Field(description='''
+        The fully qualified name of the Python class that implements the parser.
+        This class must have a function `def parse(self, mainfile, archive, logger)`.
+    ''')
     parser_as_interface: bool = Field(False, description='''
         By default the parser metadata from this config (and the loaded nomad_plugin.yaml)
         is used to instantiate a parser interface that is lazy loading the actual parser
@@ -139,6 +132,49 @@ class Parser(PythonPluginBase):
         parser class directly for parsing and matching.
     ''')
 
+    mainfile_contents_re: Optional[str] = Field(description='''
+        A regular expression that is applied the content of a potential mainfile.
+        If this expression is given, the parser is only considered for a file, if the
+        expression matches.
+    ''')
+    mainfile_name_re: str = Field(r'.*', description='''
+        A regular expression that is applied the name of a potential mainfile.
+        If this expression is given, the parser is only considered for a file, if the
+        expression matches.
+    ''')
+    mainfile_mime_re: str = Field(r'text/.*', description='''
+        A regular expression that is applied the mime type of a potential mainfile.
+        If this expression is given, the parser is only considered for a file, if the
+        expression matches.
+    ''')
+    mainfile_binary_header: Optional[bytes] = Field(description='''
+        Matches a binary file if the given bytes are included in the file.
+    ''')
+    mainfile_binary_header_re: Optional[bytes] = Field(description='''
+        Matches a binary file if the given binary regular expression bytes matches the
+        file contents.
+    ''')
+    mainfile_alternative: bool = Field(False, description='''
+        If True, the parser only matches a file, if no other file in the same directory
+        matches a parser.
+    ''')
+    mainfile_contents_dict: Optional[dict] = Field(description='''
+        Is used to match structured data files like JSON or HDF5.
+    ''')
+    supported_compressions: List[str] = Field([], description='''
+        Files compressed with the given formats (e.g. xz, gz) are uncompressed and
+        matched like normal files.
+    ''')
+    domain: str = Field('dft', description='''
+        The domain value `dft` will apply all normalizers for atomistic codes. Deprecated.
+    ''')
+
+    code_name: Optional[str]
+    code_homepage: Optional[str]
+    code_category: Optional[str]
+    metadata: Optional[dict] = Field(description='''
+        Metadata passed to the UI. Deprecated. ''')
+
     def create_matching_parser_interface(self):
         if self.parser_as_interface:
             from nomad.parsing.parser import import_class
diff --git a/nomad/mkdocs.py b/nomad/mkdocs.py
index d31128e9a709e17c795256b9de662f60a12edbc6..c8cd069534fbc9bdd9b4e2d5f15742e0106514ce 100644
--- a/nomad/mkdocs.py
+++ b/nomad/mkdocs.py
@@ -294,7 +294,7 @@ def define_env(env):
 
         return results
 
-    def pydantic_model_from_model(model, name=None, heading=None):
+    def pydantic_model_from_model(model, name=None, heading=None, hide=[]):
         fields = model.__fields__
         required_models = set()
         if not name:
@@ -340,7 +340,7 @@ def define_env(env):
 
         result += '|name|type| |\n'
         result += '|----|----|-|\n'
-        result += ''.join([field_row(field) for field in fields.values()])
+        result += ''.join([field_row(field) for field in fields.values() if field.name not in hide])
 
         for required_model in required_models:
             if required_model.__name__ not in exported_config_models:
@@ -350,7 +350,7 @@ def define_env(env):
         return result
 
     @env.macro
-    def pydantic_model(path, heading=None):  # pylint: disable=unused-variable
+    def pydantic_model(path, heading=None, hide=[]):  # pylint: disable=unused-variable
         '''
         Produces markdown code for the given pydantic model.
 
@@ -363,4 +363,4 @@ def define_env(env):
         module = importlib.import_module(module_name)
         model = getattr(module, name)
 
-        return pydantic_model_from_model(model, heading=heading)
+        return pydantic_model_from_model(model, heading=heading, hide=hide)