diff --git a/.github/workflows/pypi-publish.yml b/.github/workflows/pypi-publish.yml
index 5168e16e1621b89e74a658c603ae0d4523e6dc58..52a826735de6feaf858fd3a2fef154065a6e8a53 100644
--- a/.github/workflows/pypi-publish.yml
+++ b/.github/workflows/pypi-publish.yml
@@ -15,7 +15,7 @@ jobs:
       - name: Install dependencies
         run: |
           python -m pip install --upgrade pip
-          pip install setuptools wheel
+          pip install setuptools wheel babel
       - name: Build package
         run: |
           python setup.py compile_catalog sdist bdist_wheel
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 6db598fe3d8f4b2b6741091146aaed0e9513e9cc..4b8f19d4de28124b120c815caf009433afa37510 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -62,13 +62,13 @@ jobs:
       - name: Generate dependencies
         if: ${{ matrix.REQUIREMENTS_LEVEL != 'dev' }}
         run: |
-          python -m pip install --upgrade pip setuptools py wheel requirements-builder
+          pip install wheel requirements-builder
           requirements-builder -e ${{ matrix.EXTRAS }} --level=${{ matrix.REQUIREMENTS_LEVEL }} setup.py > .${{ matrix.REQUIREMENTS_LEVEL }}-${{ matrix.python-version }}-requirements.txt
 
       - name: Generate dependencies devel
         if: ${{ matrix.REQUIREMENTS_LEVEL == 'dev' }}
         run: |
-          python -m pip install --upgrade pip setuptools py wheel requirements-builder
+          pip install wheel requirements-builder
           requirements-builder -e ${{ matrix.EXTRAS }} --level=${{ matrix.REQUIREMENTS_LEVEL }} --req requirements-devel.txt setup.py > .${{ matrix.REQUIREMENTS_LEVEL }}-${{ matrix.python-version }}-requirements.txt
 
       - name: Cache pip
diff --git a/docs/conf.py b/docs/conf.py
index 24d1e62ad485b710f1cab31d3cfc06e97fe20531..f0499db51fb53f047f5606742ba6cc1f88153600 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -8,7 +8,7 @@
 
 """Sphinx configuration."""
 
-import os
+from invenio_utilities_tuw import __version__
 
 import sphinx.environment
 
@@ -56,19 +56,8 @@ author = "TU Wien"
 #
 # The short X.Y version.
 
-# Get the version string. Cannot be done with import!
-g = {}
-with open(
-    os.path.join(
-        os.path.dirname(__file__), "..", "invenio_utilities_tuw", "version.py"
-    ),
-    "rt",
-) as fp:
-    exec(fp.read(), g)
-    version = g["__version__"]
-
 # The full version, including alpha/beta/rc tags.
-release = version
+release = __version__
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/invenio_utilities_tuw/__init__.py b/invenio_utilities_tuw/__init__.py
index 7b63c82f50b26b98eeb9f94ad6d766c223976f70..0a9a847c2b770b3e3f4dee44e97810f573c1acc1 100644
--- a/invenio_utilities_tuw/__init__.py
+++ b/invenio_utilities_tuw/__init__.py
@@ -9,6 +9,7 @@
 """Some utilities for InvenioRDM."""
 
 from .ext import InvenioUtilitiesTUW
-from .version import __version__
+
+__version__ = "2022.2.2"
 
 __all__ = ("__version__", "InvenioUtilitiesTUW")
diff --git a/invenio_utilities_tuw/version.py b/invenio_utilities_tuw/version.py
deleted file mode 100644
index 713e85b8101772d4a8006b78b529fb4d589a0b86..0000000000000000000000000000000000000000
--- a/invenio_utilities_tuw/version.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2020 - 2021 TU Wien.
-#
-# Invenio-Utilities-TUW is free software; you can redistribute it and/or
-# modify it under the terms of the MIT License; see LICENSE file for more
-# details.
-
-"""Version information for Invenio-Utilities-TUW.
-
-This file is imported by ``invenio_utilities_tuw.__init__``,
-and parsed by ``setup.py``.
-"""
-
-__version__ = "2022.2.2"
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000000000000000000000000000000000000..f00e77850c68796aadd5f1c8450816553222feea
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,4 @@
+[build-system]
+requires = ["setuptools", "wheel", "babel>2.8"]
+build-backend = "setuptools.build_meta"
+
diff --git a/setup.cfg b/setup.cfg
index db14031f2ba03cd899d4a096246878f122e798ab..98a5503f3423edd1b3406dc7b2deba27a24d1ecc 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,11 +1,56 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2020 - 2021 TU Wien.
+# Copyright (C) 2020-2022 TU Wien.
 #
 # Invenio-Utilities-TUW is free software; you can redistribute it and/or
 # modify it under the terms of the MIT License; see LICENSE file for more
 # details.
 
