diff --git a/.cruft.json b/.cruft.json
new file mode 100644
index 0000000..68e4237
--- /dev/null
+++ b/.cruft.json
@@ -0,0 +1,26 @@
+{
+  "template": "https://github.com/FAIRmat-NFDI/cookiecutter-nomad-plugin",
+  "commit": "dbf41935075d9057d69478db6eb9e7901bb44992",
+  "checkout": null,
+  "context": {
+    "cookiecutter": {
+      "full_name": "Alvin Noe Ladines",
+      "email": "ladinesa@physik.hu-berlin.de",
+      "github_username": "ladinesa",
+      "plugin_name": "nomad-simulation-workflow",
+      "module_name": "nomad_simulation_workflow",
+      "short_description": "Schema definition and normalizer for NOMAD simulation workflow",
+      "version": "0.1.0",
+      "license": "Apache Software License 2.0",
+      "include_schema_package": true,
+      "include_normalizer": true,
+      "include_parser": false,
+      "include_app": false,
+      "_copy_without_render": [
+        "*.html"
+      ],
+      "_template": "https://github.com/FAIRmat-NFDI/cookiecutter-nomad-plugin"
+    }
+  },
+  "directory": null
+}
diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml
new file mode 100644
index 0000000..544ec7a
--- /dev/null
+++ b/.github/workflows/actions.yml
@@ -0,0 +1,56 @@
+name: install-and-test-workflow
+on: [push]
+jobs:
+  install-and-test:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v4
+    - name: Set up Python 3.9
+      uses: actions/setup-python@v5
+      with:
+        python-version: 3.9
+    - name: Install dependencies
+      run: |
+        pip install --upgrade pip
+        pip install '.[dev]' --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple
+        pip install coverage coveralls
+    - name: Test with pytest
+      run: |
+        python -m coverage run -m pytest -sv
+    - name: Submit to coveralls
+      continue-on-error: true
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      run: |
+        coveralls --service=github
+  build-and-install:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v4
+    - name: Set up Python 3.9
+      uses: actions/setup-python@v5
+      with:
+        python-version: 3.9
+    - name: Build the package
+      run: |
+        pip install --upgrade pip
+        pip install build
+        python -m build --sdist
+    - name: Install the package
+      run: |
+        pip install dist/*.tar.gz --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple
+  ruff-linting:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: chartboost/ruff-action@v1
+        with:
+          args: "check ."
+  # to enable auto-formatting check, uncomment the following lines below
+  # ruff-formatting:
+  #   runs-on: ubuntu-latest
+  #   steps:
+  #     - uses: actions/checkout@v4
+  #     - uses: chartboost/ruff-action@v1
+  #       with:
+  #         args: "format . --check"
diff --git a/.github/workflows/cruft-update.yml b/.github/workflows/cruft-update.yml
new file mode 100644
index 0000000..ace73a7
--- /dev/null
+++ b/.github/workflows/cruft-update.yml
@@ -0,0 +1,75 @@
+# /.github/workflows/cruft-update.yml
+name: Update repository with Cruft
+permissions:
+  contents: write
+  pull-requests: write
+on:
+  schedule:
+    - cron: "0 14 * * 1" # Every Monday at 2pm (UTC time)
+  workflow_dispatch:
+jobs:
+  update:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: true
+      matrix:
+        include:
+          - add-paths: .
+            body: Use this to merge the changes to this repository.
+            branch: cruft/update
+            commit-message: "chore: accept new Cruft update"
+            title: New updates detected with Cruft
+          - add-paths: .cruft.json
+            body: Use this to reject the changes in this repository.
+            branch: cruft/reject
+            commit-message: "chore: reject new Cruft update"
+            title: Reject new updates detected with Cruft
+    steps:
+      - uses: actions/checkout@v3
+
+      - uses: actions/setup-python@v4
+        with:
+          python-version: "3.10"
+
+      - name: Install Cruft
+        run: pip3 install cruft
+
+      - name: Check if update is available
+        continue-on-error: false
+        id: check
+        run: |
+          CHANGES=0
+          if [ -f .cruft.json ]; then
+            if ! cruft check; then
+              CHANGES=1
+            fi
+          else
+            echo "No .cruft.json file"
+          fi
+
+          echo "has_changes=$CHANGES" >> "$GITHUB_OUTPUT"
+
+      - name: Run update if available
+        if: steps.check.outputs.has_changes == '1'
+        run: |
+          git config --global user.email "you@example.com"
+          git config --global user.name "GitHub"
+
+          cruft update --skip-apply-ask --refresh-private-variables
+          git restore --staged .
+
+      - name: Create pull request
+        if: steps.check.outputs.has_changes == '1'
+        uses: peter-evans/create-pull-request@v4
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          add-paths: ${{ matrix.add-paths }}
+          commit-message: ${{ matrix.commit-message }}
+          branch: ${{ matrix.branch }}
+          delete-branch: true
+          branch-suffix: timestamp
+          title: ${{ matrix.title }}
+          body: |
+            This is an autogenerated PR. ${{ matrix.body }}
+
+            [Cruft](https://cruft.github.io/cruft/) has detected updates from the Cookiecutter repository.
diff --git a/.github/workflows/mkdocs-deploy.yml b/.github/workflows/mkdocs-deploy.yml
new file mode 100644
index 0000000..c46ff23
--- /dev/null
+++ b/.github/workflows/mkdocs-deploy.yml
@@ -0,0 +1,24 @@
+name: Deploy MkDocs Site
+
+on:
+  push:
+    branches:
+      - main # Triggers deployment on push to the main branch
+ 
+permissions:
+  contents: write
+
+jobs:
+  deploy:
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: Checkout Repository
+        uses: actions/checkout@v4
+
+      - name: Deploy docs
+        uses: mhausenblas/mkdocs-deploy-gh-pages@master
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          CONFIG_FILE: mkdocs.yml
+          REQUIREMENTS: requirements_docs.txt
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b1619d4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,130 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+.python-version
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+#   However, in case of collaboration, if having platform-specific dependencies or dependencies
+#   having no cross-platform support, pipenv may install dependencies that don't work, or not
+#   install all needed dependencies.
+#Pipfile.lock
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+.pyenv
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..0c8648f
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,21 @@
+{
+  "editor.rulers": [
+    90
+  ],
+  "editor.renderWhitespace": "all",
+  "editor.tabSize": 4,
+  "files.trimTrailingWhitespace": true,
+  "[python]": {
+    "editor.formatOnSave": true,
+    "editor.codeActionsOnSave": {
+      "source.fixAll": "explicit",
+      "source.organizeImports": "explicit"
+    },
+    "editor.defaultFormatter": "charliermarsh.ruff"
+  },
+  "python.testing.pytestArgs": [
+    "tests"
+  ],
+  "python.testing.unittestEnabled": false,
+  "python.testing.pytestEnabled": true
+}
diff --git a/LICENSE b/LICENSE
index 261eeb9..427417b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,3 +1,4 @@
+
                                  Apache License
                            Version 2.0, January 2004
                         http://www.apache.org/licenses/
@@ -178,7 +179,7 @@
    APPENDIX: How to apply the Apache License to your work.
 
       To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
+      boilerplate notice, with the fields enclosed by brackets "{}"
       replaced with your own identifying information. (Don't include
       the brackets!)  The text should be enclosed in the appropriate
       comment syntax for the file format. We also recommend that a
@@ -186,7 +187,7 @@
       same "printed page" as the copyright notice for easier
       identification within third-party archives.
 
-   Copyright [yyyy] [name of copyright owner]
+   Copyright {yyyy} {name of copyright owner}
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..b5ccc2d
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+recursive-include * nomad_plugin.yaml
diff --git a/README.md b/README.md
index fcf513e..cd279e7 100644
--- a/README.md
+++ b/README.md
@@ -1,84 +1,93 @@
-# nomad-plugin-template
-A template repository for creating a repository with a NOMAD plugin package.
+# nomad-nomad-simulation-workflow
 
+Schema definition and normalizer for NOMAD simulation workflow
 
-## Getting started
+----
 
-1. Click on the `Use this template` button and create a new plugin repository. The form will ask you to fill out the name for the new plugin repository.
+This `nomad`_ plugin was generated with `Cookiecutter`_ along with `@nomad`_'s `cookiecutter-nomad-plugin`_ template.
 
-2. In the newly created repository, start a new Github Codespace and generate the plugin structure.
 
-Run the following command to create a new NOMAD plugin project using cookiecutter-nomad-plugin:
+### Install
+
+You should create a virtual environment. You will need the `nomad-lab` package (and `pytest`).
+We recommend using Python 3.9.
 
 ```sh
-cruft create https://github.com/FAIRmat-NFDI/cookiecutter-nomad-plugin
+python3 -m venv .pyenv
+source .pyenv/bin/activate
+pip install --upgrade pip
+pip install -e '.[dev]' --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple
 ```
 
-Cookiecutter prompts you for information regarding your plugin:
-
-```no-highlight
-full_name [John Doe]: Citizen Kane
-email [john.doe@physik.hu-berlin.de]: citizen@kane.de
-github_username [foo]: kane
-plugin_name [foobar]: awesome-tools
-module_name [awesome_tools]: awesome_tools
-short_description [NOMAD example template]: An awesome plugin for NOMAD
-version [0.1.0]:
-Select license:
-1 - MIT
-2 - BSD-3
-3 - GNU GPL v3.0+
-Choose from 1, 2, 3 [1]: 2
-include_schema_package [y/n] (y): y
-include_normalizer [y/n] (y): n
-include_parser [y/n] (y): y
-include_app [y/n] (y): n
-
-INFO:post_gen_project:Initializing python for package - src
-..
-INFO:post_gen_project:Remove temporary folder: licenses
-INFO:post_gen_project:Remove temporary folder: macros
-INFO:post_gen_project:Remove temporary folder: py_sources
+**Note!**
+Until we have an official pypi NOMAD release with the plugins functionality. Make
+sure to include NOMAD's internal package registry (e.g. via `--index-url`).
+
+### Testing
+
+You can run automated tests with `pytest`:
+
+```sh
+pytest -svx tests
 ```
 
+### Run linting
+
+```sh
+ruff check .
+```
 
+### Run auto-formatting
 
+This is entirely optional. To add this as a check in github actions pipeline, uncomment the `ruff-formatting` step in `./github/workflows/actions.yaml`.
 
-There you go - you just created a minimal NOMAD plugin:
-
-> [!NOTE]
-> In the above prompt, we pressed `y` for schema_package and parser, this creates a python package with two plugin entry points: one for parser and one for schema_package.
-
-```no-highlight
-nomad-awesome-tools/
-├── LICENSE
-├── README.rst
-├── pyproject.toml
-├── move_template_files.sh
-├── src
-│   └── nomad_awesome_tools
-│       ├── __init__.py
-|       ├── schema_packages
-│       |   ├── __init__.py
-│       |   └── plugin.py
-|       └── parsers
-│           ├── __init__.py
-│           └── plugin.py
-|
-├── tests
-│   ├── conftest.py
-│   └── test_awesome.py
-└── MANIFEST.in
+```sh
+ruff format .
 ```
 
+### Developing a NOMAD plugin
+
+Follow the [guide](https://nomad-lab.eu/prod/v1/staging/docs/howto/plugins/plugins.html) on how to develop NOMAD plugins.
+
+### Build the python package
 
-> [!NOTE]
-> The project `nomad-awesome-tools` is created in a new directory, we have included a helper script to move all the files to the parent level of the repository.
+The `pyproject.toml` file contains everything that is necessary to turn the project
+into a pip installable python package. Run the python build tool to create a package distribution:
+
+```
+pip install build
+python -m build --sdist
+```
 
+You can install the package with pip:
+
+```
+pip install dist/nomad-nomad-simulation-workflow-0.1.0
+```
+
+Read more about python packages, `pyproject.toml`, and how to upload packages to PyPI
+on the [PyPI documentation](https://packaging.python.org/en/latest/tutorials/packaging-projects/).
+
+### Documentation on Github pages
+
+To deploy documentation on Github pages, make sure to [enable GitHub pages via the repo settings](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-from-a-branch). 
+
+To view the documentation locally, install the documentation related packages using:
 
 ```sh
-sh CHANGE_TO_PLUGIN_NAME/move_template_files.sh
+pip install -r requirements_docs.txt
 ```
 
-> [!IMPORTANT]
-> The `CHANGE_TO_PLUGIN_NAME` should be substituted by the name of the plugin you've created. In the above case it'll be `sh nomad-awesome-tools/move_template_files.sh`. 
+Run the documentation server:
+```sh
+mkdocs serve
+```
+
+### Template update
+
+We use cruft to update the project based on template changes. A `cruft-update.yml` is included in Github workflows to automatically check for updates and create pull requests to apply updates. Follow the [instructions](https://github.blog/changelog/2022-05-03-github-actions-prevent-github-actions-from-creating-and-approving-pull-requests/) on how to enable Github Actions to create pull requests. 
+
+To run the check for updates locally, follow the instructions on [`cruft` website](https://cruft.github.io/cruft/#updating-a-project).
+
+### License
+Distributed under the terms of the `Apache Software License 2.0`_ license, "nomad-nomad-simulation-workflow" is free and open source software
diff --git a/docs/assets/.gitignore b/docs/assets/.gitignore
new file mode 100644
index 0000000..3881e38
--- /dev/null
+++ b/docs/assets/.gitignore
@@ -0,0 +1 @@
+nomad-oasis*.zip
\ No newline at end of file
diff --git a/docs/assets/favicon.png b/docs/assets/favicon.png
new file mode 100644
index 0000000..f84c78f
Binary files /dev/null and b/docs/assets/favicon.png differ
diff --git a/docs/assets/nomad-plugin-logo.png b/docs/assets/nomad-plugin-logo.png
new file mode 100644
index 0000000..149856c
Binary files /dev/null and b/docs/assets/nomad-plugin-logo.png differ
diff --git a/docs/explanation/explanation.md b/docs/explanation/explanation.md
new file mode 100644
index 0000000..a2035f6
--- /dev/null
+++ b/docs/explanation/explanation.md
@@ -0,0 +1,4 @@
+# Explanation
+
+!!! note "Attention"
+    TODO
diff --git a/docs/how_to/contribute_to_the_documentation.md b/docs/how_to/contribute_to_the_documentation.md
new file mode 100644
index 0000000..173dce1
--- /dev/null
+++ b/docs/how_to/contribute_to_the_documentation.md
@@ -0,0 +1,4 @@
+# Contribute to the documentation
+
+!!! note "Attention"
+    TODO
diff --git a/docs/how_to/contribute_to_this_plugin.md b/docs/how_to/contribute_to_this_plugin.md
new file mode 100644
index 0000000..48d405a
--- /dev/null
+++ b/docs/how_to/contribute_to_this_plugin.md
@@ -0,0 +1,5 @@
+# Contribute to This Plugin
+
+!!! note "Attention"
+    TODO
+
diff --git a/docs/how_to/install_this_plugin.md b/docs/how_to/install_this_plugin.md
new file mode 100644
index 0000000..2b45e0f
--- /dev/null
+++ b/docs/how_to/install_this_plugin.md
@@ -0,0 +1,4 @@
+# Install This Plugin
+
+!!! note "Attention"
+    TODO
diff --git a/docs/how_to/use_this_plugin.md b/docs/how_to/use_this_plugin.md
new file mode 100644
index 0000000..ad93966
--- /dev/null
+++ b/docs/how_to/use_this_plugin.md
@@ -0,0 +1,10 @@
+# How to Use This Plugin
+
+This plugin can be used in a NOMAD Oasis installation.
+
+## Add This Plugin to Your NOMAD installation
+
+Read the [NOMAD plugin documentation](https://nomad-lab.eu/prod/v1/staging/docs/plugins/plugins.html#add-a-plugin-to-your-nomad) for all details on how to deploy the plugin on your NOMAD instance.
+
+!!! note "Attention"
+    TODO
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..225769b
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,48 @@
+# Welcome to the `nomad-nomad-simulation-workflow` documentation
+
+Schema definition and normalizer for NOMAD simulation workflow
+
+## Introduction
+
+!!! note "Attention"
+    TODO
+
+<div markdown="block" class="home-grid">
+<div markdown="block">
+
+### Tutorial
+
+TODO
+
+- [Tutorial](tutorial/tutorial.md)
+
+</div>
+<div markdown="block">
+
+### How-to guides
+
+How-to guides provide step-by-step instructions for a wide range of tasks, with the overarching topics:
+
+- [Install this plugin](how_to/install_this_plugin.md)
+- [Use this plugin](how_to/use_this_plugin.md)
+- [Contribute to this plugin](how_to/contribute_to_this_plugin.md)
+- [Contribute to the documentation](how_to/contribute_to_the_documentation.md)
+
+</div>
+
+<div markdown="block">
+
+### Explanation
+
+The explanation [section](explanation/explanation.md) provides background knowledge on this plugin.
+
+</div>
+<div markdown="block">
+
+### Reference
+
+The reference [section](reference/references.md) includes all CLI commands and arguments, all configuration options,
+the possible schema annotations and their arguments, and a glossary of used terms.
+
+</div>
+</div>
diff --git a/docs/reference/references.md b/docs/reference/references.md
new file mode 100644
index 0000000..c199e70
--- /dev/null
+++ b/docs/reference/references.md
@@ -0,0 +1,4 @@
+# References
+
+!!! note "Attention"
+    TODO
diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css
new file mode 100644
index 0000000..321e087
--- /dev/null
+++ b/docs/stylesheets/extra.css
@@ -0,0 +1,69 @@
+
+.md-header__button.md-logo :where(img,svg) {
+    width: 100%;
+    height: 30px;
+}
+
+.md-header, .md-header__inner {
+    background-color: #fff;
+    color: #2A4CDF;
+}
+
+.md-header[data-md-state=shadow] {
+    box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%);
+    transition: box-shadow 200ms linear;
+}
+
+.md-header__inner {
+    height: 80px;
+}
+
+.md-header__topic {
+    font-size: 24px;
+}
+
+.md-footer {
+    background-color: #2A4CDF;
+}
+
+.md-search__form:hover {
+    background-color: rgba(0,0,0,.13);
+}
+
+.md-typeset h1 {
+    color: black;
+    font-weight: 700;
+}
+
+.youtube {
+    position: relative;
+    width: 100%;
+    height: 0;
+    padding-bottom: 56.25%;
+}
+
+.youtube iframe {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+}
+
+.home-grid {
+    display: grid;
+    grid-template-columns: 1fr 1fr;
+    grid-column-gap: 24px;
+    row-gap: 24px;
+}
+
+.home-grid div {
+    border-radius: 4px;
+    padding: 24px;
+    background-color: #f3e9d9;
+}
+
+.home-grid h3 {
+    margin-top: 0;
+    font-weight: 700;
+}
\ No newline at end of file
diff --git a/docs/theme/partials/header.html b/docs/theme/partials/header.html
new file mode 100644
index 0000000..5b091f3
--- /dev/null
+++ b/docs/theme/partials/header.html
@@ -0,0 +1,86 @@
+{#-
+  This file was automatically generated - do not edit
+-#}
+{% set class = "md-header" %}
+{% if "navigation.tabs.sticky" in features %}
+  {% set class = class ~ " md-header--lifted" %}
+{% endif %}
+<header class="{{ class }}" data-md-component="header">
+  <nav class="md-header__inner md-grid" aria-label="{{ lang.t('header.title') }}">
+    <a href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}" title="{{ config.site_name | e }}" class="md-header__button md-logo" aria-label="{{ config.site_name }}" data-md-component="logo">
+      {% include "partials/logo.html" %}
+    </a>
+    <label class="md-header__button md-icon" for="__drawer">
+      {% include ".icons/material/menu" ~ ".svg" %}
+    </label>
+    <div class="md-header__title" data-md-component="header-title">
+      <div class="md-header__ellipsis">
+        <div class="md-header__topic">
+          <span class="md-ellipsis">
+            {{ config.site_name }}
+          </span>
+        </div>
+        <div class="md-header__topic" data-md-component="header-topic">
+          <span class="md-ellipsis">
+            {% if page and page.meta and page.meta.title %}
+              {{ page.meta.title }}
+            {% else %}
+              {{ page.title }}
+            {% endif %}
+          </span>
+        </div>
+      </div>
+    </div>
+    {% if not config.theme.palette is mapping %}
+      <form class="md-header__option" data-md-component="palette">
+        {% for option in config.theme.palette %}
+          {% set primary = option.primary | replace(" ", "-") | lower %}
+          {% set accent  = option.accent  | replace(" ", "-") | lower %}
+          <input class="md-option" data-md-color-media="{{ option.media }}" data-md-color-scheme="{{ option.scheme }}" data-md-color-primary="{{ primary }}" data-md-color-accent="{{ accent }}" {% if option.toggle %} aria-label="{{ option.toggle.name }}" {% else %} aria-hidden="true" {% endif %} type="radio" name="__palette" id="__palette_{{ loop.index }}">
+          {% if option.toggle %}
+            <label class="md-header__button md-icon" title="{{ option.toggle.name }}" for="__palette_{{ loop.index0 or loop.length }}" hidden>
+              {% include ".icons/" ~ option.toggle.icon ~ ".svg" %}
+            </label>
+          {% endif %}
+        {% endfor %}
+      </form>
+    {% endif %}
+    {% if config.extra.alternate %}
+      <div class="md-header__option">
+        <div class="md-select">
+          {% set icon = config.theme.icon.alternate or "material/translate" %}
+          <button class="md-header__button md-icon" aria-label="{{ lang.t('select.language.title') }}">
+            {% include ".icons/" ~ icon ~ ".svg" %}
+          </button>
+          <div class="md-select__inner">
+            <ul class="md-select__list">
+              {% for alt in config.extra.alternate %}
+                <li class="md-select__item">
+                  <a href="{{ alt.link | url }}" hreflang="{{ alt.lang }}" class="md-select__link">
+                    {{ alt.name }}
+                  </a>
+                </li>
+                {% endfor %}
+            </ul>
+          </div>
+        </div>
+      </div>
+    {% endif %}
+    {% if "search" in config["plugins"] %}
+      <label class="md-header__button md-icon" for="__search">
+        {% include ".icons/material/magnify.svg" %}
+      </label>
+      {% include "partials/search.html" %}
+    {% endif %}
+    {% if config.repo_url %}
+      <div class="md-header__source">
+        {% include "partials/source.html" %}
+      </div>
+    {% endif %}
+  </nav>
+  {% if "navigation.tabs.sticky" in features %}
+    {% if "navigation.tabs" in features %}
+      {% include "partials/tabs.html" %}
+    {% endif %}
+  {% endif %}
+</header>
\ No newline at end of file
diff --git a/docs/tutorial/tutorial.md b/docs/tutorial/tutorial.md
new file mode 100644
index 0000000..a24d72a
--- /dev/null
+++ b/docs/tutorial/tutorial.md
@@ -0,0 +1,4 @@
+# Tutorial
+
+!!! note "Attention"
+    TODO
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 0000000..85020f0
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,57 @@
+site_name: nomad-nomad-simulation-workflow
+site_description: Schema definition and normalizer for NOMAD simulation workflow
+site_author: Alvin Noe Ladines
+
+repo_url: https://github.com/ladinesa/nomad-nomad-simulation-workflow
+
+nav:
+  - Home: index.md
+  - Tutorial: tutorial/tutorial.md
+  - How-to guides:
+      - Install this Plugin: how_to/install_this_plugin.md
+      - Use this Plugin: how_to/use_this_plugin.md
+      - Contribute to this plugin: how_to/contribute_to_this_plugin.md
+      - Contribute to the documentation: how_to/contribute_to_the_documentation.md
+  - Explanation: explanation/explanation.md
+  - Reference: reference/references.md
+plugins:
+  - search
+theme:
+  name: material
+  palette:
+    primary: "#2A4CDF"
+    accent: "#008A67"
+  font:
+    text: "Titillium Web"
+  logo: assets/nomad-plugin-logo.png
+  favicon: assets/favicon.png
+  features:
+    - navigation.instant
+  custom_dir: docs/theme
+markdown_extensions:
+  - attr_list
+  - md_in_html
+  - admonition
+  - pymdownx.details
+  - pymdownx.highlight:
+      anchor_linenums: true
+  - pymdownx.inlinehilite
+  - pymdownx.snippets
+  - pymdownx.superfences
+  - toc:
+      permalink: True
+  - pymdownx.arithmatex:
+      generic: true
+  - attr_list
+  - mkdocs-click
+  - pymdownx.extra
+extra:
+  generator: false
+  homepage: https://nomad-lab.eu
+use_directory_urls: false
+extra_css:
+  - stylesheets/extra.css
+extra_javascript:
+  - javascript.js
+  - https://polyfill.io/v3/polyfill.min.js?features=es6
+  - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
diff --git a/move_template_files.sh b/move_template_files.sh
new file mode 100644
index 0000000..41d6aae
--- /dev/null
+++ b/move_template_files.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+rsync -avh nomad-nomad-simulation-workflow/ .
+rm -rfv nomad-nomad-simulation-workflow
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..34fbd5a
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,114 @@
+[build-system]
+requires = ["setuptools>=61.0.0", "setuptools-scm>=8.0"]
+build-backend = "setuptools.build_meta"
+
+[project]
+classifiers = [
+    "Intended Audience :: Developers",
+    "Operating System :: OS Independent",
+    "Programming Language :: Python",
+    "Programming Language :: Python :: 3.9",
+    "Programming Language :: Python :: 3.10",
+    "Programming Language :: Python :: 3.11",
+    "Programming Language :: Python :: 3.12",
+    "License :: OSI Approved :: Apache Software License",
+]
+name = "nomad-nomad-simulation-workflow"
+description = "Schema definition and normalizer for NOMAD simulation workflow"
+version = "0.1.0"
+readme = "README.rst"
+requires-python = ">=3.9"
+authors = [
+    { name = "Alvin Noe Ladines", email = "ladinesa@physik.hu-berlin.de" },
+]
+maintainers = [
+    { name = "Alvin Noe Ladines", email = "ladinesa@physik.hu-berlin.de" },
+]
+license = { file = "LICENSE" }
+dependencies = ["nomad-lab>=1.2.2dev578"]
+
+[project.urls]
+Repository = "https://github.com/ladinesa/nomad-nomad-simulation-workflow"
+
+[project.optional-dependencies]
+dev = ["ruff", "pytest", "structlog"]
+
+[tool.ruff]
+# Exclude a variety of commonly ignored directories.
+exclude = [
+    ".bzr",
+    ".direnv",
+    ".eggs",
+    ".git",
+    ".git-rewrite",
+    ".hg",
+    ".mypy_cache",
+    ".nox",
+    ".pants.d",
+    ".pytype",
+    ".ruff_cache",
+    ".svn",
+    ".tox",
+    ".venv",
+    "__pypackages__",
+    "_build",
+    "buck-out",
+    "build",
+    "dist",
+    "node_modules",
+    "venv",
+]
+
+# Same as Black.
+line-length = 88
+indent-width = 4
+
+
+[tool.ruff.lint]
+select = [
+    # pycodestyle
+    "E",
+    # Pyflakes
+    "F",
+    # pyupgrade
+    "UP",
+    # isort
+    "I",
+    # pylint 
+    "PL",
+]
+
+ignore = [
+    "F403", # 'from module import *' used; unable to detect undefined names
+]
+
+fixable = ["ALL"]
+
+# Allow unused variables when underscore-prefixed.
+dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
+
+# this is entirely optional, you can remove this if you wish to
+[tool.ruff.format]
+# use single quotes for strings.
+quote-style = "single"
+
+# indent with spaces, rather than tabs.
+indent-style = "space"
+
+# Like Black, respect magic trailing commas.
+skip-magic-trailing-comma = false
+
+# Like Black, automatically detect the appropriate line ending.
+line-ending = "auto"
+
+[tool.setuptools]
+package-dir = { "" = "src" }
+
+[tool.setuptools.packages.find]
+where = ["src"]
+
+[project.entry-points.'nomad.plugin']
+
+mypackage = "nomad_nomad_simulation_workflow.schema_packages:mypackage"
+mynormalizer = "nomad_nomad_simulation_workflow.normalizers:mynormalizer"
+
diff --git a/requirements_docs.txt b/requirements_docs.txt
new file mode 100644
index 0000000..bacf1ed
--- /dev/null
+++ b/requirements_docs.txt
@@ -0,0 +1,4 @@
+mkdocs
+mkdocs-material==8.1.1
+pymdown-extensions
+mkdocs-click
diff --git a/src/nomad_nomad_simulation_workflow/__init__.py b/src/nomad_nomad_simulation_workflow/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/nomad_nomad_simulation_workflow/normalizers/__init__.py b/src/nomad_nomad_simulation_workflow/normalizers/__init__.py
new file mode 100644
index 0000000..4286579
--- /dev/null
+++ b/src/nomad_nomad_simulation_workflow/normalizers/__init__.py
@@ -0,0 +1,17 @@
+from nomad.config.models.plugins import NormalizerEntryPoint
+from pydantic import Field
+
+
+class MyNormalizerEntryPoint(NormalizerEntryPoint):
+    parameter: int = Field(0, description='Custom configuration parameter')
+
+    def load(self):
+        from nomad_nomad_simulation_workflow.normalizers.mynormalizer import MyNormalizer
+
+        return MyNormalizer(**self.dict())
+
+
+mynormalizer = MyNormalizerEntryPoint(
+    name='MyNormalizer',
+    description='Normalizer defined using the new plugin mechanism.',
+)
diff --git a/src/nomad_nomad_simulation_workflow/normalizers/mynormalizer.py b/src/nomad_nomad_simulation_workflow/normalizers/mynormalizer.py
new file mode 100644
index 0000000..fce0ce6
--- /dev/null
+++ b/src/nomad_nomad_simulation_workflow/normalizers/mynormalizer.py
@@ -0,0 +1,26 @@
+from typing import (
+    TYPE_CHECKING,
+)
+
+if TYPE_CHECKING:
+    from nomad.datamodel.datamodel import (
+        EntryArchive,
+    )
+    from structlog.stdlib import (
+        BoundLogger,
+    )
+
+from nomad.config import config
+from nomad.normalizing import Normalizer
+
+configuration = config.get_plugin_entry_point(
+    'nomad_nomad_simulation_workflow.normalizers:mynormalizer'
+)
+
+
+class MyNormalizer(Normalizer):
+    def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
+        super().normalize(archive, logger)
+        logger.info('MyNormalizer.normalize', parameter=configuration.parameter)
+        if archive.results and archive.results.material:
+            archive.results.material.elements = ['C', 'O']
diff --git a/src/nomad_nomad_simulation_workflow/schema_packages/__init__.py b/src/nomad_nomad_simulation_workflow/schema_packages/__init__.py
new file mode 100644
index 0000000..16e8ee1
--- /dev/null
+++ b/src/nomad_nomad_simulation_workflow/schema_packages/__init__.py
@@ -0,0 +1,17 @@
+from nomad.config.models.plugins import SchemaPackageEntryPoint
+from pydantic import Field
+
+
+class MySchemaPackageEntryPoint(SchemaPackageEntryPoint):
+    parameter: int = Field(0, description='Custom configuration parameter')
+
+    def load(self):
+        from nomad_nomad_simulation_workflow.schema_packages.mypackage import m_package
+ 
+        return m_package
+
+
+mypackage = MySchemaPackageEntryPoint(
+    name='MyPackage',
+    description='Schema package defined using the new plugin mechanism.',
+)
diff --git a/src/nomad_nomad_simulation_workflow/schema_packages/mypackage.py b/src/nomad_nomad_simulation_workflow/schema_packages/mypackage.py
new file mode 100644
index 0000000..a5ecd7e
--- /dev/null
+++ b/src/nomad_nomad_simulation_workflow/schema_packages/mypackage.py
@@ -0,0 +1,38 @@
+from typing import (
+    TYPE_CHECKING,
+)
+
+if TYPE_CHECKING:
+    from nomad.datamodel.datamodel import (
+        EntryArchive,
+    )
+    from structlog.stdlib import (
+        BoundLogger,
+    )
+
+from nomad.config import config
+from nomad.datamodel.data import Schema
+from nomad.datamodel.metainfo.annotations import ELNAnnotation, ELNComponentEnum
+from nomad.metainfo import Quantity, SchemaPackage
+
+configuration = config.get_plugin_entry_point(
+    'nomad_nomad_simulation_workflow.schema_packages:mypackage'
+)
+
+m_package = SchemaPackage()
+
+
+class MySchema(Schema):
+    name = Quantity(
+        type=str, a_eln=ELNAnnotation(component=ELNComponentEnum.StringEditQuantity)
+    )
+    message = Quantity(type=str)
+
+    def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
+        super().normalize(archive, logger)
+
+        logger.info('MySchema.normalize', parameter=configuration.parameter)
+        self.message = f'Hello {self.name}!'
+
+
+m_package.__init_metainfo__()
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/data/.gitkeep b/tests/data/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/data/test.archive.yaml b/tests/data/test.archive.yaml
new file mode 100644
index 0000000..2158710
--- /dev/null
+++ b/tests/data/test.archive.yaml
@@ -0,0 +1,3 @@
+data:
+  m_def: nomad_nomad_simulation_workflow.schema_packages.mypackage.MySchema
+  name: Markus
diff --git a/tests/normalizers/test_normalizer.py b/tests/normalizers/test_normalizer.py
new file mode 100644
index 0000000..4e1b058
--- /dev/null
+++ b/tests/normalizers/test_normalizer.py
@@ -0,0 +1,12 @@
+from nomad.client import normalize_all
+from nomad.datamodel import EntryArchive, EntryMetadata
+from nomad.datamodel.metainfo.workflow import Workflow
+
+
+def test_normalizer():
+    entry_archive = EntryArchive(
+        metadata=EntryMetadata(), workflow2=Workflow(name='test')
+    )
+    normalize_all(entry_archive)
+
+    assert entry_archive.workflow2.name == 'test'
diff --git a/tests/schema_packages/test_schema.py b/tests/schema_packages/test_schema.py
new file mode 100644
index 0000000..76210db
--- /dev/null
+++ b/tests/schema_packages/test_schema.py
@@ -0,0 +1,11 @@
+import os.path
+
+from nomad.client import normalize_all, parse
+
+
+def test_schema():
+    test_file = os.path.join('tests', 'data', 'test.archive.yaml')
+    entry_archive = parse(test_file)[0]
+    normalize_all(entry_archive)
+
+    assert entry_archive.data.message == 'Hello Markus!'