+[metadata]
+name = invenio-utilities-tuw
+version = attr: invenio_utilities_tuw.__version__
+description = "Some utilities for InvenioRDM."
+long_description = file: README.rst, CHANGES.rst
+keywords = invenio utilities tu wien
+license = MIT
+author = TU Wien
+author_email = tudata@tuwien.ac.at
+platforms = any
+url = https://gitlab.tuwien.ac.at/fairdata/invenio-utilities-tuw
+classifiers =
+    Environment :: Web Environment
+    License :: OSI Approved :: MIT License
+    Operating System :: OS Independent
+    Topic :: Internet :: WWW/HTTP :: Dynamic Content
+    Topic :: Software Development :: Libraries :: Python Modules
+    Programming Language :: Python
+    Programming Language :: Python 3.7
+    Programming Language :: Python 3.8
+    Programming Language :: Python 3.9
+    Development Status :: 5 - Production/Stable
+
+[options]
+include_package_data = True
+packages = find:
+python_requires = >=3.7
+zip_safe = False
+install_requires =
+    invenio-app-rdm>=9.0.6
+
+[options.extras_require]
+tests =
+    pytest-invenio>=1.4.0
+    Sphinx>=4.2.0
+# Kept for backwards compatibility
+docs =
+
+[options.entry_points]
+flask.commands =
+    tuw = invenio_utilities_tuw.cli:utilities
+invenio_base.apps =
+    invenio_utilities_tuw = invenio_utilities_tuw:InvenioUtilitiesTUW
+invenio_i18n.translations =
+    messages = invenio_utilities_tuw
 
 [build_sphinx]
 source-dir = docs/
diff --git a/setup.py b/setup.py
index 81ad2e589d3be1360de15065f8ef447e85854e52..cc2a7c68650d4fff3786c420c7a628640e430cb4 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2020 - 2021 TU Wien.
+# Copyright (C) 2020-2022 TU Wien.
 #
 # Invenio-Utilities-TUW is free software; you can redistribute it and/or
 # modify it under the terms of the MIT License; see LICENSE file for more
@@ -8,83 +8,6 @@
 
 """Some utilities for InvenioRDM."""
 
-import os
+from setuptools import setup
 
-from setuptools import find_packages, setup
-
-readme = open("README.rst").read()
-history = open("CHANGES.rst").read()
-
-tests_require = [
-    "pytest-invenio>=1.4.0",
-]
-
-extras_require = {
-    "docs": [
-        "Sphinx>=4.2.0",
-    ],
-    "tests": tests_require,
-}
-
-extras_require["all"] = []
-for reqs in extras_require.values():
-    extras_require["all"].extend(reqs)
-
-setup_requires = [
-    "Babel>=2.8",
-]
-
-install_requires = [
-    "invenio-app-rdm>=9.0.6",
-]
-
-packages = find_packages()
-
-
-# Get the version string. Cannot be done with import!
-g = {}
-with open(os.path.join("invenio_utilities_tuw", "version.py"), "rt") as fp:
-    exec(fp.read(), g)
-    version = g["__version__"]
-
-setup(
-    name="invenio-utilities-tuw",
-    version=version,
-    description=__doc__,
-    long_description=readme + "\n\n" + history,
-    keywords="invenio utilities tu wien",
-    license="MIT",
-    author="TU Wien",
-    author_email="tudata@tuwien.ac.at",
-    url="https://gitlab.tuwien.ac.at/fairdata/invenio-utilities-tuw",
-    packages=packages,
-    zip_safe=False,
-    include_package_data=True,
-    platforms="any",
-    entry_points={
-        "flask.commands": ["tuw = invenio_utilities_tuw.cli:utilities"],
-        "invenio_base.apps": [
-            "invenio_utilities_tuw = invenio_utilities_tuw:InvenioUtilitiesTUW",
-        ],
-        "invenio_i18n.translations": [
-            "messages = invenio_utilities_tuw",
-        ],
-    },
-    extras_require=extras_require,
-    install_requires=install_requires,
-    setup_requires=setup_requires,
-    tests_require=tests_require,
-    classifiers=[
-        "Environment :: Web Environment",
-        "Intended Audience :: Developers",
-        "License :: OSI Approved :: MIT License",
-        "Operating System :: OS Independent",
-        "Programming Language :: Python",
-        "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
-        "Topic :: Software Development :: Libraries :: Python Modules",
-        "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.8",
-        "Programming Language :: Python :: 3.9",
-        "Development Status :: 4 - Beta",
-    ],
-)
+setup()